From a175314c3e5827eb193872241446f2f8f5c9d33c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 20:07:14 +0200 Subject: Adding upstream version 1:10.5.12. Signed-off-by: Daniel Baumann --- storage/mroonga/vendor/groonga/lib/CMakeLists.txt | 185 + storage/mroonga/vendor/groonga/lib/Makefile.am | 99 + storage/mroonga/vendor/groonga/lib/alloc.c | 961 + storage/mroonga/vendor/groonga/lib/arrow.cpp | 849 + storage/mroonga/vendor/groonga/lib/c_sources.am | 112 + storage/mroonga/vendor/groonga/lib/cache.c | 1036 + storage/mroonga/vendor/groonga/lib/column.c | 49 + storage/mroonga/vendor/groonga/lib/com.c | 1202 + storage/mroonga/vendor/groonga/lib/command.c | 201 + storage/mroonga/vendor/groonga/lib/config.c | 289 + storage/mroonga/vendor/groonga/lib/cpp_sources.am | 3 + storage/mroonga/vendor/groonga/lib/ctx.c | 1873 + storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c | 324 + storage/mroonga/vendor/groonga/lib/dat.cpp | 1338 + storage/mroonga/vendor/groonga/lib/dat/Makefile.am | 11 + storage/mroonga/vendor/groonga/lib/dat/array.hpp | 98 + storage/mroonga/vendor/groonga/lib/dat/base.hpp | 67 + storage/mroonga/vendor/groonga/lib/dat/block.hpp | 94 + storage/mroonga/vendor/groonga/lib/dat/check.hpp | 149 + .../vendor/groonga/lib/dat/cursor-factory.cpp | 92 + .../vendor/groonga/lib/dat/cursor-factory.hpp | 44 + storage/mroonga/vendor/groonga/lib/dat/cursor.hpp | 46 + storage/mroonga/vendor/groonga/lib/dat/dat.hpp | 248 + storage/mroonga/vendor/groonga/lib/dat/entry.hpp | 59 + .../mroonga/vendor/groonga/lib/dat/file-impl.cpp | 279 + .../mroonga/vendor/groonga/lib/dat/file-impl.hpp | 73 + storage/mroonga/vendor/groonga/lib/dat/file.cpp | 73 + storage/mroonga/vendor/groonga/lib/dat/file.hpp | 60 + storage/mroonga/vendor/groonga/lib/dat/header.hpp | 179 + .../mroonga/vendor/groonga/lib/dat/id-cursor.cpp | 184 + .../mroonga/vendor/groonga/lib/dat/id-cursor.hpp | 83 + .../mroonga/vendor/groonga/lib/dat/key-cursor.cpp | 349 + .../mroonga/vendor/groonga/lib/dat/key-cursor.hpp | 88 + storage/mroonga/vendor/groonga/lib/dat/key.hpp | 110 + storage/mroonga/vendor/groonga/lib/dat/node.hpp | 127 + .../vendor/groonga/lib/dat/predictive-cursor.cpp | 206 + .../vendor/groonga/lib/dat/predictive-cursor.hpp | 84 + .../vendor/groonga/lib/dat/prefix-cursor.cpp | 175 + .../vendor/groonga/lib/dat/prefix-cursor.hpp | 78 + storage/mroonga/vendor/groonga/lib/dat/sources.am | 29 + storage/mroonga/vendor/groonga/lib/dat/string.hpp | 173 + storage/mroonga/vendor/groonga/lib/dat/trie.cpp | 1225 + storage/mroonga/vendor/groonga/lib/dat/trie.hpp | 285 + storage/mroonga/vendor/groonga/lib/dat/vector.hpp | 191 + storage/mroonga/vendor/groonga/lib/db.c | 14054 ++++ storage/mroonga/vendor/groonga/lib/dump.c | 112 + storage/mroonga/vendor/groonga/lib/error.c | 454 + storage/mroonga/vendor/groonga/lib/expr.c | 9294 +++ storage/mroonga/vendor/groonga/lib/expr_code.c | 55 + storage/mroonga/vendor/groonga/lib/expr_executor.c | 945 + storage/mroonga/vendor/groonga/lib/file_lock.c | 121 + storage/mroonga/vendor/groonga/lib/file_reader.c | 109 + storage/mroonga/vendor/groonga/lib/geo.c | 2788 + storage/mroonga/vendor/groonga/lib/grn.h | 759 + storage/mroonga/vendor/groonga/lib/grn_alloc.h | 163 + storage/mroonga/vendor/groonga/lib/grn_cache.h | 49 + storage/mroonga/vendor/groonga/lib/grn_com.h | 250 + storage/mroonga/vendor/groonga/lib/grn_config.h | 37 + storage/mroonga/vendor/groonga/lib/grn_ctx.h | 501 + storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h | 237 + .../mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h | 35 + storage/mroonga/vendor/groonga/lib/grn_dat.h | 95 + storage/mroonga/vendor/groonga/lib/grn_db.h | 493 + .../mroonga/vendor/groonga/lib/grn_ecmascript.c | 2542 + .../mroonga/vendor/groonga/lib/grn_ecmascript.h | 74 + .../vendor/groonga/lib/grn_ecmascript.lemon | 581 + storage/mroonga/vendor/groonga/lib/grn_error.h | 34 + storage/mroonga/vendor/groonga/lib/grn_expr.h | 86 + storage/mroonga/vendor/groonga/lib/grn_expr_code.h | 33 + .../mroonga/vendor/groonga/lib/grn_expr_executor.h | 39 + storage/mroonga/vendor/groonga/lib/grn_file_lock.h | 48 + storage/mroonga/vendor/groonga/lib/grn_geo.h | 200 + storage/mroonga/vendor/groonga/lib/grn_hash.h | 378 + storage/mroonga/vendor/groonga/lib/grn_ii.h | 192 + .../mroonga/vendor/groonga/lib/grn_index_column.h | 34 + storage/mroonga/vendor/groonga/lib/grn_io.h | 487 + storage/mroonga/vendor/groonga/lib/grn_load.h | 47 + storage/mroonga/vendor/groonga/lib/grn_logger.h | 35 + storage/mroonga/vendor/groonga/lib/grn_mrb.h | 42 + storage/mroonga/vendor/groonga/lib/grn_msgpack.h | 46 + storage/mroonga/vendor/groonga/lib/grn_nfkc.h | 39 + .../mroonga/vendor/groonga/lib/grn_normalizer.h | 42 + storage/mroonga/vendor/groonga/lib/grn_obj.h | 32 + storage/mroonga/vendor/groonga/lib/grn_output.h | 127 + storage/mroonga/vendor/groonga/lib/grn_pat.h | 129 + storage/mroonga/vendor/groonga/lib/grn_plugin.h | 62 + storage/mroonga/vendor/groonga/lib/grn_proc.h | 152 + .../mroonga/vendor/groonga/lib/grn_raw_string.h | 62 + storage/mroonga/vendor/groonga/lib/grn_report.h | 47 + .../vendor/groonga/lib/grn_request_canceler.h | 28 + .../mroonga/vendor/groonga/lib/grn_request_timer.h | 28 + storage/mroonga/vendor/groonga/lib/grn_rset.h | 114 + storage/mroonga/vendor/groonga/lib/grn_scanner.h | 40 + storage/mroonga/vendor/groonga/lib/grn_scorer.h | 49 + storage/mroonga/vendor/groonga/lib/grn_scorers.h | 31 + storage/mroonga/vendor/groonga/lib/grn_snip.h | 125 + storage/mroonga/vendor/groonga/lib/grn_store.h | 216 + storage/mroonga/vendor/groonga/lib/grn_str.h | 116 + storage/mroonga/vendor/groonga/lib/grn_string.h | 51 + storage/mroonga/vendor/groonga/lib/grn_time.h | 40 + .../mroonga/vendor/groonga/lib/grn_token_cursor.h | 81 + .../mroonga/vendor/groonga/lib/grn_tokenizers.h | 38 + storage/mroonga/vendor/groonga/lib/grn_ts.h | 48 + storage/mroonga/vendor/groonga/lib/grn_util.h | 49 + .../vendor/groonga/lib/grn_window_function.h | 40 + .../vendor/groonga/lib/grn_window_functions.h | 26 + storage/mroonga/vendor/groonga/lib/grn_windows.h | 33 + storage/mroonga/vendor/groonga/lib/hash.c | 3720 + storage/mroonga/vendor/groonga/lib/icudump.c | 298 + storage/mroonga/vendor/groonga/lib/id.c | 36 + storage/mroonga/vendor/groonga/lib/ii.c | 12816 +++ storage/mroonga/vendor/groonga/lib/index_column.c | 194 + storage/mroonga/vendor/groonga/lib/io.c | 2201 + storage/mroonga/vendor/groonga/lib/load.c | 1229 + storage/mroonga/vendor/groonga/lib/logger.c | 810 + storage/mroonga/vendor/groonga/lib/metadata.rc.in | 28 + storage/mroonga/vendor/groonga/lib/mrb.c | 220 + storage/mroonga/vendor/groonga/lib/mrb/Makefile.am | 21 + .../mroonga/vendor/groonga/lib/mrb/mrb_accessor.c | 121 + .../mroonga/vendor/groonga/lib/mrb/mrb_accessor.h | 33 + storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c | 92 + storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h | 32 + storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c | 373 + storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h | 41 + storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.c | 130 + storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.h | 33 + .../mroonga/vendor/groonga/lib/mrb/mrb_column.c | 173 + .../mroonga/vendor/groonga/lib/mrb/mrb_column.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_command.c | 196 + .../mroonga/vendor/groonga/lib/mrb/mrb_command.h | 34 + .../vendor/groonga/lib/mrb/mrb_command_input.c | 139 + .../vendor/groonga/lib/mrb/mrb_command_input.h | 32 + .../vendor/groonga/lib/mrb/mrb_command_version.c | 41 + .../vendor/groonga/lib/mrb/mrb_command_version.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_config.c | 90 + .../mroonga/vendor/groonga/lib/mrb/mrb_config.h | 31 + .../vendor/groonga/lib/mrb/mrb_content_type.c | 49 + .../vendor/groonga/lib/mrb/mrb_content_type.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_converter.c | 350 + .../mroonga/vendor/groonga/lib/mrb/mrb_converter.h | 64 + storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c | 838 + storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h | 33 + .../mroonga/vendor/groonga/lib/mrb/mrb_database.c | 206 + .../mroonga/vendor/groonga/lib/mrb/mrb_database.h | 32 + .../vendor/groonga/lib/mrb/mrb_double_array_trie.c | 60 + .../vendor/groonga/lib/mrb/mrb_double_array_trie.h | 32 + storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c | 202 + storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h | 32 + .../vendor/groonga/lib/mrb/mrb_eval_context.c | 98 + .../vendor/groonga/lib/mrb/mrb_eval_context.h | 32 + storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c | 1079 + storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h | 43 + .../vendor/groonga/lib/mrb/mrb_fixed_size_column.c | 59 + .../vendor/groonga/lib/mrb/mrb_fixed_size_column.h | 32 + .../vendor/groonga/lib/mrb/mrb_hash_table.c | 117 + .../vendor/groonga/lib/mrb/mrb_hash_table.h | 32 + storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c | 79 + storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h | 32 + .../vendor/groonga/lib/mrb/mrb_index_column.c | 199 + .../vendor/groonga/lib/mrb/mrb_index_column.h | 32 + .../vendor/groonga/lib/mrb/mrb_index_cursor.c | 245 + .../vendor/groonga/lib/mrb/mrb_index_cursor.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_indexable.c | 170 + .../mroonga/vendor/groonga/lib/mrb/mrb_indexable.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_logger.c | 99 + .../mroonga/vendor/groonga/lib/mrb/mrb_logger.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_object.c | 346 + .../mroonga/vendor/groonga/lib/mrb/mrb_object.h | 34 + .../vendor/groonga/lib/mrb/mrb_object_flags.c | 96 + .../vendor/groonga/lib/mrb/mrb_object_flags.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_operator.c | 155 + .../mroonga/vendor/groonga/lib/mrb/mrb_operator.h | 34 + .../mroonga/vendor/groonga/lib/mrb/mrb_options.c | 39 + .../mroonga/vendor/groonga/lib/mrb/mrb_options.h | 38 + .../vendor/groonga/lib/mrb/mrb_patricia_trie.c | 59 + .../vendor/groonga/lib/mrb/mrb_patricia_trie.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_pointer.c | 77 + .../mroonga/vendor/groonga/lib/mrb/mrb_pointer.h | 31 + .../mroonga/vendor/groonga/lib/mrb/mrb_procedure.c | 108 + .../mroonga/vendor/groonga/lib/mrb/mrb_procedure.h | 32 + .../vendor/groonga/lib/mrb/mrb_query_logger.c | 76 + .../vendor/groonga/lib/mrb/mrb_query_logger.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_record.c | 162 + .../mroonga/vendor/groonga/lib/mrb/mrb_record.h | 31 + storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c | 493 + storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h | 32 + .../vendor/groonga/lib/mrb/mrb_table_cursor.c | 208 + .../vendor/groonga/lib/mrb/mrb_table_cursor.h | 32 + .../groonga/lib/mrb/mrb_table_cursor_flags.c | 60 + .../groonga/lib/mrb/mrb_table_cursor_flags.h | 32 + .../vendor/groonga/lib/mrb/mrb_table_group_flags.c | 48 + .../vendor/groonga/lib/mrb/mrb_table_group_flags.h | 32 + .../groonga/lib/mrb/mrb_table_group_result.c | 254 + .../groonga/lib/mrb/mrb_table_group_result.h | 31 + .../vendor/groonga/lib/mrb/mrb_table_sort_flags.c | 42 + .../vendor/groonga/lib/mrb/mrb_table_sort_flags.h | 31 + .../vendor/groonga/lib/mrb/mrb_table_sort_key.c | 159 + .../vendor/groonga/lib/mrb/mrb_table_sort_key.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_thread.c | 46 + .../mroonga/vendor/groonga/lib/mrb/mrb_thread.h | 32 + storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c | 60 + storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h | 32 + .../groonga/lib/mrb/mrb_variable_size_column.c | 60 + .../groonga/lib/mrb/mrb_variable_size_column.h | 32 + storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c | 59 + storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h | 32 + .../vendor/groonga/lib/mrb/mrb_window_definition.c | 164 + .../vendor/groonga/lib/mrb/mrb_window_definition.h | 32 + .../mroonga/vendor/groonga/lib/mrb/mrb_writer.c | 253 + .../mroonga/vendor/groonga/lib/mrb/mrb_writer.h | 32 + .../vendor/groonga/lib/mrb/scripts/Makefile.am | 16 + .../vendor/groonga/lib/mrb/scripts/accessor.rb | 5 + .../groonga/lib/mrb/scripts/backtrace_entry.rb | 28 + .../vendor/groonga/lib/mrb/scripts/command.rb | 64 + .../groonga/lib/mrb/scripts/command_input.rb | 15 + .../lib/mrb/scripts/command_line/Makefile.am | 9 + .../groonga/lib/mrb/scripts/command_line/grndb.rb | 452 + .../lib/mrb/scripts/command_line/sources.am | 2 + .../groonga/lib/mrb/scripts/command_line_parser.rb | 168 + .../vendor/groonga/lib/mrb/scripts/context.rb | 85 + .../groonga/lib/mrb/scripts/context/Makefile.am | 9 + .../groonga/lib/mrb/scripts/context/error_level.rb | 30 + .../vendor/groonga/lib/mrb/scripts/context/rc.rb | 205 + .../groonga/lib/mrb/scripts/context/sources.am | 3 + .../vendor/groonga/lib/mrb/scripts/database.rb | 65 + .../vendor/groonga/lib/mrb/scripts/error.rb | 16 + .../vendor/groonga/lib/mrb/scripts/eval_context.rb | 18 + .../vendor/groonga/lib/mrb/scripts/expression.rb | 68 + .../groonga/lib/mrb/scripts/expression_rewriter.rb | 22 + .../lib/mrb/scripts/expression_rewriters.rb | 41 + .../lib/mrb/scripts/expression_size_estimator.rb | 54 + .../groonga/lib/mrb/scripts/expression_tree.rb | 9 + .../lib/mrb/scripts/expression_tree/Makefile.am | 9 + .../lib/mrb/scripts/expression_tree/accessor.rb | 14 + .../scripts/expression_tree/binary_operation.rb | 67 + .../lib/mrb/scripts/expression_tree/constant.rb | 22 + .../mrb/scripts/expression_tree/function_call.rb | 66 + .../mrb/scripts/expression_tree/index_column.rb | 14 + .../scripts/expression_tree/logical_operation.rb | 33 + .../lib/mrb/scripts/expression_tree/options.rb | 14 + .../lib/mrb/scripts/expression_tree/procedure.rb | 18 + .../lib/mrb/scripts/expression_tree/sources.am | 10 + .../lib/mrb/scripts/expression_tree/variable.rb | 18 + .../lib/mrb/scripts/expression_tree_builder.rb | 111 + .../groonga/lib/mrb/scripts/fixed_size_column.rb | 5 + .../mroonga/vendor/groonga/lib/mrb/scripts/id.rb | 12 + .../vendor/groonga/lib/mrb/scripts/index_column.rb | 39 + .../vendor/groonga/lib/mrb/scripts/index_cursor.rb | 18 + .../vendor/groonga/lib/mrb/scripts/index_info.rb | 10 + .../groonga/lib/mrb/scripts/initialize/Makefile.am | 9 + .../groonga/lib/mrb/scripts/initialize/post.rb | 28 + .../groonga/lib/mrb/scripts/initialize/pre.rb | 3 + .../groonga/lib/mrb/scripts/initialize/sources.am | 3 + .../vendor/groonga/lib/mrb/scripts/logger.rb | 34 + .../groonga/lib/mrb/scripts/logger/Makefile.am | 9 + .../vendor/groonga/lib/mrb/scripts/logger/level.rb | 40 + .../groonga/lib/mrb/scripts/logger/sources.am | 2 + .../vendor/groonga/lib/mrb/scripts/object.rb | 18 + .../vendor/groonga/lib/mrb/scripts/operator.rb | 22 + .../groonga/lib/mrb/scripts/plugin_loader.rb | 14 + .../vendor/groonga/lib/mrb/scripts/query_logger.rb | 9 + .../lib/mrb/scripts/query_logger/Makefile.am | 9 + .../groonga/lib/mrb/scripts/query_logger/flag.rb | 39 + .../lib/mrb/scripts/query_logger/sources.am | 2 + .../vendor/groonga/lib/mrb/scripts/record.rb | 38 + .../vendor/groonga/lib/mrb/scripts/require.rb | 71 + .../vendor/groonga/lib/mrb/scripts/scan_info.rb | 38 + .../groonga/lib/mrb/scripts/scan_info_builder.rb | 577 + .../groonga/lib/mrb/scripts/scan_info_data.rb | 324 + .../mrb/scripts/scan_info_data_size_estimator.rb | 185 + .../lib/mrb/scripts/scan_info_search_index.rb | 9 + .../vendor/groonga/lib/mrb/scripts/sources.am | 37 + .../vendor/groonga/lib/mrb/scripts/table.rb | 144 + .../vendor/groonga/lib/mrb/scripts/table_cursor.rb | 28 + .../lib/mrb/scripts/variable_size_column.rb | 5 + .../vendor/groonga/lib/mrb/scripts/writer.rb | 21 + storage/mroonga/vendor/groonga/lib/mrb/sources.am | 93 + .../vendor/groonga/lib/nfkc-custom-rules.txt | 1 + storage/mroonga/vendor/groonga/lib/nfkc.c | 45 + storage/mroonga/vendor/groonga/lib/nfkc.rb | 897 + storage/mroonga/vendor/groonga/lib/nfkc50.c | 77784 +++++++++++++++++++ storage/mroonga/vendor/groonga/lib/normalizer.c | 1193 + storage/mroonga/vendor/groonga/lib/obj.c | 689 + storage/mroonga/vendor/groonga/lib/operator.c | 1362 + storage/mroonga/vendor/groonga/lib/output.c | 2880 + storage/mroonga/vendor/groonga/lib/pat.c | 3674 + storage/mroonga/vendor/groonga/lib/plugin.c | 1396 + storage/mroonga/vendor/groonga/lib/proc.c | 4211 + .../mroonga/vendor/groonga/lib/proc/Makefile.am | 17 + .../mroonga/vendor/groonga/lib/proc/proc_column.c | 1019 + .../mroonga/vendor/groonga/lib/proc/proc_config.c | 139 + .../mroonga/vendor/groonga/lib/proc/proc_dump.c | 1138 + .../vendor/groonga/lib/proc/proc_fuzzy_search.c | 467 + .../vendor/groonga/lib/proc/proc_highlight.c | 503 + .../vendor/groonga/lib/proc/proc_in_records.c | 519 + .../mroonga/vendor/groonga/lib/proc/proc_lock.c | 172 + .../mroonga/vendor/groonga/lib/proc/proc_object.c | 138 + .../vendor/groonga/lib/proc/proc_object_inspect.c | 614 + .../vendor/groonga/lib/proc/proc_object_list.c | 413 + .../mroonga/vendor/groonga/lib/proc/proc_query.c | 118 + .../vendor/groonga/lib/proc/proc_query_log_flags.c | 220 + .../mroonga/vendor/groonga/lib/proc/proc_schema.c | 1226 + .../mroonga/vendor/groonga/lib/proc/proc_select.c | 3809 + .../mroonga/vendor/groonga/lib/proc/proc_snippet.c | 319 + .../mroonga/vendor/groonga/lib/proc/proc_table.c | 910 + .../vendor/groonga/lib/proc/proc_tokenize.c | 433 + storage/mroonga/vendor/groonga/lib/proc/sources.am | 18 + storage/mroonga/vendor/groonga/lib/raw_string.c | 38 + storage/mroonga/vendor/groonga/lib/report.c | 98 + .../mroonga/vendor/groonga/lib/request_canceler.c | 176 + storage/mroonga/vendor/groonga/lib/request_timer.c | 88 + storage/mroonga/vendor/groonga/lib/rset.c | 324 + storage/mroonga/vendor/groonga/lib/scanner.c | 73 + storage/mroonga/vendor/groonga/lib/scorer.c | 189 + storage/mroonga/vendor/groonga/lib/scorers.c | 96 + storage/mroonga/vendor/groonga/lib/snip.c | 841 + storage/mroonga/vendor/groonga/lib/store.c | 2864 + storage/mroonga/vendor/groonga/lib/str.c | 3276 + storage/mroonga/vendor/groonga/lib/string.c | 416 + storage/mroonga/vendor/groonga/lib/table.c | 122 + storage/mroonga/vendor/groonga/lib/thread.c | 59 + storage/mroonga/vendor/groonga/lib/time.c | 245 + storage/mroonga/vendor/groonga/lib/token_cursor.c | 386 + storage/mroonga/vendor/groonga/lib/token_filter.c | 59 + storage/mroonga/vendor/groonga/lib/tokenizer.c | 375 + storage/mroonga/vendor/groonga/lib/tokenizers.c | 890 + storage/mroonga/vendor/groonga/lib/ts.c | 906 + storage/mroonga/vendor/groonga/lib/ts/Makefile.am | 20 + storage/mroonga/vendor/groonga/lib/ts/sources.am | 25 + storage/mroonga/vendor/groonga/lib/ts/ts_buf.c | 244 + storage/mroonga/vendor/groonga/lib/ts/ts_buf.h | 111 + storage/mroonga/vendor/groonga/lib/ts/ts_cursor.c | 163 + storage/mroonga/vendor/groonga/lib/ts/ts_cursor.h | 59 + storage/mroonga/vendor/groonga/lib/ts/ts_expr.c | 219 + storage/mroonga/vendor/groonga/lib/ts/ts_expr.h | 87 + .../vendor/groonga/lib/ts/ts_expr_builder.c | 757 + .../vendor/groonga/lib/ts/ts_expr_builder.h | 128 + .../mroonga/vendor/groonga/lib/ts/ts_expr_node.c | 5325 ++ .../mroonga/vendor/groonga/lib/ts/ts_expr_node.h | 128 + .../mroonga/vendor/groonga/lib/ts/ts_expr_parser.c | 1329 + .../mroonga/vendor/groonga/lib/ts/ts_expr_parser.h | 107 + storage/mroonga/vendor/groonga/lib/ts/ts_log.h | 46 + storage/mroonga/vendor/groonga/lib/ts/ts_op.c | 131 + storage/mroonga/vendor/groonga/lib/ts/ts_op.h | 87 + storage/mroonga/vendor/groonga/lib/ts/ts_plan.c | 21 + storage/mroonga/vendor/groonga/lib/ts/ts_plan.h | 87 + storage/mroonga/vendor/groonga/lib/ts/ts_sorter.c | 2174 + storage/mroonga/vendor/groonga/lib/ts/ts_sorter.h | 98 + storage/mroonga/vendor/groonga/lib/ts/ts_str.c | 191 + storage/mroonga/vendor/groonga/lib/ts/ts_str.h | 106 + storage/mroonga/vendor/groonga/lib/ts/ts_types.h | 168 + storage/mroonga/vendor/groonga/lib/ts/ts_util.c | 129 + storage/mroonga/vendor/groonga/lib/ts/ts_util.h | 61 + storage/mroonga/vendor/groonga/lib/type.c | 87 + storage/mroonga/vendor/groonga/lib/util.c | 1643 + .../mroonga/vendor/groonga/lib/window_function.c | 464 + .../mroonga/vendor/groonga/lib/window_functions.c | 405 + storage/mroonga/vendor/groonga/lib/windows.c | 104 + .../vendor/groonga/lib/windows_event_logger.c | 203 + 359 files changed, 218537 insertions(+) create mode 100644 storage/mroonga/vendor/groonga/lib/CMakeLists.txt create mode 100644 storage/mroonga/vendor/groonga/lib/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/alloc.c create mode 100644 storage/mroonga/vendor/groonga/lib/arrow.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/c_sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/cache.c create mode 100644 storage/mroonga/vendor/groonga/lib/column.c create mode 100644 storage/mroonga/vendor/groonga/lib/com.c create mode 100644 storage/mroonga/vendor/groonga/lib/command.c create mode 100644 storage/mroonga/vendor/groonga/lib/config.c create mode 100644 storage/mroonga/vendor/groonga/lib/cpp_sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/ctx.c create mode 100644 storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c create mode 100644 storage/mroonga/vendor/groonga/lib/dat.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/dat/array.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/base.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/block.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/check.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/cursor-factory.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/cursor-factory.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/cursor.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/dat.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/entry.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/file-impl.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/file.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/file.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/header.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/id-cursor.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/key-cursor.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/key-cursor.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/key.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/node.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/predictive-cursor.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/predictive-cursor.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/prefix-cursor.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/prefix-cursor.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/dat/string.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/trie.cpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/trie.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/dat/vector.hpp create mode 100644 storage/mroonga/vendor/groonga/lib/db.c create mode 100644 storage/mroonga/vendor/groonga/lib/dump.c create mode 100644 storage/mroonga/vendor/groonga/lib/error.c create mode 100644 storage/mroonga/vendor/groonga/lib/expr.c create mode 100644 storage/mroonga/vendor/groonga/lib/expr_code.c create mode 100644 storage/mroonga/vendor/groonga/lib/expr_executor.c create mode 100644 storage/mroonga/vendor/groonga/lib/file_lock.c create mode 100644 storage/mroonga/vendor/groonga/lib/file_reader.c create mode 100644 storage/mroonga/vendor/groonga/lib/geo.c create mode 100644 storage/mroonga/vendor/groonga/lib/grn.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_alloc.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_cache.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_com.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_config.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_ctx.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_dat.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_db.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_ecmascript.c create mode 100644 storage/mroonga/vendor/groonga/lib/grn_ecmascript.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_ecmascript.lemon create mode 100644 storage/mroonga/vendor/groonga/lib/grn_error.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_expr.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_expr_code.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_expr_executor.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_file_lock.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_geo.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_hash.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_ii.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_index_column.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_io.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_load.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_logger.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_mrb.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_msgpack.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_nfkc.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_normalizer.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_obj.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_output.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_pat.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_plugin.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_proc.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_raw_string.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_report.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_request_canceler.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_request_timer.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_rset.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_scanner.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_scorer.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_scorers.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_snip.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_store.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_str.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_string.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_time.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_token_cursor.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_tokenizers.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_ts.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_util.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_window_function.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_window_functions.h create mode 100644 storage/mroonga/vendor/groonga/lib/grn_windows.h create mode 100644 storage/mroonga/vendor/groonga/lib/hash.c create mode 100644 storage/mroonga/vendor/groonga/lib/icudump.c create mode 100644 storage/mroonga/vendor/groonga/lib/id.c create mode 100644 storage/mroonga/vendor/groonga/lib/ii.c create mode 100644 storage/mroonga/vendor/groonga/lib/index_column.c create mode 100644 storage/mroonga/vendor/groonga/lib/io.c create mode 100644 storage/mroonga/vendor/groonga/lib/load.c create mode 100644 storage/mroonga/vendor/groonga/lib/logger.c create mode 100644 storage/mroonga/vendor/groonga/lib/metadata.rc.in create mode 100644 storage/mroonga/vendor/groonga/lib/mrb.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_command_version.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_command_version.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_config.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_config.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_content_type.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_content_type.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_eval_context.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_eval_context.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_indexable.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_indexable.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_object.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_object_flags.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_object_flags.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_options.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_options.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_pointer.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_pointer.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_query_logger.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_query_logger.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_record.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_record.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_flags.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_flags.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_result.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_result.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_flags.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_flags.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_key.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_key.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_thread.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_thread.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_window_definition.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_window_definition.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/accessor.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/backtrace_entry.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/command_input.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line_parser.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/context/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/context/error_level.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/context/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/eval_context.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_rewriter.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_rewriters.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_size_estimator.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/accessor.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/binary_operation.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/constant.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/function_call.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/index_column.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/logical_operation.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/options.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/procedure.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/variable.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree_builder.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/fixed_size_column.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/id.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/index_column.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/index_info.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/level.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/object.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/operator.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/flag.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/record.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data_size_estimator.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_search_index.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/table.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/variable_size_column.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb create mode 100644 storage/mroonga/vendor/groonga/lib/mrb/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/nfkc-custom-rules.txt create mode 100644 storage/mroonga/vendor/groonga/lib/nfkc.c create mode 100755 storage/mroonga/vendor/groonga/lib/nfkc.rb create mode 100644 storage/mroonga/vendor/groonga/lib/nfkc50.c create mode 100644 storage/mroonga/vendor/groonga/lib/normalizer.c create mode 100644 storage/mroonga/vendor/groonga/lib/obj.c create mode 100644 storage/mroonga/vendor/groonga/lib/operator.c create mode 100644 storage/mroonga/vendor/groonga/lib/output.c create mode 100644 storage/mroonga/vendor/groonga/lib/pat.c create mode 100644 storage/mroonga/vendor/groonga/lib/plugin.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_column.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_config.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_dump.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_fuzzy_search.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_highlight.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_in_records.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_lock.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_object.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_object_inspect.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_object_list.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_query.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_query_log_flags.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_schema.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_select.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_snippet.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_table.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/proc_tokenize.c create mode 100644 storage/mroonga/vendor/groonga/lib/proc/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/raw_string.c create mode 100644 storage/mroonga/vendor/groonga/lib/report.c create mode 100644 storage/mroonga/vendor/groonga/lib/request_canceler.c create mode 100644 storage/mroonga/vendor/groonga/lib/request_timer.c create mode 100644 storage/mroonga/vendor/groonga/lib/rset.c create mode 100644 storage/mroonga/vendor/groonga/lib/scanner.c create mode 100644 storage/mroonga/vendor/groonga/lib/scorer.c create mode 100644 storage/mroonga/vendor/groonga/lib/scorers.c create mode 100644 storage/mroonga/vendor/groonga/lib/snip.c create mode 100644 storage/mroonga/vendor/groonga/lib/store.c create mode 100644 storage/mroonga/vendor/groonga/lib/str.c create mode 100644 storage/mroonga/vendor/groonga/lib/string.c create mode 100644 storage/mroonga/vendor/groonga/lib/table.c create mode 100644 storage/mroonga/vendor/groonga/lib/thread.c create mode 100644 storage/mroonga/vendor/groonga/lib/time.c create mode 100644 storage/mroonga/vendor/groonga/lib/token_cursor.c create mode 100644 storage/mroonga/vendor/groonga/lib/token_filter.c create mode 100644 storage/mroonga/vendor/groonga/lib/tokenizer.c create mode 100644 storage/mroonga/vendor/groonga/lib/tokenizers.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/Makefile.am create mode 100644 storage/mroonga/vendor/groonga/lib/ts/sources.am create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_buf.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_buf.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_cursor.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_cursor.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_expr.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_expr.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_expr_builder.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_expr_builder.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_expr_parser.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_expr_parser.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_log.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_op.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_op.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_plan.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_plan.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_sorter.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_sorter.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_str.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_str.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_types.h create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_util.c create mode 100644 storage/mroonga/vendor/groonga/lib/ts/ts_util.h create mode 100644 storage/mroonga/vendor/groonga/lib/type.c create mode 100644 storage/mroonga/vendor/groonga/lib/util.c create mode 100644 storage/mroonga/vendor/groonga/lib/window_function.c create mode 100644 storage/mroonga/vendor/groonga/lib/window_functions.c create mode 100644 storage/mroonga/vendor/groonga/lib/windows.c create mode 100644 storage/mroonga/vendor/groonga/lib/windows_event_logger.c (limited to 'storage/mroonga/vendor/groonga/lib') diff --git a/storage/mroonga/vendor/groonga/lib/CMakeLists.txt b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt new file mode 100644 index 00000000..8c71563f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/CMakeLists.txt @@ -0,0 +1,185 @@ +# Copyright(C) 2012-2016 Brazil +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1 as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA + +add_definitions( + -DGRN_DAT_EXPORT + ) + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/dat + ${ONIGMO_INCLUDE_DIRS} + ${MRUBY_INCLUDE_DIRS} + ${LIBLZ4_INCLUDE_DIRS} + ${LIBZSTD_INCLUDE_DIRS} + ${MESSAGE_PACK_INCLUDE_DIRS}) + +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/c_sources.am LIBGROONGA_C_SOURCES) +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/cpp_sources.am LIBGROONGA_CPP_SOURCES) +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/dat/sources.am LIBGRNDAT_SOURCES) +string(REGEX REPLACE "([^;]+)" "dat/\\1" + LIBGRNDAT_SOURCES "${LIBGRNDAT_SOURCES}") +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/sources.am LIBGRNMRB_SOURCES) +string(REGEX REPLACE "([^;]+)" "mrb/\\1" + LIBGRNMRB_SOURCES "${LIBGRNMRB_SOURCES}") +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/proc/sources.am LIBGRNPROC_SOURCES) +string(REGEX REPLACE "([^;]+)" "proc/\\1" + LIBGRNPROC_SOURCES "${LIBGRNPROC_SOURCES}") +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/ts/sources.am LIBGRNTS_SOURCES) +string(REGEX REPLACE "([^;]+)" "ts/\\1" + LIBGRNTS_SOURCES "${LIBGRNTS_SOURCES}") + +if(WIN32) + configure_file( + "metadata.rc.in" + "${CMAKE_CURRENT_BINARY_DIR}/metadata.rc" + @ONLY) + set(LIBGROONGA_METADATA_SOURCES + "${CMAKE_CURRENT_BINARY_DIR}/metadata.rc") +else() + set(LIBGROONGA_METADATA_SOURCES) +endif() + +set_source_files_properties( + ${LIBGROONGA_C_SOURCES} + ${LIBGRNMRB_SOURCES} + ${LIBGRNPROC_SOURCES} + ${LIBGRNTS_SOURCES} + PROPERTIES + COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") +set_source_files_properties( + ${LIBGROONGA_C_SOURCES} + ${LIBGROONGA_CPP_SOURCES} + ${LIBGRNMRB_SOURCES} + PROPERTIES + COMPILE_DEFINITIONS "${MRUBY_DEFINITIONS}") +set_source_files_properties( + ${LIBGROONGA_CPP_SOURCES} + ${LIBGRNDAT_SOURCES} + PROPERTIES + COMPILE_FLAGS "${GRN_CXX_COMPILE_FLAGS}") + +set(GRN_ALL_SOURCES + ${LIBGROONGA_C_SOURCES} + ${LIBGROONGA_CPP_SOURCES} + ${LIBGRNDAT_SOURCES} + ${LIBGRNMRB_SOURCES} + ${LIBGRNPROC_SOURCES} + ${LIBGRNTS_SOURCES} + ${LIBGROONGA_METADATA_SOURCES}) +if(GRN_EMBED) + add_library(libgroonga STATIC ${GRN_ALL_SOURCES}) + set_target_properties( + libgroonga + PROPERTIES + POSITION_INDEPENDENT_CODE ON) +else() + add_library(libgroonga SHARED ${GRN_ALL_SOURCES}) +endif() +set_target_properties(libgroonga PROPERTIES OUTPUT_NAME "groonga") + +set(GRN_ALL_LIBRARIES + ${EXECINFO_LIBS} + ${RT_LIBS} + ${PTHREAD_LIBS} + ${Z_LIBS} + ${LZ4_LIBS} + ${LIBZSTD_LIBS} + ${MESSAGE_PACK_LIBS} + ${CMAKE_DL_LIBS} + ${M_LIBS} + ${WS2_32_LIBS} + ${MRUBY_LIBS} + ${ONIGMO_LIBS}) +if(GRN_EMBED) + set(GRN_EMBEDDED_PLUGIN_LIBRARIES "") + if(GRN_WITH_MECAB) + list(APPEND GRN_EMBEDDED_PLUGIN_LIBRARIES mecab_tokenizer) + endif() + target_link_libraries(libgroonga + ${GRN_ALL_LIBRARIES} + ${STDCPP_LIBS} + ${GRN_EMBEDDED_PLUGIN_LIBRARIES}) +else() + target_link_libraries(libgroonga + ${GRN_ALL_LIBRARIES}) + install(TARGETS libgroonga + ARCHIVE DESTINATION "${LIB_DIR}" + LIBRARY DESTINATION "${LIB_DIR}" + RUNTIME DESTINATION "${BIN_DIR}") +endif() + +if(GRN_WITH_MRUBY) + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/scripts/sources.am + RUBY_SCRIPTS) + string(REGEX REPLACE "([^;]+)" "mrb/scripts/\\1" + RUBY_SCRIPTS "${RUBY_SCRIPTS}") + install( + FILES ${RUBY_SCRIPTS} + DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}") + + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/scripts/command_line/sources.am + COMMANE_LINE_RUBY_SCRIPTS) + string(REGEX REPLACE "([^;]+)" "mrb/scripts/command_line/\\1" + COMMANE_LINE_RUBY_SCRIPTS "${COMMANE_LINE_RUBY_SCRIPTS}") + install( + FILES ${COMMANE_LINE_RUBY_SCRIPTS} + DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}/command_line") + + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/scripts/context/sources.am + CONTEXT_RUBY_SCRIPTS) + string(REGEX REPLACE "([^;]+)" "mrb/scripts/context/\\1" + CONTEXT_RUBY_SCRIPTS "${CONTEXT_RUBY_SCRIPTS}") + install( + FILES ${CONTEXT_RUBY_SCRIPTS} + DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}/context") + + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/scripts/initialize/sources.am + INITIALIZE_RUBY_SCRIPTS) + string(REGEX REPLACE "([^;]+)" "mrb/scripts/initialize/\\1" + INITIALIZE_RUBY_SCRIPTS "${INITIALIZE_RUBY_SCRIPTS}") + install( + FILES ${INITIALIZE_RUBY_SCRIPTS} + DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}/initialize") + + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/scripts/logger/sources.am + LOGGER_RUBY_SCRIPTS) + string(REGEX REPLACE "([^;]+)" "mrb/scripts/logger/\\1" + LOGGER_RUBY_SCRIPTS "${LOGGER_RUBY_SCRIPTS}") + install( + FILES ${LOGGER_RUBY_SCRIPTS} + DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}/logger") + + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/scripts/query_logger/sources.am + QUERY_LOGGER_RUBY_SCRIPTS) + string(REGEX REPLACE "([^;]+)" "mrb/scripts/query_logger/\\1" + QUERY_LOGGER_RUBY_SCRIPTS "${QUERY_LOGGER_RUBY_SCRIPTS}") + install( + FILES ${QUERY_LOGGER_RUBY_SCRIPTS} + DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}/query_logger") + + read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/mrb/scripts/expression_tree/sources.am + EXPRESSION_TREE_RUBY_SCRIPTS) + string(REGEX REPLACE "([^;]+)" "mrb/scripts/expression_tree/\\1" + EXPRESSION_TREE_RUBY_SCRIPTS "${EXPRESSION_TREE_RUBY_SCRIPTS}") + install( + FILES ${EXPRESSION_TREE_RUBY_SCRIPTS} + DESTINATION "${GRN_RELATIVE_RUBY_SCRIPTS_DIR}/expression_tree") +endif() + +# Workaround GCC ICE on ARM64 +IF(CMAKE_COMPILER_IS_GNUCXX AND CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64" AND + CMAKE_C_COMPILER_VERSION VERSION_GREATER "5") + ADD_COMPILE_FLAGS(ts/ts_expr_node.c COMPILE_FLAGS "-fno-tree-loop-vectorize") +ENDIF() diff --git a/storage/mroonga/vendor/groonga/lib/Makefile.am b/storage/mroonga/vendor/groonga/lib/Makefile.am new file mode 100644 index 00000000..9a2217ee --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/Makefile.am @@ -0,0 +1,99 @@ +SUBDIRS = \ + dat \ + mrb \ + proc \ + ts + +lib_LTLIBRARIES = libgroonga.la + +include $(top_srcdir)/version.sh + +AM_CPPFLAGS = \ + $(MRUBY_CPPFLAGS) + +AM_CFLAGS = \ + $(NO_STRICT_ALIASING_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(GRN_CFLAGS) \ + $(MESSAGE_PACK_CFLAGS) \ + $(LIBLZ4_CFLAGS) \ + $(LIBZSTD_CFLAGS) + +AM_CXXFLAGS = \ + $(NO_STRICT_ALIASING_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(GRN_CXXFLAGS) \ + $(ARROW_CFLAGS) + +BUNDLED_LIBRARIES_CFLAGS = \ + $(MRUBY_CFLAGS) \ + $(ONIGMO_CFLAGS) + +DEFAULT_INCLUDES = \ + -I$(top_builddir) \ + -I$(top_srcdir)/include \ + $(BUNDLED_LIBRARIES_CFLAGS) + +DEFS += -D_REENTRANT $(GRN_DEFS) -DGRN_DAT_EXPORT + +include c_sources.am +include cpp_sources.am +libgroonga_la_SOURCES = \ + $(libgroonga_c_sources) \ + $(libgroonga_cpp_source) + +#nfkc.c: +# $(RUBY) nfkc.rb --impl=table + +libgroonga_la_LDFLAGS = \ + -version-info $(LT_VERSION_INFO) \ + -no-undefined \ + $(WINDOWS_LDFLAGS) + +libgroonga_la_LIBADD = \ + dat/libgrndat.la \ + mrb/libgrnmrb.la \ + proc/libgrnproc.la \ + ts/libgrnts.la \ + $(MESSAGE_PACK_LIBS) + +if WITH_MRUBY +libgroonga_la_LIBADD += \ + ../vendor/mruby/libmruby.la +endif + +libgroonga_la_LIBADD += \ + $(ONIGMO_LIBS) \ + $(LIBLZ4_LIBS) \ + $(LIBZSTD_LIBS) \ + $(ATOMIC_LIBS) \ + $(ARROW_LIBS) + +if WITH_LEMON +BUILT_SOURCES = \ + grn_ecmascript.c + +SUFFIXES = .lemon .c + +.lemon.c: + $(LEMON) $< +endif + +if PLATFORM_WIN32 +libgroonga_la_SOURCES += \ + metadata.rc + +.rc.lo: + $(LIBTOOL) $(AM_V_lt) --tag=RC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ + --mode=compile \ + $(RC) $(RCFLAGS) -o $@ $< +endif + +EXTRA_DIST = \ + grn_ecmascript.c \ + grn_ecmascript.h \ + grn_ecmascript.lemon \ + CMakeLists.txt + +CLEANFILES = *.gcno *.gcda diff --git a/storage/mroonga/vendor/groonga/lib/alloc.c b/storage/mroonga/vendor/groonga/lib/alloc.c new file mode 100644 index 00000000..5e556b83 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/alloc.c @@ -0,0 +1,961 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_alloc.h" +#include "grn_ctx_impl.h" + +static int alloc_count = 0; + +#ifdef USE_FAIL_MALLOC +static int grn_fmalloc_prob = 0; +static char *grn_fmalloc_func = NULL; +static char *grn_fmalloc_file = NULL; +static int grn_fmalloc_line = 0; +#endif /* USE_FAIL_MALLOC */ + +#ifdef USE_EXACT_ALLOC_COUNT +# define GRN_ADD_ALLOC_COUNT(count) do { \ + uint32_t alloced; \ + GRN_ATOMIC_ADD_EX(&alloc_count, count, alloced); \ +} while (0) +#else /* USE_EXACT_ALLOC_COUNT */ +# define GRN_ADD_ALLOC_COUNT(count) do { \ + alloc_count += count; \ +} while (0) +#endif + +void +grn_alloc_init_from_env(void) +{ +#ifdef USE_FAIL_MALLOC + { + char grn_fmalloc_prob_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_FMALLOC_PROB", + grn_fmalloc_prob_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_prob_env[0]) { + char grn_fmalloc_seed_env[GRN_ENV_BUFFER_SIZE]; + grn_fmalloc_prob = strtod(grn_fmalloc_prob_env, 0) * RAND_MAX; + grn_getenv("GRN_FMALLOC_SEED", + grn_fmalloc_seed_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_seed_env[0]) { + srand((unsigned int)atoi(grn_fmalloc_seed_env)); + } else { + srand((unsigned int)time(NULL)); + } + } + } + { + static char grn_fmalloc_func_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_FMALLOC_FUNC", + grn_fmalloc_func_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_func_env[0]) { + grn_fmalloc_func = grn_fmalloc_func_env; + } + } + { + static char grn_fmalloc_file_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_FMALLOC_FILE", + grn_fmalloc_file_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_file_env[0]) { + grn_fmalloc_file = grn_fmalloc_file_env; + } + } + { + char grn_fmalloc_line_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_FMALLOC_LINE", + grn_fmalloc_line_env, + GRN_ENV_BUFFER_SIZE); + if (grn_fmalloc_line_env[0]) { + grn_fmalloc_line = atoi(grn_fmalloc_line_env); + } + } +#endif /* USE_FAIL_MALLOC */ +} + +#ifdef USE_MEMORY_DEBUG +static grn_critical_section grn_alloc_info_lock; + +void +grn_alloc_info_init(void) +{ + CRITICAL_SECTION_INIT(grn_alloc_info_lock); +} + +void +grn_alloc_info_fin(void) +{ + CRITICAL_SECTION_FIN(grn_alloc_info_lock); +} + +inline static void +grn_alloc_info_set_backtrace(char *buffer, size_t size) +{ +# ifdef HAVE_BACKTRACE +# define N_TRACE_LEVEL 100 + static void *trace[N_TRACE_LEVEL]; + char **symbols; + int i, n, rest; + + rest = size; + n = backtrace(trace, N_TRACE_LEVEL); + symbols = backtrace_symbols(trace, n); + if (symbols) { + for (i = 0; i < n; i++) { + int symbol_length; + + symbol_length = strlen(symbols[i]); + if (symbol_length + 2 > rest) { + break; + } + grn_memcpy(buffer, symbols[i], symbol_length); + buffer += symbol_length; + rest -= symbol_length; + buffer[0] = '\n'; + buffer++; + rest--; + buffer[0] = '\0'; + rest--; + } + free(symbols); + } else { + buffer[0] = '\0'; + } +# undef N_TRACE_LEVEL +# else /* HAVE_BACKTRACE */ + buffer[0] = '\0'; +# endif /* HAVE_BACKTRACE */ +} + +inline static void +grn_alloc_info_add(void *address, size_t size, + const char *file, int line, const char *func) +{ + grn_ctx *ctx; + grn_alloc_info *new_alloc_info; + + ctx = &grn_gctx; + if (!ctx->impl) { return; } + + CRITICAL_SECTION_ENTER(grn_alloc_info_lock); + new_alloc_info = malloc(sizeof(grn_alloc_info)); + if (new_alloc_info) { + new_alloc_info->address = address; + new_alloc_info->size = size; + new_alloc_info->freed = GRN_FALSE; + grn_alloc_info_set_backtrace(new_alloc_info->alloc_backtrace, + sizeof(new_alloc_info->alloc_backtrace)); + if (file) { + new_alloc_info->file = strdup(file); + } else { + new_alloc_info->file = NULL; + } + new_alloc_info->line = line; + if (func) { + new_alloc_info->func = strdup(func); + } else { + new_alloc_info->func = NULL; + } + new_alloc_info->next = ctx->impl->alloc_info; + ctx->impl->alloc_info = new_alloc_info; + } + CRITICAL_SECTION_LEAVE(grn_alloc_info_lock); +} + +inline static void +grn_alloc_info_change(void *old_address, void *new_address, size_t size) +{ + grn_ctx *ctx; + grn_alloc_info *alloc_info; + + ctx = &grn_gctx; + if (!ctx->impl) { return; } + + CRITICAL_SECTION_ENTER(grn_alloc_info_lock); + alloc_info = ctx->impl->alloc_info; + for (; alloc_info; alloc_info = alloc_info->next) { + if (alloc_info->address == old_address) { + alloc_info->address = new_address; + alloc_info->size = size; + grn_alloc_info_set_backtrace(alloc_info->alloc_backtrace, + sizeof(alloc_info->alloc_backtrace)); + } + } + CRITICAL_SECTION_LEAVE(grn_alloc_info_lock); +} + +void +grn_alloc_info_dump(grn_ctx *ctx) +{ + int i = 0; + grn_alloc_info *alloc_info; + + if (!ctx) { return; } + if (!ctx->impl) { return; } + + alloc_info = ctx->impl->alloc_info; + for (; alloc_info; alloc_info = alloc_info->next) { + if (alloc_info->freed) { + printf("address[%d][freed]: %p(%" GRN_FMT_SIZE ")\n", + i, alloc_info->address, alloc_info->size); + } else { + printf("address[%d][not-freed]: %p(%" GRN_FMT_SIZE "): %s:%d: %s()\n%s", + i, + alloc_info->address, + alloc_info->size, + alloc_info->file ? alloc_info->file : "(unknown)", + alloc_info->line, + alloc_info->func ? alloc_info->func : "(unknown)", + alloc_info->alloc_backtrace); + } + i++; + } +} + +inline static void +grn_alloc_info_check(grn_ctx *ctx, void *address) +{ + grn_alloc_info *alloc_info; + + if (!grn_gctx.impl) { return; } + /* grn_alloc_info_dump(ctx); */ + + CRITICAL_SECTION_ENTER(grn_alloc_info_lock); + alloc_info = grn_gctx.impl->alloc_info; + for (; alloc_info; alloc_info = alloc_info->next) { + if (alloc_info->address == address) { + if (alloc_info->freed) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "double free: %p(%" GRN_FMT_SIZE "):\n" + "alloc backtrace:\n" + "%sfree backtrace:\n" + "%s", + alloc_info->address, + alloc_info->size, + alloc_info->alloc_backtrace, + alloc_info->free_backtrace); + } else { + alloc_info->freed = GRN_TRUE; + grn_alloc_info_set_backtrace(alloc_info->free_backtrace, + sizeof(alloc_info->free_backtrace)); + } + break; + } + } + CRITICAL_SECTION_LEAVE(grn_alloc_info_lock); +} + +void +grn_alloc_info_free(grn_ctx *ctx) +{ + grn_alloc_info *alloc_info; + + if (!ctx) { return; } + if (!ctx->impl) { return; } + + alloc_info = ctx->impl->alloc_info; + while (alloc_info) { + grn_alloc_info *current_alloc_info = alloc_info; + alloc_info = alloc_info->next; + current_alloc_info->next = NULL; + free(current_alloc_info->file); + free(current_alloc_info->func); + free(current_alloc_info); + } + ctx->impl->alloc_info = NULL; +} + +#else /* USE_MEMORY_DEBUG */ +void +grn_alloc_info_init(void) +{ +} + +void +grn_alloc_info_fin(void) +{ +} + +# define grn_alloc_info_add(address, size, file, line, func) +# define grn_alloc_info_change(old_address, new_address, size) +# define grn_alloc_info_check(ctx, address) + +void +grn_alloc_info_dump(grn_ctx *ctx) +{ +} + +void +grn_alloc_info_free(grn_ctx *ctx) +{ +} +#endif /* USE_MEMORY_DEBUG */ + +#define GRN_CTX_SEGMENT_SIZE (1U <<22) +#define GRN_CTX_SEGMENT_MASK (GRN_CTX_SEGMENT_SIZE - 1) + +#define GRN_CTX_SEGMENT_WORD (1U <<31) +#define GRN_CTX_SEGMENT_VLEN (1U <<30) +#define GRN_CTX_SEGMENT_LIFO (1U <<29) +#define GRN_CTX_SEGMENT_DIRTY (1U <<28) + +void +grn_alloc_init_ctx_impl(grn_ctx *ctx) +{ +#ifdef USE_DYNAMIC_MALLOC_CHANGE +# ifdef USE_FAIL_MALLOC + ctx->impl->malloc_func = grn_malloc_fail; + ctx->impl->calloc_func = grn_calloc_fail; + ctx->impl->realloc_func = grn_realloc_fail; + ctx->impl->strdup_func = grn_strdup_fail; +# else + ctx->impl->malloc_func = grn_malloc_default; + ctx->impl->calloc_func = grn_calloc_default; + ctx->impl->realloc_func = grn_realloc_default; + ctx->impl->strdup_func = grn_strdup_default; +# endif +#endif + +#ifdef USE_MEMORY_DEBUG + ctx->impl->alloc_info = NULL; +#endif +} + +void +grn_alloc_fin_ctx_impl(grn_ctx *ctx) +{ + int i; + grn_io_mapinfo *mi; + for (i = 0, mi = ctx->impl->segs; i < GRN_CTX_N_SEGMENTS; i++, mi++) { + if (mi->map) { + //GRN_LOG(ctx, GRN_LOG_NOTICE, "unmap in ctx_fin(%d,%d,%d)", i, (mi->count & GRN_CTX_SEGMENT_MASK), mi->nref); + if (mi->count & GRN_CTX_SEGMENT_VLEN) { + grn_io_anon_unmap(ctx, mi, mi->nref * grn_pagesize); + } else { + grn_io_anon_unmap(ctx, mi, GRN_CTX_SEGMENT_SIZE); + } + } + } +} + +#define ALIGN_SIZE (1<<3) +#define ALIGN_MASK (ALIGN_SIZE-1) +#define GRN_CTX_ALLOC_CLEAR 1 + +static void * +grn_ctx_alloc(grn_ctx *ctx, size_t size, int flags, + const char* file, int line, const char *func) +{ + void *res = NULL; + if (!ctx) { return res; } + if (!ctx->impl) { + if (ERRP(ctx, GRN_ERROR)) { return res; } + } + CRITICAL_SECTION_ENTER(ctx->impl->lock); + { + int32_t i; + int32_t *header; + grn_io_mapinfo *mi; + size = ((size + ALIGN_MASK) & ~ALIGN_MASK) + ALIGN_SIZE; + if (size > GRN_CTX_SEGMENT_SIZE) { + uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize; + size_t aligned_size; + if (npages >= (1LL<<32)) { + MERR("too long request size=%" GRN_FMT_SIZE, size); + goto exit; + } + for (i = 0, mi = ctx->impl->segs;; i++, mi++) { + if (i >= GRN_CTX_N_SEGMENTS) { + MERR("all segments are full"); + goto exit; + } + if (!mi->map) { break; } + } + aligned_size = grn_pagesize * ((size_t)npages); + if (!grn_io_anon_map(ctx, mi, aligned_size)) { goto exit; } + /* GRN_LOG(ctx, GRN_LOG_NOTICE, "map i=%d (%d)", i, npages * grn_pagesize); */ + mi->nref = (uint32_t) npages; + mi->count = GRN_CTX_SEGMENT_VLEN; + ctx->impl->currseg = -1; + header = mi->map; + header[0] = i; + header[1] = (int32_t) size; + } else { + if ((i = ctx->impl->currseg) >= 0) + mi = &ctx->impl->segs[i]; + if (i < 0 || size + mi->nref > GRN_CTX_SEGMENT_SIZE) { + for (i = 0, mi = ctx->impl->segs;; i++, mi++) { + if (i >= GRN_CTX_N_SEGMENTS) { + MERR("all segments are full"); + goto exit; + } + if (!mi->map) { break; } + } + if (!grn_io_anon_map(ctx, mi, GRN_CTX_SEGMENT_SIZE)) { goto exit; } + /* GRN_LOG(ctx, GRN_LOG_NOTICE, "map i=%d", i); */ + mi->nref = 0; + mi->count = GRN_CTX_SEGMENT_WORD; + ctx->impl->currseg = i; + } + header = (int32_t *)((byte *)mi->map + mi->nref); + mi->nref += size; + mi->count++; + header[0] = i; + header[1] = (int32_t) size; + if ((flags & GRN_CTX_ALLOC_CLEAR) && + (mi->count & GRN_CTX_SEGMENT_DIRTY) && (size > ALIGN_SIZE)) { + memset(&header[2], 0, size - ALIGN_SIZE); + } + } + /* + { + char g = (ctx == &grn_gctx) ? 'g' : ' '; + GRN_LOG(ctx, GRN_LOG_NOTICE, "+%c(%p) %s:%d(%s) (%d:%d)%p mi(%d:%d)", g, ctx, file, line, func, header[0], header[1], &header[2], mi->nref, (mi->count & GRN_CTX_SEGMENT_MASK)); + } + */ + res = &header[2]; + } +exit : + CRITICAL_SECTION_LEAVE(ctx->impl->lock); + return res; +} + +void * +grn_ctx_malloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + return grn_ctx_alloc(ctx, size, 0, file, line, func); +} + +void * +grn_ctx_calloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + return grn_ctx_alloc(ctx, size, GRN_CTX_ALLOC_CLEAR, file, line, func); +} + +void * +grn_ctx_realloc(grn_ctx *ctx, void *ptr, size_t size, + const char* file, int line, const char *func) +{ + void *res = NULL; + if (size) { + /* todo : expand if possible */ + res = grn_ctx_alloc(ctx, size, 0, file, line, func); + if (res && ptr) { + int32_t *header = &((int32_t *)ptr)[-2]; + size_t size_ = header[1]; + grn_memcpy(res, ptr, size_ > size ? size : size_); + grn_ctx_free(ctx, ptr, file, line, func); + } + } else { + grn_ctx_free(ctx, ptr, file, line, func); + } + return res; +} + +char * +grn_ctx_strdup(grn_ctx *ctx, const char *s, + const char* file, int line, const char *func) +{ + void *res = NULL; + if (s) { + size_t size = strlen(s) + 1; + if ((res = grn_ctx_alloc(ctx, size, 0, file, line, func))) { + grn_memcpy(res, s, size); + } + } + return res; +} + +void +grn_ctx_free(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func) +{ + if (!ctx) { return; } + if (!ctx->impl) { + ERR(GRN_INVALID_ARGUMENT,"ctx without impl passed."); + return; + } + CRITICAL_SECTION_ENTER(ctx->impl->lock); + if (ptr) { + int32_t *header = &((int32_t *)ptr)[-2]; + + if (header[0] >= GRN_CTX_N_SEGMENTS) { + ERR(GRN_INVALID_ARGUMENT,"invalid ptr passed. ptr=%p seg=%d", ptr, *header); + goto exit; + } + /* + { + int32_t i = header[0]; + char c = 'X', g = (ctx == &grn_gctx) ? 'g' : ' '; + grn_io_mapinfo *mi = &ctx->impl->segs[i]; + if (!(mi->count & GRN_CTX_SEGMENT_VLEN) && + mi->map <= (void *)header && (char *)header < ((char *)mi->map + GRN_CTX_SEGMENT_SIZE)) { c = '-'; } + GRN_LOG(ctx, GRN_LOG_NOTICE, "%c%c(%p) %s:%d(%s) (%d:%d)%p mi(%d:%d)", c, g, ctx, file, line, func, header[0], header[1], &header[2], mi->nref, (mi->count & GRN_CTX_SEGMENT_MASK)); + } + */ + { + int32_t i = header[0]; + grn_io_mapinfo *mi = &ctx->impl->segs[i]; + if (mi->count & GRN_CTX_SEGMENT_VLEN) { + if (mi->map != header) { + ERR(GRN_INVALID_ARGUMENT,"invalid ptr passed.. ptr=%p seg=%d", ptr, i); + goto exit; + } + //GRN_LOG(ctx, GRN_LOG_NOTICE, "umap i=%d (%d)", i, mi->nref * grn_pagesize); + grn_io_anon_unmap(ctx, mi, mi->nref * grn_pagesize); + mi->map = NULL; + } else { + if (!mi->map) { + ERR(GRN_INVALID_ARGUMENT,"invalid ptr passed... ptr=%p seg=%d", ptr, i); + goto exit; + } + mi->count--; + if (!(mi->count & GRN_CTX_SEGMENT_MASK)) { + //GRN_LOG(ctx, GRN_LOG_NOTICE, "umap i=%d", i); + if (i == ctx->impl->currseg) { + mi->count |= GRN_CTX_SEGMENT_DIRTY; + mi->nref = 0; + } else { + grn_io_anon_unmap(ctx, mi, GRN_CTX_SEGMENT_SIZE); + mi->map = NULL; + } + } + } + } + } +exit : + CRITICAL_SECTION_LEAVE(ctx->impl->lock); +} + +void * +grn_ctx_alloc_lifo(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (!ctx) { return NULL; } + if (!ctx->impl) { + if (ERRP(ctx, GRN_ERROR)) { return NULL; } + } + { + int32_t i = ctx->impl->lifoseg; + grn_io_mapinfo *mi = &ctx->impl->segs[i]; + if (size > GRN_CTX_SEGMENT_SIZE) { + uint64_t npages = (size + (grn_pagesize - 1)) / grn_pagesize; + size_t aligned_size; + if (npages >= (1LL<<32)) { + MERR("too long request size=%" GRN_FMT_SIZE, size); + return NULL; + } + for (;;) { + if (++i >= GRN_CTX_N_SEGMENTS) { + MERR("all segments are full"); + return NULL; + } + mi++; + if (!mi->map) { break; } + } + aligned_size = grn_pagesize * ((size_t)npages); + if (!grn_io_anon_map(ctx, mi, aligned_size)) { return NULL; } + mi->nref = (uint32_t) npages; + mi->count = GRN_CTX_SEGMENT_VLEN|GRN_CTX_SEGMENT_LIFO; + ctx->impl->lifoseg = i; + return mi->map; + } else { + size = (size + ALIGN_MASK) & ~ALIGN_MASK; + if (i < 0 || (mi->count & GRN_CTX_SEGMENT_VLEN) || size + mi->nref > GRN_CTX_SEGMENT_SIZE) { + for (;;) { + if (++i >= GRN_CTX_N_SEGMENTS) { + MERR("all segments are full"); + return NULL; + } + if (!(++mi)->map) { break; } + } + if (!grn_io_anon_map(ctx, mi, GRN_CTX_SEGMENT_SIZE)) { return NULL; } + mi->nref = 0; + mi->count = GRN_CTX_SEGMENT_WORD|GRN_CTX_SEGMENT_LIFO; + ctx->impl->lifoseg = i; + } + { + uint32_t u = mi->nref; + mi->nref += size; + return (byte *)mi->map + u; + } + } + } +} + +void +grn_ctx_free_lifo(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func) +{ + if (!ctx) { return; } + if (!ctx->impl) { + ERR(GRN_INVALID_ARGUMENT,"ctx without impl passed."); + return; + } + { + int32_t i = ctx->impl->lifoseg, done = 0; + grn_io_mapinfo *mi = &ctx->impl->segs[i]; + if (i < 0) { + ERR(GRN_INVALID_ARGUMENT, "lifo buffer is void"); + return; + } + for (; i >= 0; i--, mi--) { + if (!(mi->count & GRN_CTX_SEGMENT_LIFO)) { continue; } + if (done) { break; } + if (mi->count & GRN_CTX_SEGMENT_VLEN) { + if (mi->map == ptr) { done = 1; } + grn_io_anon_unmap(ctx, mi, mi->nref * grn_pagesize); + mi->map = NULL; + } else { + if (mi->map == ptr) { + done = 1; + } else { + if (mi->map < ptr && ptr < (void *)((byte*)mi->map + mi->nref)) { + mi->nref = (uint32_t) ((uintptr_t)ptr - (uintptr_t)mi->map); + break; + } + } + grn_io_anon_unmap(ctx, mi, GRN_CTX_SEGMENT_SIZE); + mi->map = NULL; + } + } + ctx->impl->lifoseg = i; + } +} + +#if defined(USE_DYNAMIC_MALLOC_CHANGE) +grn_malloc_func +grn_ctx_get_malloc(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->malloc_func; +} + +void +grn_ctx_set_malloc(grn_ctx *ctx, grn_malloc_func malloc_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->malloc_func = malloc_func; +} + +grn_calloc_func +grn_ctx_get_calloc(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->calloc_func; +} + +void +grn_ctx_set_calloc(grn_ctx *ctx, grn_calloc_func calloc_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->calloc_func = calloc_func; +} + +grn_realloc_func +grn_ctx_get_realloc(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->realloc_func; +} + +void +grn_ctx_set_realloc(grn_ctx *ctx, grn_realloc_func realloc_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->realloc_func = realloc_func; +} + +grn_strdup_func +grn_ctx_get_strdup(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->strdup_func; +} + +void +grn_ctx_set_strdup(grn_ctx *ctx, grn_strdup_func strdup_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->strdup_func = strdup_func; +} + +grn_free_func +grn_ctx_get_free(grn_ctx *ctx) +{ + if (!ctx || !ctx->impl) { return NULL; } + return ctx->impl->free_func; +} + +void +grn_ctx_set_free(grn_ctx *ctx, grn_free_func free_func) +{ + if (!ctx || !ctx->impl) { return; } + ctx->impl->free_func = free_func; +} + +void * +grn_malloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->malloc_func) { + return ctx->impl->malloc_func(ctx, size, file, line, func); + } else { + return grn_malloc_default(ctx, size, file, line, func); + } +} + +void * +grn_calloc(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->calloc_func) { + return ctx->impl->calloc_func(ctx, size, file, line, func); + } else { + return grn_calloc_default(ctx, size, file, line, func); + } +} + +void * +grn_realloc(grn_ctx *ctx, void *ptr, size_t size, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->realloc_func) { + return ctx->impl->realloc_func(ctx, ptr, size, file, line, func); + } else { + return grn_realloc_default(ctx, ptr, size, file, line, func); + } +} + +char * +grn_strdup(grn_ctx *ctx, const char *string, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->strdup_func) { + return ctx->impl->strdup_func(ctx, string, file, line, func); + } else { + return grn_strdup_default(ctx, string, file, line, func); + } +} + +void +grn_free(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func) +{ + if (ctx && ctx->impl && ctx->impl->free_func) { + return ctx->impl->free_func(ctx, ptr, file, line, func); + } else { + return grn_free_default(ctx, ptr, file, line, func); + } +} +#endif + +void * +grn_malloc_default(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (!ctx) { return NULL; } + { + void *res = malloc(size); + if (res) { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } else { + if (!(res = malloc(size))) { + MERR("malloc fail (%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", + size, res, file, line, alloc_count); + } else { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } + } + return res; + } +} + +void * +grn_calloc_default(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (!ctx) { return NULL; } + { + void *res = calloc(size, 1); + if (res) { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } else { + if (!(res = calloc(size, 1))) { + MERR("calloc fail (%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", + size, res, file, line, alloc_count); + } else { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } + } + return res; + } +} + +void +grn_free_default(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func) +{ + if (!ctx) { return; } + grn_alloc_info_check(ctx, ptr); + { + free(ptr); + if (ptr) { + GRN_ADD_ALLOC_COUNT(-1); + } else { + GRN_LOG(ctx, GRN_LOG_ALERT, "free fail (%p) (%s:%d) <%d>", + ptr, file, line, alloc_count); + } + } +} + +void * +grn_realloc_default(grn_ctx *ctx, void *ptr, size_t size, + const char* file, int line, const char *func) +{ + void *res; + if (!ctx) { return NULL; } + if (size) { + if (!(res = realloc(ptr, size))) { + if (!(res = realloc(ptr, size))) { + MERR("realloc fail (%p,%" GRN_FMT_SIZE ")=%p (%s:%d) <%d>", + ptr, size, res, file, line, alloc_count); + return NULL; + } + } + if (ptr) { + grn_alloc_info_change(ptr, res, size); + } else { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, size, file, line, func); + } + } else { + if (!ptr) { return NULL; } + grn_alloc_info_check(ctx, ptr); + GRN_ADD_ALLOC_COUNT(-1); + free(ptr); + res = NULL; + } + return res; +} + +int +grn_alloc_count(void) +{ + return alloc_count; +} + +char * +grn_strdup_default(grn_ctx *ctx, const char *s, + const char* file, int line, const char *func) +{ + if (!ctx) { return NULL; } + { + char *res = grn_strdup_raw(s); + if (res) { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, strlen(res) + 1, file, line, func); + } else { + if (!(res = grn_strdup_raw(s))) { + MERR("strdup(%p)=%p (%s:%d) <%d>", s, res, file, line, alloc_count); + } else { + GRN_ADD_ALLOC_COUNT(1); + grn_alloc_info_add(res, strlen(res) + 1, file, line, func); + } + } + return res; + } +} + +#ifdef USE_FAIL_MALLOC +int +grn_fail_malloc_check(size_t size, + const char *file, int line, const char *func) +{ + if ((grn_fmalloc_file && strcmp(file, grn_fmalloc_file)) || + (grn_fmalloc_line && line != grn_fmalloc_line) || + (grn_fmalloc_func && strcmp(func, grn_fmalloc_func))) { + return 1; + } + if (grn_fmalloc_prob && grn_fmalloc_prob >= rand()) { + return 0; + } + return 1; +} + +void * +grn_malloc_fail(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (grn_fail_malloc_check(size, file, line, func)) { + return grn_malloc_default(ctx, size, file, line, func); + } else { + MERR("fail_malloc (%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", + size, file, line, func, alloc_count); + return NULL; + } +} + +void * +grn_calloc_fail(grn_ctx *ctx, size_t size, + const char* file, int line, const char *func) +{ + if (grn_fail_malloc_check(size, file, line, func)) { + return grn_calloc_default(ctx, size, file, line, func); + } else { + MERR("fail_calloc (%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", + size, file, line, func, alloc_count); + return NULL; + } +} + +void * +grn_realloc_fail(grn_ctx *ctx, void *ptr, size_t size, + const char* file, int line, const char *func) +{ + if (grn_fail_malloc_check(size, file, line, func)) { + return grn_realloc_default(ctx, ptr, size, file, line, func); + } else { + MERR("fail_realloc (%p,%" GRN_FMT_SIZE ") (%s:%d@%s) <%d>", + ptr, size, file, line, func, alloc_count); + return NULL; + } +} + +char * +grn_strdup_fail(grn_ctx *ctx, const char *s, + const char* file, int line, const char *func) +{ + if (grn_fail_malloc_check(strlen(s), file, line, func)) { + return grn_strdup_default(ctx, s, file, line, func); + } else { + MERR("fail_strdup(%p) (%s:%d@%s) <%d>", s, file, line, func, alloc_count); + return NULL; + } +} +#endif /* USE_FAIL_MALLOC */ diff --git a/storage/mroonga/vendor/groonga/lib/arrow.cpp b/storage/mroonga/vendor/groonga/lib/arrow.cpp new file mode 100644 index 00000000..5f022ed1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/arrow.cpp @@ -0,0 +1,849 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_db.h" + +#ifdef GRN_WITH_ARROW +#include + +#include +#include +#include + +#include + +namespace grnarrow { + grn_rc status_to_rc(arrow::Status &status) { + switch (status.code()) { + case arrow::StatusCode::OK: + return GRN_SUCCESS; + case arrow::StatusCode::OutOfMemory: + return GRN_NO_MEMORY_AVAILABLE; + case arrow::StatusCode::KeyError: + return GRN_INVALID_ARGUMENT; // TODO + case arrow::StatusCode::TypeError: + return GRN_INVALID_ARGUMENT; // TODO + case arrow::StatusCode::Invalid: + return GRN_INVALID_ARGUMENT; + case arrow::StatusCode::IOError: + return GRN_INPUT_OUTPUT_ERROR; + case arrow::StatusCode::UnknownError: + return GRN_UNKNOWN_ERROR; + case arrow::StatusCode::NotImplemented: + return GRN_FUNCTION_NOT_IMPLEMENTED; + default: + return GRN_UNKNOWN_ERROR; + } + } + + grn_bool check_status(grn_ctx *ctx, + arrow::Status &status, + const char *context) { + if (status.ok()) { + return GRN_TRUE; + } else { + auto rc = status_to_rc(status); + auto message = status.ToString(); + ERR(rc, "%s: %s", context, message.c_str()); + return GRN_FALSE; + } + } + + grn_bool check_status(grn_ctx *ctx, + arrow::Status &status, + std::ostream &output) { + return check_status(ctx, + status, + static_cast(output).str().c_str()); + } + + class ColumnLoadVisitor : public arrow::ArrayVisitor { + public: + ColumnLoadVisitor(grn_ctx *ctx, + grn_obj *grn_table, + std::shared_ptr &arrow_column, + const grn_id *ids) + : ctx_(ctx), + grn_table_(grn_table), + ids_(ids), + time_unit_(arrow::TimeUnit::SECOND) { + auto column_name = arrow_column->name(); + grn_column_ = grn_obj_column(ctx_, grn_table_, + column_name.data(), + column_name.size()); + + auto arrow_type = arrow_column->type(); + grn_id type_id; + switch (arrow_type->id()) { + case arrow::Type::BOOL : + type_id = GRN_DB_BOOL; + break; + case arrow::Type::UINT8 : + type_id = GRN_DB_UINT8; + break; + case arrow::Type::INT8 : + type_id = GRN_DB_INT8; + break; + case arrow::Type::UINT16 : + type_id = GRN_DB_UINT16; + break; + case arrow::Type::INT16 : + type_id = GRN_DB_INT16; + break; + case arrow::Type::UINT32 : + type_id = GRN_DB_UINT32; + break; + case arrow::Type::INT32 : + type_id = GRN_DB_INT32; + break; + case arrow::Type::UINT64 : + type_id = GRN_DB_UINT64; + break; + case arrow::Type::INT64 : + type_id = GRN_DB_INT64; + break; + case arrow::Type::HALF_FLOAT : + case arrow::Type::FLOAT : + case arrow::Type::DOUBLE : + type_id = GRN_DB_FLOAT; + break; + case arrow::Type::STRING : + type_id = GRN_DB_TEXT; + break; + case arrow::Type::DATE64 : + type_id = GRN_DB_TIME; + break; + case arrow::Type::TIMESTAMP : + type_id = GRN_DB_TIME; + { + auto arrow_timestamp_type = + std::static_pointer_cast(arrow_type); + time_unit_ = arrow_timestamp_type->unit(); + } + break; + default : + type_id = GRN_DB_VOID; + break; + } + + if (type_id == GRN_DB_VOID) { + // TODO + return; + } + + if (!grn_column_) { + grn_column_ = grn_column_create(ctx_, + grn_table_, + column_name.data(), + column_name.size(), + NULL, + GRN_OBJ_COLUMN_SCALAR, + grn_ctx_at(ctx_, type_id)); + } + if (type_id == GRN_DB_TEXT) { + GRN_TEXT_INIT(&buffer_, GRN_OBJ_DO_SHALLOW_COPY); + } else { + GRN_VALUE_FIX_SIZE_INIT(&buffer_, 0, type_id); + } + } + + ~ColumnLoadVisitor() { + if (grn_obj_is_accessor(ctx_, grn_column_)) { + grn_obj_unlink(ctx_, grn_column_); + } + GRN_OBJ_FIN(ctx_, &buffer_); + } + + arrow::Status Visit(const arrow::BooleanArray &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::Int8Array &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::UInt8Array &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::Int16Array &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::UInt16Array &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::Int32Array &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::UInt32Array &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::Int64Array &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::UInt64Array &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::HalfFloatArray &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::FloatArray &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::DoubleArray &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::StringArray &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::Date64Array &array) { + return set_values(array); + } + + arrow::Status Visit(const arrow::TimestampArray &array) { + return set_values(array); + } + + private: + grn_ctx *ctx_; + grn_obj *grn_table_; + const grn_id *ids_; + arrow::TimeUnit::type time_unit_; + grn_obj *grn_column_; + grn_obj buffer_; + + template + arrow::Status set_values(const T &array) { + int64_t n_rows = array.length(); + for (int i = 0; i < n_rows; ++i) { + auto id = ids_[i]; + GRN_BULK_REWIND(&buffer_); + get_value(array, i); + grn_obj_set_value(ctx_, grn_column_, id, &buffer_, GRN_OBJ_SET); + } + return arrow::Status::OK(); + } + + void + get_value(const arrow::BooleanArray &array, int i) { + GRN_BOOL_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::UInt8Array &array, int i) { + GRN_UINT8_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::Int8Array &array, int i) { + GRN_INT8_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::UInt16Array &array, int i) { + GRN_UINT16_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::Int16Array &array, int i) { + GRN_INT16_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::UInt32Array &array, int i) { + GRN_UINT32_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::Int32Array &array, int i) { + GRN_INT32_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::UInt64Array &array, int i) { + GRN_UINT64_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::Int64Array &array, int i) { + GRN_INT64_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::HalfFloatArray &array, int i) { + GRN_FLOAT_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::FloatArray &array, int i) { + GRN_FLOAT_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::DoubleArray &array, int i) { + GRN_FLOAT_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::StringArray &array, int i) { + int32_t size; + const auto data = array.GetValue(i, &size); + GRN_TEXT_SET(ctx_, &buffer_, data, size); + } + + void + get_value(const arrow::Date64Array &array, int i) { + GRN_TIME_SET(ctx_, &buffer_, array.Value(i)); + } + + void + get_value(const arrow::TimestampArray &array, int i) { + switch (time_unit_) { + case arrow::TimeUnit::SECOND : + GRN_TIME_SET(ctx_, &buffer_, GRN_TIME_PACK(array.Value(i), 0)); + break; + case arrow::TimeUnit::MILLI : + GRN_TIME_SET(ctx_, &buffer_, array.Value(i) * 1000); + break; + case arrow::TimeUnit::MICRO : + GRN_TIME_SET(ctx_, &buffer_, array.Value(i)); + break; + case arrow::TimeUnit::NANO : + GRN_TIME_SET(ctx_, &buffer_, array.Value(i) / 1000); + break; + } + } + }; + + class FileLoader { + public: + FileLoader(grn_ctx *ctx, grn_obj *grn_table) + : ctx_(ctx), + grn_table_(grn_table), + key_column_name_("") { + } + + ~FileLoader() { + } + + grn_rc load_table(const std::shared_ptr &arrow_table) { + int n_columns = arrow_table->num_columns(); + + if (key_column_name_.empty()) { + grn_obj ids; + GRN_RECORD_INIT(&ids, GRN_OBJ_VECTOR, grn_obj_id(ctx_, grn_table_)); + auto n_records = arrow_table->num_rows(); + for (int64_t i = 0; i < n_records; ++i) { + auto id = grn_table_add(ctx_, grn_table_, NULL, 0, NULL); + GRN_RECORD_PUT(ctx_, &ids, id); + } + for (int i = 0; i < n_columns; ++i) { + int64_t offset = 0; + auto arrow_column = arrow_table->column(i); + auto arrow_chunked_data = arrow_column->data(); + for (auto arrow_array : arrow_chunked_data->chunks()) { + grn_id *sub_ids = + reinterpret_cast(GRN_BULK_HEAD(&ids)) + offset; + ColumnLoadVisitor visitor(ctx_, + grn_table_, + arrow_column, + sub_ids); + arrow_array->Accept(&visitor); + offset += arrow_array->length(); + } + } + GRN_OBJ_FIN(ctx_, &ids); + } else { + auto status = arrow::Status::NotImplemented("_key isn't supported yet"); + check_status(ctx_, status, "[arrow][load]"); + } + return ctx_->rc; + }; + + grn_rc load_record_batch(const std::shared_ptr &arrow_record_batch) { + std::shared_ptr arrow_table; + std::vector> arrow_record_batches(1); + arrow_record_batches[0] = arrow_record_batch; + auto status = + arrow::Table::FromRecordBatches(arrow_record_batches, &arrow_table); + if (!check_status(ctx_, + status, + "[arrow][load] " + "failed to convert record batch to table")) { + return ctx_->rc; + } + return load_table(arrow_table); + }; + + private: + grn_ctx *ctx_; + grn_obj *grn_table_; + std::string key_column_name_; + }; + + class FileDumper { + public: + FileDumper(grn_ctx *ctx, grn_obj *grn_table, grn_obj *grn_columns) + : ctx_(ctx), + grn_table_(grn_table), + grn_columns_(grn_columns) { + } + + ~FileDumper() { + } + + grn_rc dump(arrow::io::OutputStream *output) { + std::vector> fields; + auto n_columns = GRN_BULK_VSIZE(grn_columns_) / sizeof(grn_obj *); + for (auto i = 0; i < n_columns; ++i) { + auto column = GRN_PTR_VALUE_AT(grn_columns_, i); + + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + column_name_size = + grn_column_name(ctx_, column, column_name, GRN_TABLE_MAX_KEY_SIZE); + std::string field_name(column_name, column_name_size); + std::shared_ptr field_type; + switch (grn_obj_get_range(ctx_, column)) { + case GRN_DB_BOOL : + field_type = arrow::boolean(); + break; + case GRN_DB_UINT8 : + field_type = arrow::uint8(); + break; + case GRN_DB_INT8 : + field_type = arrow::int8(); + break; + case GRN_DB_UINT16 : + field_type = arrow::uint16(); + break; + case GRN_DB_INT16 : + field_type = arrow::int16(); + break; + case GRN_DB_UINT32 : + field_type = arrow::uint32(); + break; + case GRN_DB_INT32 : + field_type = arrow::int32(); + break; + case GRN_DB_UINT64 : + field_type = arrow::uint64(); + break; + case GRN_DB_INT64 : + field_type = arrow::int64(); + break; + case GRN_DB_FLOAT : + field_type = arrow::float64(); + break; + case GRN_DB_TIME : + field_type = + std::make_shared(arrow::TimeUnit::MICRO); + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + field_type = arrow::utf8(); + break; + default : + break; + } + if (!field_type) { + continue; + } + + auto field = std::make_shared(field_name, + field_type, + false); + fields.push_back(field); + }; + + auto schema = std::make_shared(fields); + + std::shared_ptr writer; + auto status = + arrow::ipc::RecordBatchFileWriter::Open(output, schema, &writer); + if (!check_status(ctx_, + status, + "[arrow][dump] failed to create file format writer")) { + return ctx_->rc; + } + + std::vector ids; + int n_records_per_batch = 1000; + GRN_TABLE_EACH_BEGIN(ctx_, grn_table_, table_cursor, record_id) { + ids.push_back(record_id); + if (ids.size() == n_records_per_batch) { + write_record_batch(ids, schema, writer); + ids.clear(); + } + } GRN_TABLE_EACH_END(ctx_, table_cursor); + if (!ids.empty()) { + write_record_batch(ids, schema, writer); + } + writer->Close(); + + return ctx_->rc; + } + + private: + grn_ctx *ctx_; + grn_obj *grn_table_; + grn_obj *grn_columns_; + + void write_record_batch(std::vector &ids, + std::shared_ptr &schema, + std::shared_ptr &writer) { + std::vector> columns; + auto n_columns = GRN_BULK_VSIZE(grn_columns_) / sizeof(grn_obj *); + for (auto i = 0; i < n_columns; ++i) { + auto grn_column = GRN_PTR_VALUE_AT(grn_columns_, i); + + arrow::Status status; + std::shared_ptr column; + + switch (grn_obj_get_range(ctx_, grn_column)) { + case GRN_DB_BOOL : + status = build_boolean_array(ids, grn_column, &column); + break; + case GRN_DB_UINT8 : + status = build_uint8_array(ids, grn_column, &column); + break; + case GRN_DB_INT8 : + status = build_int8_array(ids, grn_column, &column); + break; + case GRN_DB_UINT16 : + status = build_uint16_array(ids, grn_column, &column); + break; + case GRN_DB_INT16 : + status = build_int16_array(ids, grn_column, &column); + break; + case GRN_DB_UINT32 : + status = build_uint32_array(ids, grn_column, &column); + break; + case GRN_DB_INT32 : + status = build_int32_array(ids, grn_column, &column); + break; + case GRN_DB_UINT64 : + status = build_uint64_array(ids, grn_column, &column); + break; + case GRN_DB_INT64 : + status = build_int64_array(ids, grn_column, &column); + break; + case GRN_DB_FLOAT : + status = build_double_array(ids, grn_column, &column); + break; + case GRN_DB_TIME : + status = build_timestamp_array(ids, grn_column, &column); + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + status = build_utf8_array(ids, grn_column, &column); + break; + default : + status = + arrow::Status::NotImplemented("[arrow][dumper] not supported type: TODO"); + break; + } + if (!status.ok()) { + continue; + } + columns.push_back(column); + } + + arrow::RecordBatch record_batch(schema, ids.size(), columns); + writer->WriteRecordBatch(record_batch); + } + + arrow::Status build_boolean_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::BooleanBuilder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + + arrow::Status build_uint8_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::UInt8Builder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + + arrow::Status build_int8_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::Int8Builder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + + arrow::Status build_uint16_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::UInt16Builder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + + arrow::Status build_int16_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::Int16Builder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + + arrow::Status build_uint32_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::UInt32Builder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + + arrow::Status build_int32_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::Int32Builder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + arrow::Status build_uint64_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::UInt64Builder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + + arrow::Status build_int64_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::Int64Builder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + + arrow::Status build_double_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::DoubleBuilder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(*(reinterpret_cast(data))); + } + return builder.Finish(array); + } + + arrow::Status build_timestamp_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + auto timestamp_ns_data_type = + std::make_shared(arrow::TimeUnit::MICRO); + arrow::TimestampBuilder builder(arrow::default_memory_pool(), + timestamp_ns_data_type); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + auto timestamp_ns = *(reinterpret_cast(data)); + builder.Append(timestamp_ns); + } + return builder.Finish(array); + } + + arrow::Status build_utf8_array(std::vector &ids, + grn_obj *grn_column, + std::shared_ptr *array) { + arrow::StringBuilder builder(arrow::default_memory_pool()); + for (auto id : ids) { + uint32_t size; + auto data = grn_obj_get_value_(ctx_, grn_column, id, &size); + builder.Append(data, size); + } + return builder.Finish(array); + } + }; +} +#endif /* GRN_WITH_ARROW */ + +extern "C" { +grn_rc +grn_arrow_load(grn_ctx *ctx, + grn_obj *table, + const char *path) +{ + GRN_API_ENTER; +#ifdef GRN_WITH_ARROW + std::shared_ptr input; + auto status = + arrow::io::MemoryMappedFile::Open(path, arrow::io::FileMode::READ, &input); + if (!grnarrow::check_status(ctx, + status, + std::ostringstream() << + "[arrow][load] failed to open path: " << + "<" << path << ">")) { + GRN_API_RETURN(ctx->rc); + } + std::shared_ptr reader; + status = arrow::ipc::RecordBatchFileReader::Open(input, &reader); + if (!grnarrow::check_status(ctx, + status, + "[arrow][load] " + "failed to create file format reader")) { + GRN_API_RETURN(ctx->rc); + } + + grnarrow::FileLoader loader(ctx, table); + int n_record_batches = reader->num_record_batches(); + for (int i = 0; i < n_record_batches; ++i) { + std::shared_ptr record_batch; + status = reader->ReadRecordBatch(i, &record_batch); + if (!grnarrow::check_status(ctx, + status, + std::ostringstream("") << + "[arrow][load] failed to get " << + "the " << i << "-th " << "record")) { + break; + } + loader.load_record_batch(record_batch); + if (ctx->rc != GRN_SUCCESS) { + break; + } + } +#else /* GRN_WITH_ARROW */ + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "[arrow][load] Apache Arrow support isn't enabled"); +#endif /* GRN_WITH_ARROW */ + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_arrow_dump(grn_ctx *ctx, + grn_obj *table, + const char *path) +{ + GRN_API_ENTER; +#ifdef GRN_WITH_ARROW + auto all_columns = + grn_hash_create(ctx, + NULL, + sizeof(grn_id), + 0, + GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); + grn_table_columns(ctx, + table, + "", 0, + reinterpret_cast(all_columns)); + + grn_obj columns; + GRN_PTR_INIT(&columns, GRN_OBJ_VECTOR, GRN_ID_NIL); + GRN_HASH_EACH_BEGIN(ctx, all_columns, cursor, id) { + void *key; + grn_hash_cursor_get_key(ctx, cursor, &key); + auto column_id = static_cast(key); + auto column = grn_ctx_at(ctx, *column_id); + GRN_PTR_PUT(ctx, &columns, column); + } GRN_HASH_EACH_END(ctx, cursor); + grn_hash_close(ctx, all_columns); + + grn_arrow_dump_columns(ctx, table, &columns, path); + GRN_OBJ_FIN(ctx, &columns); +#else /* GRN_WITH_ARROW */ + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "[arrow][dump] Apache Arrow support isn't enabled"); +#endif /* GRN_WITH_ARROW */ + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_arrow_dump_columns(grn_ctx *ctx, + grn_obj *table, + grn_obj *columns, + const char *path) +{ + GRN_API_ENTER; +#ifdef GRN_WITH_ARROW + std::shared_ptr output; + auto status = arrow::io::FileOutputStream::Open(path, &output); + if (!grnarrow::check_status(ctx, + status, + std::stringstream() << + "[arrow][dump] failed to open path: " << + "<" << path << ">")) { + GRN_API_RETURN(ctx->rc); + } + + grnarrow::FileDumper dumper(ctx, table, columns); + dumper.dump(output.get()); +#else /* GRN_WITH_ARROW */ + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "[arrow][dump] Apache Arrow support isn't enabled"); +#endif /* GRN_WITH_ARROW */ + GRN_API_RETURN(ctx->rc); +} +} diff --git a/storage/mroonga/vendor/groonga/lib/c_sources.am b/storage/mroonga/vendor/groonga/lib/c_sources.am new file mode 100644 index 00000000..3b76e693 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/c_sources.am @@ -0,0 +1,112 @@ +libgroonga_c_sources = \ + alloc.c \ + grn_alloc.h \ + cache.c \ + grn_cache.h \ + column.c \ + com.c \ + grn_com.h \ + command.c \ + config.c \ + grn_config.h \ + ctx.c \ + grn_ctx.h \ + grn_ctx_impl.h \ + ctx_impl_mrb.c \ + grn_ctx_impl_mrb.h \ + grn_dat.h \ + db.c \ + grn_db.h \ + dump.c \ + ts.c \ + grn_ts.h \ + type.c \ + error.c \ + grn_error.h \ + expr.c \ + grn_expr.h \ + expr_code.c \ + grn_expr_code.h \ + expr_executor.c \ + grn_expr_executor.h \ + file_lock.c \ + grn_file_lock.h \ + geo.c \ + grn_geo.h \ + grn.h \ + hash.c \ + grn_hash.h \ + id.c \ + ii.c \ + grn_ii.h \ + index_column.c \ + grn_index_column.h \ + io.c \ + grn_io.h \ + load.c \ + grn_load.h \ + logger.c \ + grn_logger.h \ + mrb.c \ + grn_mrb.h \ + grn_msgpack.h \ + nfkc.c \ + grn_nfkc.h \ + nfkc50.c \ + normalizer.c \ + grn_normalizer.h \ + obj.c \ + grn_obj.h \ + operator.c \ + output.c \ + grn_output.h \ + pat.c \ + grn_pat.h \ + plugin.c \ + grn_plugin.h \ + proc.c \ + grn_proc.h \ + raw_string.c \ + grn_raw_string.h \ + report.c \ + grn_report.h \ + request_canceler.c \ + grn_request_canceler.h \ + request_timer.c \ + grn_request_timer.h \ + rset.c \ + grn_rset.h \ + scanner.c \ + grn_scanner.h \ + scorer.c \ + grn_scorer.h \ + scorers.c \ + grn_scorers.h \ + snip.c \ + grn_snip.h \ + store.c \ + grn_store.h \ + str.c \ + grn_str.h \ + string.c \ + grn_string.h \ + table.c \ + thread.c \ + time.c \ + grn_time.h \ + token_cursor.c \ + grn_token_cursor.h \ + tokenizer.c \ + tokenizers.c \ + grn_tokenizers.h \ + token_filter.c \ + util.c \ + grn_util.h \ + windows.c \ + grn_windows.h \ + windows_event_logger.c \ + file_reader.c \ + window_function.c \ + grn_window_function.h \ + window_functions.c \ + grn_window_functions.h diff --git a/storage/mroonga/vendor/groonga/lib/cache.c b/storage/mroonga/vendor/groonga/lib/cache.c new file mode 100644 index 00000000..79a2c678 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/cache.c @@ -0,0 +1,1036 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_cache.h" +#include "grn_ctx.h" +#include "grn_ctx_impl.h" +#include "grn_hash.h" +#include "grn_pat.h" +#include "grn_store.h" +#include "grn_db.h" +#include "grn_file_lock.h" + +#include + +typedef struct _grn_cache_entry_memory grn_cache_entry_memory; + +struct _grn_cache_entry_memory { + grn_cache_entry_memory *next; + grn_cache_entry_memory *prev; + grn_obj *value; + grn_timeval tv; + grn_id id; +}; + +typedef struct _grn_cache_entry_persistent_data { + grn_id next; + grn_id prev; + grn_timeval modified_time; +} grn_cache_entry_persistent_data; + +/* + sizeof(grn_cache_entry_persistent_metadata) should be equal or smaller + than sizeof(grn_cache_entry_persistent_data). + */ +typedef struct _grn_cache_entry_persistent_metadata { + uint32_t max_nentries; + uint32_t nfetches; + uint32_t nhits; +} grn_cache_entry_persistent_metadata; + +typedef union _grn_cache_entry_persistent { + grn_cache_entry_persistent_data data; + grn_cache_entry_persistent_metadata metadata; +} grn_cache_entry_persistent; + +struct _grn_cache { + union { + struct { + grn_cache_entry_memory *next; + grn_cache_entry_memory *prev; + grn_hash *hash; + grn_mutex mutex; + uint32_t max_nentries; + uint32_t nfetches; + uint32_t nhits; + } memory; + struct { + grn_hash *keys; + grn_ja *values; + int timeout; + } persistent; + } impl; + grn_bool is_memory; + grn_ctx *ctx; +}; + +#define GRN_CACHE_PERSISTENT_ROOT_ID 1 +#define GRN_CACHE_PERSISTENT_ROOT_KEY "\0" +#define GRN_CACHE_PERSISTENT_ROOT_KEY_LEN \ + (sizeof(GRN_CACHE_PERSISTENT_ROOT_KEY) - 1) +#define GRN_CACHE_PERSISTENT_METADATA_ID 2 +#define GRN_CACHE_PERSISTENT_METADATA_KEY "\1" +#define GRN_CACHE_PERSISTENT_METADATA_KEY_LEN \ + (sizeof(GRN_CACHE_PERSISTENT_METADATA_KEY) - 1) + +static grn_ctx grn_cache_ctx; +static grn_cache *grn_cache_current = NULL; +static grn_cache *grn_cache_default = NULL; +static char grn_cache_default_base_path[PATH_MAX]; + +void +grn_set_default_cache_base_path(const char *base_path) +{ + if (base_path) { + grn_strcpy(grn_cache_default_base_path, + PATH_MAX, + base_path); + } else { + grn_cache_default_base_path[0] = '\0'; + } +} + +const char * +grn_get_default_cache_base_path(void) +{ + if (grn_cache_default_base_path[0] == '\0') { + return NULL; + } else { + return grn_cache_default_base_path; + } +} + +static void +grn_cache_open_memory(grn_ctx *ctx, grn_cache *cache) +{ + cache->impl.memory.next = (grn_cache_entry_memory *)cache; + cache->impl.memory.prev = (grn_cache_entry_memory *)cache; + cache->impl.memory.hash = grn_hash_create(cache->ctx, + NULL, + GRN_CACHE_MAX_KEY_SIZE, + sizeof(grn_cache_entry_memory), + GRN_OBJ_KEY_VAR_SIZE); + if (!cache->impl.memory.hash) { + ERR(GRN_NO_MEMORY_AVAILABLE, "[cache] failed to create hash table"); + return; + } + MUTEX_INIT(cache->impl.memory.mutex); + + cache->impl.memory.max_nentries = GRN_CACHE_DEFAULT_MAX_N_ENTRIES; + cache->impl.memory.nfetches = 0; + cache->impl.memory.nhits = 0; +} + +static void +grn_cache_open_persistent(grn_ctx *ctx, + grn_cache *cache, + const char *base_path) +{ + grn_file_lock file_lock; + char *keys_path = NULL; + char *values_path = NULL; + char lock_path_buffer[PATH_MAX]; + char keys_path_buffer[PATH_MAX]; + char values_path_buffer[PATH_MAX]; + + cache->impl.persistent.timeout = 1000; + + if (base_path) { + grn_snprintf(lock_path_buffer, PATH_MAX, PATH_MAX, "%s.lock", base_path); + grn_file_lock_init(ctx, &file_lock, lock_path_buffer); + } else { + grn_file_lock_init(ctx, &file_lock, NULL); + } + + if (base_path) { + struct stat stat_buffer; + + grn_snprintf(keys_path_buffer, PATH_MAX, PATH_MAX, "%s.keys", base_path); + grn_snprintf(values_path_buffer, PATH_MAX, PATH_MAX, "%s.values", base_path); + keys_path = keys_path_buffer; + values_path = values_path_buffer; + + if (!grn_file_lock_acquire(ctx, + &file_lock, + cache->impl.persistent.timeout, + "[cache][persistent][open]")) { + goto exit; + } + + if (stat(keys_path, &stat_buffer) == 0) { + cache->impl.persistent.keys = grn_hash_open(ctx, keys_path); + if (cache->impl.persistent.keys) { + cache->impl.persistent.values = grn_ja_open(ctx, values_path); + } + } + if (!cache->impl.persistent.keys) { + if (cache->impl.persistent.values) { + grn_ja_close(ctx, cache->impl.persistent.values); + cache->impl.persistent.values = NULL; + } + if (stat(keys_path, &stat_buffer) == 0) { + if (grn_hash_remove(ctx, keys_path) != GRN_SUCCESS) { + ERRNO_ERR("[cache][persistent] " + "failed to remove path for cache keys: <%s>", + keys_path); + goto exit; + } + } + if (stat(values_path, &stat_buffer) == 0) { + if (grn_ja_remove(ctx, values_path) != GRN_SUCCESS) { + ERRNO_ERR("[cache][persistent] " + "failed to remove path for cache values: <%s>", + values_path); + goto exit; + } + } + } + } + + if (!cache->impl.persistent.keys) { + cache->impl.persistent.keys = + grn_hash_create(ctx, + keys_path, + GRN_CACHE_MAX_KEY_SIZE, + sizeof(grn_cache_entry_persistent), + GRN_OBJ_KEY_VAR_SIZE); + if (!cache->impl.persistent.keys) { + ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc, + "[cache][persistent] failed to create cache keys storage: <%s>", + keys_path ? keys_path : "(memory)"); + goto exit; + } + cache->impl.persistent.values = + grn_ja_create(ctx, + values_path, + 1 << 16, + 0); + if (!cache->impl.persistent.values) { + grn_hash_close(ctx, cache->impl.persistent.keys); + ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc, + "[cache][persistent] failed to create cache values storage: <%s>", + values_path ? values_path : "(memory)"); + goto exit; + } + } + + { + grn_cache_entry_persistent *entry; + grn_id root_id; + int added; + + root_id = grn_hash_add(ctx, + cache->impl.persistent.keys, + GRN_CACHE_PERSISTENT_ROOT_KEY, + GRN_CACHE_PERSISTENT_ROOT_KEY_LEN, + (void **)&entry, + &added); + if (root_id != GRN_CACHE_PERSISTENT_ROOT_ID) { + grn_ja_close(ctx, cache->impl.persistent.values); + grn_hash_close(ctx, cache->impl.persistent.keys); + if (values_path) { + grn_ja_remove(ctx, values_path); + } + if (keys_path) { + grn_hash_remove(ctx, keys_path); + } + ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc, + "[cache][persistent] broken cache keys storage: broken root: <%s>", + keys_path ? keys_path : "(memory)"); + return; + } + + if (added) { + entry->data.next = root_id; + entry->data.prev = root_id; + entry->data.modified_time.tv_sec = 0; + entry->data.modified_time.tv_nsec = 0; + } + } + + { + grn_cache_entry_persistent *entry; + grn_id metadata_id; + int added; + + metadata_id = grn_hash_add(ctx, + cache->impl.persistent.keys, + GRN_CACHE_PERSISTENT_METADATA_KEY, + GRN_CACHE_PERSISTENT_METADATA_KEY_LEN, + (void **)&entry, + &added); + if (metadata_id != GRN_CACHE_PERSISTENT_METADATA_ID) { + grn_ja_close(ctx, cache->impl.persistent.values); + grn_hash_close(ctx, cache->impl.persistent.keys); + if (values_path) { + grn_ja_remove(ctx, values_path); + } + if (keys_path) { + grn_hash_remove(ctx, keys_path); + } + ERR(ctx->rc == GRN_SUCCESS ? GRN_FILE_CORRUPT : ctx->rc, + "[cache][persistent] broken cache keys storage: broken metadata: <%s>", + keys_path ? keys_path : "(memory)"); + goto exit; + } + + if (added) { + entry->metadata.max_nentries = GRN_CACHE_DEFAULT_MAX_N_ENTRIES; + entry->metadata.nfetches = 0; + entry->metadata.nhits = 0; + } + } + +exit : + grn_file_lock_release(ctx, &file_lock); + grn_file_lock_fin(ctx, &file_lock); +} + +static grn_cache * +grn_cache_open_raw(grn_ctx *ctx, + grn_bool is_memory, + const char *base_path) +{ + grn_cache *cache = NULL; + + GRN_API_ENTER; + cache = GRN_CALLOC(sizeof(grn_cache)); + if (!cache) { + ERR(GRN_NO_MEMORY_AVAILABLE, "[cache] failed to allocate grn_cache"); + goto exit; + } + + cache->ctx = ctx; + cache->is_memory = is_memory; + if (cache->is_memory) { + grn_cache_open_memory(ctx, cache); + } else { + grn_cache_open_persistent(ctx, cache, base_path); + } + if (ctx->rc != GRN_SUCCESS) { + GRN_FREE(cache); + cache = NULL; + goto exit; + } + +exit : + GRN_API_RETURN(cache); +} + +grn_cache * +grn_cache_open(grn_ctx *ctx) +{ + const char *base_path = NULL; + grn_bool is_memory; + + if (grn_cache_default_base_path[0] != '\0') { + base_path = grn_cache_default_base_path; + } + + if (base_path) { + is_memory = GRN_FALSE; + } else { + char grn_cache_type_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_CACHE_TYPE", grn_cache_type_env, GRN_ENV_BUFFER_SIZE); + if (strcmp(grn_cache_type_env, "persistent") == 0) { + is_memory = GRN_FALSE; + } else { + is_memory = GRN_TRUE; + } + } + + return grn_cache_open_raw(ctx, is_memory, base_path); +} + +grn_cache * +grn_persistent_cache_open(grn_ctx *ctx, const char *base_path) +{ + grn_bool is_memory = GRN_FALSE; + return grn_cache_open_raw(ctx, is_memory, base_path); +} + + +static void +grn_cache_close_memory(grn_ctx *ctx, grn_cache *cache) +{ + grn_cache_entry_memory *vp; + + GRN_HASH_EACH(ctx, cache->impl.memory.hash, id, NULL, NULL, &vp, { + grn_obj_close(ctx, vp->value); + }); + grn_hash_close(ctx, cache->impl.memory.hash); + MUTEX_FIN(cache->impl.memory.mutex); +} + +static void +grn_cache_close_persistent(grn_ctx *ctx, grn_cache *cache) +{ + grn_hash_close(ctx, cache->impl.persistent.keys); + grn_ja_close(ctx, cache->impl.persistent.values); +} + +grn_rc +grn_cache_close(grn_ctx *ctx_not_used, grn_cache *cache) +{ + grn_ctx *ctx = cache->ctx; + + GRN_API_ENTER; + + if (cache->is_memory) { + grn_cache_close_memory(ctx, cache); + } else { + grn_cache_close_persistent(ctx, cache); + } + GRN_FREE(cache); + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_cache_current_set(grn_ctx *ctx, grn_cache *cache) +{ + grn_cache_current = cache; + return GRN_SUCCESS; +} + +grn_cache * +grn_cache_current_get(grn_ctx *ctx) +{ + return grn_cache_current; +} + +void +grn_cache_init(void) +{ + grn_ctx *ctx = &grn_cache_ctx; + + grn_ctx_init(ctx, 0); + + grn_cache_default = grn_cache_open(ctx); + grn_cache_current_set(ctx, grn_cache_default); +} + +grn_rc +grn_cache_default_reopen(void) +{ + grn_ctx *ctx = &grn_cache_ctx; + grn_cache *new_default; + grn_bool default_is_current; + + GRN_API_ENTER; + + new_default = grn_cache_open(ctx); + if (!new_default) { + GRN_API_RETURN(ctx->rc); + } + + default_is_current = (grn_cache_default == grn_cache_current_get(ctx)); + if (default_is_current) { + grn_cache_current_set(ctx, new_default); + } + + if (grn_cache_default) { + grn_cache_close(ctx, grn_cache_default); + } + grn_cache_default = new_default; + + GRN_API_RETURN(ctx->rc); +} + +static void +grn_cache_expire_entry_memory(grn_cache *cache, grn_cache_entry_memory *ce) +{ + ce->prev->next = ce->next; + ce->next->prev = ce->prev; + grn_obj_close(cache->ctx, ce->value); + grn_hash_delete_by_id(cache->ctx, cache->impl.memory.hash, ce->id, NULL); +} + +static void +grn_cache_entry_persistent_delete_link(grn_cache *cache, + grn_cache_entry_persistent *entry) +{ + grn_ctx *ctx = cache->ctx; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *prev_entry; + grn_cache_entry_persistent *next_entry; + + prev_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + entry->data.prev, + NULL); + next_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + entry->data.next, + NULL); + prev_entry->data.next = entry->data.next; + next_entry->data.prev = entry->data.prev; +} + +static void +grn_cache_entry_persistent_prepend_link(grn_cache *cache, + grn_cache_entry_persistent *entry, + grn_id entry_id, + grn_cache_entry_persistent *head_entry, + grn_id head_entry_id) +{ + grn_ctx *ctx = cache->ctx; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *head_next_entry; + + entry->data.next = head_entry->data.next; + entry->data.prev = head_entry_id; + head_next_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + head_entry->data.next, + NULL); + head_next_entry->data.prev = entry_id; + head_entry->data.next = entry_id; +} + +static void +grn_cache_expire_entry_persistent(grn_cache *cache, + grn_cache_entry_persistent *entry, + grn_id cache_id) +{ + grn_hash *keys = cache->impl.persistent.keys; + grn_ja *values = cache->impl.persistent.values; + + grn_cache_entry_persistent_delete_link(cache, entry); + grn_ja_put(cache->ctx, values, cache_id, NULL, 0, GRN_OBJ_SET, NULL); + grn_hash_delete_by_id(cache->ctx, keys, cache_id, NULL); +} + +static void +grn_cache_expire_memory_without_lock(grn_cache *cache, int32_t size) +{ + grn_cache_entry_memory *ce0 = + (grn_cache_entry_memory *)(&(cache->impl.memory)); + while (ce0 != ce0->prev && size--) { + grn_cache_expire_entry_memory(cache, ce0->prev); + } +} + +static void +grn_cache_expire_persistent_without_lock(grn_cache *cache, int32_t size) +{ + grn_ctx *ctx = cache->ctx; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *head_entry; + + head_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_ROOT_ID, + NULL); + while (head_entry->data.prev != GRN_CACHE_PERSISTENT_ROOT_ID && + size > 0) { + grn_cache_entry_persistent *tail_entry; + tail_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + head_entry->data.prev, + NULL); + grn_cache_expire_entry_persistent(cache, tail_entry, head_entry->data.prev); + size--; + } +} + +static grn_rc +grn_cache_set_max_n_entries_memory(grn_ctx *ctx, + grn_cache *cache, + unsigned int n) +{ + uint32_t current_max_n_entries; + + MUTEX_LOCK(cache->impl.memory.mutex); + current_max_n_entries = cache->impl.memory.max_nentries; + cache->impl.memory.max_nentries = n; + if (n < current_max_n_entries) { + grn_cache_expire_memory_without_lock(cache, current_max_n_entries - n); + } + MUTEX_UNLOCK(cache->impl.memory.mutex); + + return GRN_SUCCESS; +} + +static grn_rc +grn_cache_set_max_n_entries_persistent(grn_ctx *ctx, + grn_cache *cache, + unsigned int n) +{ + grn_rc rc; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *metadata_entry; + uint32_t current_max_n_entries; + + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); + if (rc != GRN_SUCCESS) { + return rc; + } + + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + + current_max_n_entries = metadata_entry->metadata.max_nentries; + metadata_entry->metadata.max_nentries = n; + if (n < current_max_n_entries) { + grn_cache_expire_persistent_without_lock(cache, current_max_n_entries - n); + } + grn_io_unlock(keys->io); + + return GRN_SUCCESS; +} + +grn_rc +grn_cache_set_max_n_entries(grn_ctx *ctx, grn_cache *cache, unsigned int n) +{ + if (!cache) { + return GRN_INVALID_ARGUMENT; + } + + if (cache->is_memory) { + return grn_cache_set_max_n_entries_memory(cache->ctx, cache, n); + } else { + return grn_cache_set_max_n_entries_persistent(cache->ctx, cache, n); + } +} + +static uint32_t +grn_cache_get_max_n_entries_memory(grn_ctx *ctx, grn_cache *cache) +{ + return cache->impl.memory.max_nentries; +} + +static uint32_t +grn_cache_get_max_n_entries_persistent(grn_ctx *ctx, grn_cache *cache) +{ + grn_rc rc; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *metadata_entry; + uint32_t current_max_n_entries; + + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); + if (rc != GRN_SUCCESS) { + return 0; + } + + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + current_max_n_entries = metadata_entry->metadata.max_nentries; + grn_io_unlock(keys->io); + + return current_max_n_entries; +} + +uint32_t +grn_cache_get_max_n_entries(grn_ctx *ctx, grn_cache *cache) +{ + if (!cache) { + return 0; + } + + if (cache->is_memory) { + return grn_cache_get_max_n_entries_memory(cache->ctx, cache); + } else { + return grn_cache_get_max_n_entries_persistent(cache->ctx, cache); + } +} + +static void +grn_cache_get_statistics_memory(grn_ctx *ctx, grn_cache *cache, + grn_cache_statistics *statistics) +{ + MUTEX_LOCK(cache->impl.memory.mutex); + statistics->nentries = GRN_HASH_SIZE(cache->impl.memory.hash); + statistics->max_nentries = cache->impl.memory.max_nentries; + statistics->nfetches = cache->impl.memory.nfetches; + statistics->nhits = cache->impl.memory.nhits; + MUTEX_UNLOCK(cache->impl.memory.mutex); +} + +static void +grn_cache_get_statistics_persistent(grn_ctx *ctx, grn_cache *cache, + grn_cache_statistics *statistics) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_hash *keys = cache->impl.persistent.keys; + grn_cache_entry_persistent *metadata_entry; + + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); + if (rc != GRN_SUCCESS) { + return; + } + + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + + statistics->nentries = GRN_HASH_SIZE(keys); + statistics->max_nentries = metadata_entry->metadata.max_nentries; + statistics->nfetches = metadata_entry->metadata.nfetches; + statistics->nhits = metadata_entry->metadata.nhits; + + grn_io_unlock(keys->io); +} + +void +grn_cache_get_statistics(grn_ctx *ctx, grn_cache *cache, + grn_cache_statistics *statistics) +{ + if (cache->is_memory) { + return grn_cache_get_statistics_memory(ctx, cache, statistics); + } else { + return grn_cache_get_statistics_persistent(ctx, cache, statistics); + } +} + +static grn_rc +grn_cache_fetch_memory(grn_ctx *ctx, grn_cache *cache, + const char *key, uint32_t key_len, + grn_obj *output) +{ + /* TODO: How about GRN_NOT_FOUND? */ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_cache_entry_memory *ce; + + MUTEX_LOCK(cache->impl.memory.mutex); + cache->impl.memory.nfetches++; + if (grn_hash_get(cache->ctx, cache->impl.memory.hash, key, key_len, + (void **)&ce)) { + if (ce->tv.tv_sec <= grn_db_get_last_modified(ctx, ctx->impl->db)) { + grn_cache_expire_entry_memory(cache, ce); + goto exit; + } + rc = GRN_SUCCESS; + GRN_TEXT_PUT(ctx, + output, + GRN_TEXT_VALUE(ce->value), + GRN_TEXT_LEN(ce->value)); + ce->prev->next = ce->next; + ce->next->prev = ce->prev; + { + grn_cache_entry_memory *ce0 = + (grn_cache_entry_memory *)(&(cache->impl.memory)); + ce->next = ce0->next; + ce->prev = ce0; + ce0->next->prev = ce; + ce0->next = ce; + } + cache->impl.memory.nhits++; + } +exit : + MUTEX_UNLOCK(cache->impl.memory.mutex); + return rc; +} + +static grn_rc +grn_cache_fetch_persistent(grn_ctx *ctx, grn_cache *cache, + const char *key, uint32_t key_len, + grn_obj *output) +{ + /* TODO: How about GRN_NOT_FOUND? */ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_hash *keys = cache->impl.persistent.keys; + grn_ja *values = cache->impl.persistent.values; + grn_id cache_id; + grn_cache_entry_persistent *entry; + grn_cache_entry_persistent *metadata_entry; + + if (key_len == GRN_CACHE_PERSISTENT_ROOT_KEY_LEN && + memcmp(key, + GRN_CACHE_PERSISTENT_ROOT_KEY, + GRN_CACHE_PERSISTENT_ROOT_KEY_LEN) == 0) { + return rc; + } + + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); + if (rc != GRN_SUCCESS) { + return rc; + } + + /* TODO: How about GRN_NOT_FOUND? */ + rc = GRN_INVALID_ARGUMENT; + + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + metadata_entry->metadata.nfetches++; + + cache_id = grn_hash_get(cache->ctx, keys, key, key_len, (void **)&entry); + if (cache_id == GRN_ID_NIL) { + goto exit; + } + + if (cache_id != GRN_ID_NIL) { + if (entry->data.modified_time.tv_sec <= + grn_db_get_last_modified(ctx, ctx->impl->db)) { + grn_cache_expire_entry_persistent(cache, entry, cache_id); + goto exit; + } + + rc = GRN_SUCCESS; + grn_ja_get_value(ctx, values, cache_id, output); + grn_cache_entry_persistent_delete_link(cache, entry); + { + grn_cache_entry_persistent *head_entry; + head_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_ROOT_ID, + NULL); + grn_cache_entry_persistent_prepend_link(cache, + entry, + cache_id, + head_entry, + GRN_CACHE_PERSISTENT_ROOT_ID); + } + metadata_entry->metadata.nhits++; + } + +exit : + grn_io_unlock(keys->io); + + return rc; +} + +grn_rc +grn_cache_fetch(grn_ctx *ctx, grn_cache *cache, + const char *key, uint32_t key_len, + grn_obj *output) +{ + if (!ctx->impl || !ctx->impl->db) { return GRN_INVALID_ARGUMENT; } + + if (cache->is_memory) { + return grn_cache_fetch_memory(ctx, cache, key, key_len, output); + } else { + return grn_cache_fetch_persistent(ctx, cache, key, key_len, output); + } +} + +static void +grn_cache_update_memory(grn_ctx *ctx, grn_cache *cache, + const char *key, uint32_t key_len, + grn_obj *value) +{ + grn_id id; + int added = 0; + grn_cache_entry_memory *ce; + grn_rc rc = GRN_SUCCESS; + grn_obj *old = NULL; + grn_obj *obj = NULL; + + if (cache->impl.memory.max_nentries == 0) { + return; + } + + MUTEX_LOCK(cache->impl.memory.mutex); + obj = grn_obj_open(cache->ctx, GRN_BULK, 0, GRN_DB_TEXT); + if (!obj) { + goto exit; + } + GRN_TEXT_PUT(cache->ctx, obj, GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value)); + id = grn_hash_add(cache->ctx, cache->impl.memory.hash, key, key_len, + (void **)&ce, &added); + if (id) { + if (!added) { + old = ce->value; + ce->prev->next = ce->next; + ce->next->prev = ce->prev; + } + ce->id = id; + ce->value = obj; + ce->tv = ctx->impl->tv; + { + grn_cache_entry_memory *ce0 = + (grn_cache_entry_memory *)(&(cache->impl.memory)); + ce->next = ce0->next; + ce->prev = ce0; + ce0->next->prev = ce; + ce0->next = ce; + } + if (GRN_HASH_SIZE(cache->impl.memory.hash) > + cache->impl.memory.max_nentries) { + grn_cache_expire_entry_memory(cache, cache->impl.memory.prev); + } + } else { + rc = GRN_NO_MEMORY_AVAILABLE; + } +exit : + if (rc) { grn_obj_close(cache->ctx, obj); } + if (old) { grn_obj_close(cache->ctx, old); } + MUTEX_UNLOCK(cache->impl.memory.mutex); +} + +static void +grn_cache_update_persistent(grn_ctx *ctx, grn_cache *cache, + const char *key, uint32_t key_len, + grn_obj *value) +{ + grn_rc rc; + grn_hash *keys = cache->impl.persistent.keys; + grn_ja *values = cache->impl.persistent.values; + grn_cache_entry_persistent *metadata_entry; + grn_id cache_id; + grn_cache_entry_persistent *entry; + int added; + + if (key_len == GRN_CACHE_PERSISTENT_ROOT_KEY_LEN && + memcmp(key, + GRN_CACHE_PERSISTENT_ROOT_KEY, + GRN_CACHE_PERSISTENT_ROOT_KEY_LEN) == 0) { + return; + } + + if (key_len == GRN_CACHE_PERSISTENT_METADATA_KEY_LEN && + memcmp(key, + GRN_CACHE_PERSISTENT_METADATA_KEY, + GRN_CACHE_PERSISTENT_METADATA_KEY_LEN) == 0) { + return; + } + + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); + if (rc != GRN_SUCCESS) { + return; + } + + metadata_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_METADATA_ID, + NULL); + if (metadata_entry->metadata.max_nentries == 0) { + goto exit; + } + + cache_id = grn_hash_add(cache->ctx, keys, key, key_len, (void **)&entry, + &added); + if (cache_id) { + grn_cache_entry_persistent *head_entry; + + if (!added) { + grn_cache_entry_persistent_delete_link(cache, entry); + } + entry->data.modified_time = ctx->impl->tv; + + grn_ja_put(cache->ctx, values, cache_id, + GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value), + GRN_OBJ_SET, NULL); + + head_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + GRN_CACHE_PERSISTENT_ROOT_ID, + NULL); + grn_cache_entry_persistent_prepend_link(cache, + entry, + cache_id, + head_entry, + GRN_CACHE_PERSISTENT_ROOT_ID); + if (GRN_HASH_SIZE(keys) > metadata_entry->metadata.max_nentries) { + grn_cache_entry_persistent *tail_entry; + tail_entry = + (grn_cache_entry_persistent *)grn_hash_get_value_(ctx, + keys, + head_entry->data.prev, + NULL); + grn_cache_expire_entry_persistent(cache, + tail_entry, + head_entry->data.prev); + } + } + +exit : + grn_io_unlock(keys->io); +} + +void +grn_cache_update(grn_ctx *ctx, grn_cache *cache, + const char *key, uint32_t key_len, grn_obj *value) +{ + if (!ctx->impl) { return; } + + if (cache->is_memory) { + grn_cache_update_memory(ctx, cache, key, key_len, value); + } else { + grn_cache_update_persistent(ctx, cache, key, key_len, value); + } +} + +static void +grn_cache_expire_memory(grn_cache *cache, int32_t size) +{ + MUTEX_LOCK(cache->impl.memory.mutex); + grn_cache_expire_memory_without_lock(cache, size); + MUTEX_UNLOCK(cache->impl.memory.mutex); +} + +static void +grn_cache_expire_persistent(grn_cache *cache, int32_t size) +{ + grn_rc rc; + grn_ctx *ctx = cache->ctx; + grn_hash *keys = cache->impl.persistent.keys; + + rc = grn_io_lock(ctx, keys->io, cache->impl.persistent.timeout); + if (rc != GRN_SUCCESS) { + return; + } + + grn_cache_expire_persistent_without_lock(cache, size); + + grn_io_unlock(keys->io); +} + +void +grn_cache_expire(grn_cache *cache, int32_t size) +{ + if (cache->is_memory) { + grn_cache_expire_memory(cache, size); + } else { + grn_cache_expire_persistent(cache, size); + } +} + +void +grn_cache_fin(void) +{ + grn_ctx *ctx = &grn_cache_ctx; + + grn_cache_current_set(ctx, NULL); + + if (grn_cache_default) { + grn_cache_close(ctx, grn_cache_default); + grn_cache_default = NULL; + } + + grn_ctx_fin(ctx); +} diff --git a/storage/mroonga/vendor/groonga/lib/column.c b/storage/mroonga/vendor/groonga/lib/column.c new file mode 100644 index 00000000..ecfc71b7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/column.c @@ -0,0 +1,49 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_store.h" +#include "grn_ii.h" + +grn_column_flags +grn_column_get_flags(grn_ctx *ctx, grn_obj *column) +{ + grn_column_flags flags = 0; + + GRN_API_ENTER; + + if (!column) { + GRN_API_RETURN(0); + } + + switch (column->header.type) { + case GRN_COLUMN_FIX_SIZE : + flags = column->header.flags; + break; + case GRN_COLUMN_VAR_SIZE : + flags = grn_ja_get_flags(ctx, (grn_ja *)column); + break; + case GRN_COLUMN_INDEX : + flags = grn_ii_get_flags(ctx, (grn_ii *)column); + break; + default : + break; + } + + GRN_API_RETURN(flags); +} diff --git a/storage/mroonga/vendor/groonga/lib/com.c b/storage/mroonga/vendor/groonga/lib/com.c new file mode 100644 index 00000000..7761f483 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/com.c @@ -0,0 +1,1202 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2009-2012 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" + +#include +#include +#include "grn_ctx_impl.h" + +#ifdef WIN32 +# include +#else +# ifdef HAVE_SYS_SOCKET_H +# include +# endif /* HAVE_SYS_SOCKET_H */ +# include +# include +# ifdef HAVE_SIGNAL_H +# include +# endif /* HAVE_SIGNAL_H */ +# include +#endif /* WIN32 */ + +#include "grn_ctx.h" +#include "grn_com.h" + +#ifndef PF_INET +#define PF_INET AF_INET +#endif /* PF_INET */ + +#ifndef SOL_TCP +# ifdef IPPROTO_TCP +# define SOL_TCP IPPROTO_TCP +# else +# define SOL_TCP 6 +# endif /* IPPROTO_TCP */ +#endif /* SOL_TCP */ + +#ifndef USE_MSG_MORE +# ifdef MSG_MORE +# undef MSG_MORE +# endif +# define MSG_MORE 0 +#endif /* USE_MSG_MORE */ + + +#ifndef USE_MSG_NOSIGNAL +# ifdef MSG_NOSIGNAL +# undef MSG_NOSIGNAL +# endif +# define MSG_NOSIGNAL 0 +#endif /* USE_MSG_NOSIGNAL */ +/******* grn_com_queue ********/ + +grn_rc +grn_com_queue_enque(grn_ctx *ctx, grn_com_queue *q, grn_com_queue_entry *e) +{ + CRITICAL_SECTION_ENTER(q->cs); + e->next = NULL; + *q->tail = e; + q->tail = &e->next; + CRITICAL_SECTION_LEAVE(q->cs); + /* + uint8_t i = q->last + 1; + e->next = NULL; + if (q->first == i || q->next) { + CRITICAL_SECTION_ENTER(q->cs); + if (q->first == i || q->next) { + *q->tail = e; + q->tail = &e->next; + } else { + q->bins[q->last] = e; + q->last = i; + } + CRITICAL_SECTION_LEAVE(q->cs); + } else { + q->bins[q->last] = e; + q->last = i; + } + */ + return GRN_SUCCESS; +} + +grn_com_queue_entry * +grn_com_queue_deque(grn_ctx *ctx, grn_com_queue *q) +{ + grn_com_queue_entry *e = NULL; + + CRITICAL_SECTION_ENTER(q->cs); + if (q->next) { + e = q->next; + if (!(q->next = e->next)) { q->tail = &q->next; } + } + CRITICAL_SECTION_LEAVE(q->cs); + + /* + if (q->first == q->last) { + if (q->next) { + CRITICAL_SECTION_ENTER(q->cs); + e = q->next; + if (!(q->next = e->next)) { q->tail = &q->next; } + CRITICAL_SECTION_LEAVE(q->cs); + } + } else { + e = q->bins[q->first++]; + } + */ + return e; +} + +/******* grn_msg ********/ + +grn_obj * +grn_msg_open(grn_ctx *ctx, grn_com *com, grn_com_queue *old) +{ + grn_msg *msg = NULL; + if (old && (msg = (grn_msg *)grn_com_queue_deque(ctx, old))) { + if (msg->ctx != ctx) { + ERR(GRN_INVALID_ARGUMENT, "ctx unmatch"); + return NULL; + } + GRN_BULK_REWIND(&msg->qe.obj); + } else if ((msg = GRN_MALLOCN(grn_msg, 1))) { + GRN_OBJ_INIT(&msg->qe.obj, GRN_MSG, 0, GRN_DB_TEXT); + msg->qe.obj.header.impl_flags |= GRN_OBJ_ALLOCATED; + msg->ctx = ctx; + } + msg->qe.next = NULL; + msg->u.peer = com; + msg->old = old; + memset(&msg->header, 0, sizeof(grn_com_header)); + return (grn_obj *)msg; +} + +grn_obj * +grn_msg_open_for_reply(grn_ctx *ctx, grn_obj *query, grn_com_queue *old) +{ + grn_msg *req = (grn_msg *)query, *msg = NULL; + if (req && (msg = (grn_msg *)grn_msg_open(ctx, req->u.peer, old))) { + msg->edge_id = req->edge_id; + msg->header.proto = req->header.proto == GRN_COM_PROTO_MBREQ + ? GRN_COM_PROTO_MBRES : req->header.proto; + } + return (grn_obj *)msg; +} + +grn_rc +grn_msg_close(grn_ctx *ctx, grn_obj *obj) +{ + grn_msg *msg = (grn_msg *)obj; + if (ctx == msg->ctx) { return grn_obj_close(ctx, obj); } + return grn_com_queue_enque(ctx, msg->old, (grn_com_queue_entry *)msg); +} + +grn_rc +grn_msg_set_property(grn_ctx *ctx, grn_obj *obj, + uint16_t status, uint32_t key_size, uint8_t extra_size) +{ + grn_com_header *header = &((grn_msg *)obj)->header; + header->status = htons(status); + header->keylen = htons(key_size); + header->level = extra_size; + return GRN_SUCCESS; +} + +grn_rc +grn_msg_send(grn_ctx *ctx, grn_obj *msg, int flags) +{ + grn_rc rc; + grn_msg *m = (grn_msg *)msg; + grn_com *peer = m->u.peer; + grn_com_header *header = &m->header; + if (GRN_COM_QUEUE_EMPTYP(&peer->new_)) { + switch (header->proto) { + case GRN_COM_PROTO_HTTP : + { + ssize_t ret; + ret = send(peer->fd, GRN_BULK_HEAD(msg), GRN_BULK_VSIZE(msg), MSG_NOSIGNAL); + if (ret == -1) { SOERR("send"); } + if (ctx->rc != GRN_OPERATION_WOULD_BLOCK) { + grn_com_queue_enque(ctx, m->old, (grn_com_queue_entry *)msg); + return ctx->rc; + } + } + break; + case GRN_COM_PROTO_GQTP : + { + if (flags & GRN_CTX_MORE) { flags |= GRN_CTX_QUIET; } + if (ctx->stat == GRN_CTX_QUIT) { flags |= GRN_CTX_QUIT; } + header->qtype = (uint8_t) ctx->impl->output.type; + header->keylen = 0; + header->level = 0; + header->flags = flags; + header->status = htons((uint16_t)ctx->rc); + header->opaque = 0; + header->cas = 0; + //todo : MSG_DONTWAIT + rc = grn_com_send(ctx, peer, header, + GRN_BULK_HEAD(msg), GRN_BULK_VSIZE(msg), 0); + if (rc != GRN_OPERATION_WOULD_BLOCK) { + grn_com_queue_enque(ctx, m->old, (grn_com_queue_entry *)msg); + return rc; + } + } + break; + case GRN_COM_PROTO_MBREQ : + return GRN_FUNCTION_NOT_IMPLEMENTED; + case GRN_COM_PROTO_MBRES : + rc = grn_com_send(ctx, peer, header, + GRN_BULK_HEAD(msg), GRN_BULK_VSIZE(msg), + (flags & GRN_CTX_MORE) ? MSG_MORE :0); + if (rc != GRN_OPERATION_WOULD_BLOCK) { + grn_com_queue_enque(ctx, m->old, (grn_com_queue_entry *)msg); + return rc; + } + break; + default : + return GRN_INVALID_ARGUMENT; + } + } + MUTEX_LOCK(peer->ev->mutex); + rc = grn_com_queue_enque(ctx, &peer->new_, (grn_com_queue_entry *)msg); + COND_SIGNAL(peer->ev->cond); + MUTEX_UNLOCK(peer->ev->mutex); + return rc; +} + +/******* grn_com ********/ + +grn_rc +grn_com_init(void) +{ +#ifdef WIN32 + WSADATA wd; + if (WSAStartup(MAKEWORD(2, 0), &wd) != 0) { + grn_ctx *ctx = &grn_gctx; + SOERR("WSAStartup"); + } +#else /* WIN32 */ +#ifndef USE_MSG_NOSIGNAL + if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) { + grn_ctx *ctx = &grn_gctx; + SERR("signal"); + } +#endif /* USE_MSG_NOSIGNAL */ +#endif /* WIN32 */ + return grn_gctx.rc; +} + +void +grn_com_fin(void) +{ +#ifdef WIN32 + WSACleanup(); +#endif /* WIN32 */ +} + +grn_rc +grn_com_event_init(grn_ctx *ctx, grn_com_event *ev, int max_nevents, int data_size) +{ + ev->max_nevents = max_nevents; + if ((ev->hash = grn_hash_create(ctx, NULL, sizeof(grn_sock), data_size, 0))) { + MUTEX_INIT(ev->mutex); + COND_INIT(ev->cond); + GRN_COM_QUEUE_INIT(&ev->recv_old); + ev->msg_handler = NULL; + memset(&(ev->curr_edge_id), 0, sizeof(grn_com_addr)); + ev->acceptor = NULL; + ev->opaque = NULL; +#ifndef USE_SELECT +# ifdef USE_EPOLL + if ((ev->events = GRN_MALLOC(sizeof(struct epoll_event) * max_nevents))) { + if ((ev->epfd = epoll_create(max_nevents)) != -1) { + goto exit; + } else { + SERR("epoll_create"); + } + GRN_FREE(ev->events); + } +# else /* USE_EPOLL */ +# ifdef USE_KQUEUE + if ((ev->events = GRN_MALLOC(sizeof(struct kevent) * max_nevents))) { + if ((ev->kqfd = kqueue()) != -1) { + goto exit; + } else { + SERR("kqueue"); + } + GRN_FREE(ev->events); + } +# else /* USE_KQUEUE */ + if ((ev->events = GRN_MALLOC(sizeof(struct pollfd) * max_nevents))) { + goto exit; + } +# endif /* USE_KQUEUE*/ +# endif /* USE_EPOLL */ + grn_hash_close(ctx, ev->hash); + ev->hash = NULL; + ev->events = NULL; +#else /* USE_SELECT */ + goto exit; +#endif /* USE_SELECT */ + } +exit : + return ctx->rc; +} + +grn_rc +grn_com_event_fin(grn_ctx *ctx, grn_com_event *ev) +{ + grn_obj *msg; + while ((msg = (grn_obj *)grn_com_queue_deque(ctx, &ev->recv_old))) { + grn_msg_close(ctx, msg); + } + if (ev->hash) { grn_hash_close(ctx, ev->hash); } +#ifndef USE_SELECT + if (ev->events) { GRN_FREE(ev->events); } +# ifdef USE_EPOLL + grn_close(ev->epfd); +# endif /* USE_EPOLL */ +# ifdef USE_KQUEUE + grn_close(ev->kqfd); +# endif /* USE_KQUEUE*/ +#endif /* USE_SELECT */ + return GRN_SUCCESS; +} + +grn_rc +grn_com_event_add(grn_ctx *ctx, grn_com_event *ev, grn_sock fd, int events, grn_com **com) +{ + grn_com *c; + /* todo : expand events */ + if (!ev || *ev->hash->n_entries == (uint32_t) ev->max_nevents) { + if (ev) { GRN_LOG(ctx, GRN_LOG_ERROR, "too many connections (%d)", ev->max_nevents); } + return GRN_INVALID_ARGUMENT; + } +#ifdef USE_EPOLL + { + struct epoll_event e; + memset(&e, 0, sizeof(struct epoll_event)); + e.data.fd = (fd); + e.events = (uint32_t) events; + if (epoll_ctl(ev->epfd, EPOLL_CTL_ADD, (fd), &e) == -1) { + SERR("epoll_ctl"); + return ctx->rc; + } + } +#endif /* USE_EPOLL*/ +#ifdef USE_KQUEUE + { + struct kevent e; + /* todo: udata should have fd */ + EV_SET(&e, (fd), events, EV_ADD, 0, 0, NULL); + if (kevent(ev->kqfd, &e, 1, NULL, 0, NULL) == -1) { + SERR("kevent"); + return ctx->rc; + } + } +#endif /* USE_KQUEUE */ + { + if (grn_hash_add(ctx, ev->hash, &fd, sizeof(grn_sock), (void **)&c, NULL)) { + c->ev = ev; + c->fd = fd; + c->events = events; + if (com) { *com = c; } + } + } + return ctx->rc; +} + +grn_rc +grn_com_event_mod(grn_ctx *ctx, grn_com_event *ev, grn_sock fd, int events, grn_com **com) +{ + grn_com *c; + if (!ev) { return GRN_INVALID_ARGUMENT; } + if (grn_hash_get(ctx, ev->hash, &fd, sizeof(grn_sock), (void **)&c)) { + if (c->fd != fd) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "grn_com_event_mod fd unmatch " + "%" GRN_FMT_SOCKET " != %" GRN_FMT_SOCKET, + c->fd, fd); + return GRN_OBJECT_CORRUPT; + } + if (com) { *com = c; } + if (c->events != events) { +#ifdef USE_EPOLL + struct epoll_event e; + memset(&e, 0, sizeof(struct epoll_event)); + e.data.fd = (fd); + e.events = (uint32_t) events; + if (epoll_ctl(ev->epfd, EPOLL_CTL_MOD, (fd), &e) == -1) { + SERR("epoll_ctl"); + return ctx->rc; + } +#endif /* USE_EPOLL*/ +#ifdef USE_KQUEUE + // experimental + struct kevent e[2]; + EV_SET(&e[0], (fd), GRN_COM_POLLIN|GRN_COM_POLLOUT, EV_DELETE, 0, 0, NULL); + EV_SET(&e[1], (fd), events, EV_ADD, 0, 0, NULL); + if (kevent(ev->kqfd, e, 2, NULL, 0, NULL) == -1) { + SERR("kevent"); + return ctx->rc; + } +#endif /* USE_KQUEUE */ + c->events = events; + } + return GRN_SUCCESS; + } + return GRN_INVALID_ARGUMENT; +} + +grn_rc +grn_com_event_del(grn_ctx *ctx, grn_com_event *ev, grn_sock fd) +{ + if (!ev) { return GRN_INVALID_ARGUMENT; } + { + grn_com *c; + grn_id id = grn_hash_get(ctx, ev->hash, &fd, sizeof(grn_sock), (void **)&c); + if (id) { +#ifdef USE_EPOLL + if (!c->closed) { + struct epoll_event e; + memset(&e, 0, sizeof(struct epoll_event)); + e.data.fd = fd; + e.events = c->events; + if (epoll_ctl(ev->epfd, EPOLL_CTL_DEL, fd, &e) == -1) { + SERR("epoll_ctl"); + return ctx->rc; + } + } +#endif /* USE_EPOLL*/ +#ifdef USE_KQUEUE + struct kevent e; + EV_SET(&e, (fd), c->events, EV_DELETE, 0, 0, NULL); + if (kevent(ev->kqfd, &e, 1, NULL, 0, NULL) == -1) { + SERR("kevent"); + return ctx->rc; + } +#endif /* USE_KQUEUE */ + return grn_hash_delete_by_id(ctx, ev->hash, id, NULL); + } else { + GRN_LOG(ctx, GRN_LOG_ERROR, + "%04x| fd(%" GRN_FMT_SOCKET ") not found in ev(%p)", + grn_getpid(), fd, ev); + return GRN_INVALID_ARGUMENT; + } + } +} + +#define LISTEN_BACKLOG 0x1000 + +grn_rc +grn_com_event_start_accept(grn_ctx *ctx, grn_com_event *ev) +{ + grn_com *com = ev->acceptor; + + if (com->accepting) {return ctx->rc;} + + GRN_API_ENTER; + if (!grn_com_event_mod(ctx, ev, com->fd, GRN_COM_POLLIN, NULL)) { + if (listen(com->fd, LISTEN_BACKLOG) == 0) { + com->accepting = GRN_TRUE; + } else { + SOERR("listen - start accept"); + } + } + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_com_event_stop_accept(grn_ctx *ctx, grn_com_event *ev) +{ + grn_com *com = ev->acceptor; + + if (!com->accepting) {return ctx->rc;} + + GRN_API_ENTER; + if (!grn_com_event_mod(ctx, ev, com->fd, 0, NULL)) { + if (listen(com->fd, 0) == 0) { + com->accepting = GRN_FALSE; + } else { + SOERR("listen - disable accept"); + } + } + GRN_API_RETURN(ctx->rc); +} + +static void +grn_com_receiver(grn_ctx *ctx, grn_com *com) +{ + grn_com_event *ev = com->ev; + ERRCLR(ctx); + if (ev->acceptor == com) { + grn_com *ncs; + grn_sock fd = accept(com->fd, NULL, NULL); + if (fd == -1) { + if (errno == EMFILE) { + grn_com_event_stop_accept(ctx, ev); + } else { + SOERR("accept"); + } + return; + } + if (grn_com_event_add(ctx, ev, fd, GRN_COM_POLLIN, (grn_com **)&ncs)) { + grn_sock_close(fd); + return; + } + ncs->has_sid = 0; + ncs->closed = 0; + ncs->opaque = NULL; + GRN_COM_QUEUE_INIT(&ncs->new_); + // GRN_LOG(ctx, GRN_LOG_NOTICE, "accepted (%d)", fd); + return; + } else { + grn_msg *msg = (grn_msg *)grn_msg_open(ctx, com, &ev->recv_old); + grn_com_recv(ctx, msg->u.peer, &msg->header, (grn_obj *)msg); + if (msg->u.peer /* is_edge_request(msg)*/) { + grn_memcpy(&msg->edge_id, &ev->curr_edge_id, sizeof(grn_com_addr)); + if (!com->has_sid) { + com->has_sid = 1; + com->sid = ev->curr_edge_id.sid++; + } + msg->edge_id.sid = com->sid; + } + msg->acceptor = ev->acceptor; + ev->msg_handler(ctx, (grn_obj *)msg); + } +} + +grn_rc +grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout) +{ + int nevents; + grn_com *com; +#ifdef USE_SELECT + uint32_t dummy; + grn_sock *pfd; + int nfds = 0; + fd_set rfds; + fd_set wfds; + struct timeval tv; + if (timeout >= 0) { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + } + FD_ZERO(&rfds); + FD_ZERO(&wfds); + ctx->errlvl = GRN_OK; + ctx->rc = GRN_SUCCESS; + { + grn_hash_cursor *cursor; + cursor = grn_hash_cursor_open(ctx, ev->hash, NULL, 0, NULL, 0, 0, -1, 0); + if (cursor) { + grn_id id; + while ((id = grn_hash_cursor_next(ctx, cursor))) { + grn_hash_cursor_get_key_value(ctx, + cursor, + (void **)(&pfd), + &dummy, + (void **)(&com)); + if (com->events & GRN_COM_POLLIN) { FD_SET(*pfd, &rfds); } + if (com->events & GRN_COM_POLLOUT) { FD_SET(*pfd, &wfds); } +# ifndef WIN32 + if (*pfd > nfds) { nfds = *pfd; } +# endif /* WIN32 */ + } + grn_hash_cursor_close(ctx, cursor); + } + } + nevents = select(nfds + 1, &rfds, &wfds, NULL, (timeout >= 0) ? &tv : NULL); + if (nevents < 0) { + SOERR("select"); + if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { ERRCLR(ctx); } + return ctx->rc; + } + if (timeout < 0 && !nevents) { GRN_LOG(ctx, GRN_LOG_NOTICE, "select returns 0 events"); } + GRN_HASH_EACH(ctx, ev->hash, eh, &pfd, &dummy, &com, { + if (FD_ISSET(*pfd, &rfds)) { grn_com_receiver(ctx, com); } + }); +#else /* USE_SELECT */ +# ifdef USE_EPOLL + struct epoll_event *ep; + ctx->errlvl = GRN_OK; + ctx->rc = GRN_SUCCESS; + nevents = epoll_wait(ev->epfd, ev->events, ev->max_nevents, timeout); + if (nevents < 0) { + SERR("epoll_wait"); + } +# else /* USE_EPOLL */ +# ifdef USE_KQUEUE + struct kevent *ep; + struct timespec tv; + if (timeout >= 0) { + tv.tv_sec = timeout / 1000; + tv.tv_nsec = (timeout % 1000) * 1000; + } + nevents = kevent(ev->kqfd, NULL, 0, ev->events, ev->max_nevents, &tv); + if (nevents < 0) { + SERR("kevent"); + } +# else /* USE_KQUEUE */ + uint32_t dummy; + int nfd = 0, *pfd; + struct pollfd *ep = ev->events; + ctx->errlvl = GRN_OK; + ctx->rc = GRN_SUCCESS; + GRN_HASH_EACH(ctx, ev->hash, eh, &pfd, &dummy, &com, { + ep->fd = *pfd; + // ep->events =(short) com->events; + ep->events = POLLIN; + ep->revents = 0; + ep++; + nfd++; + }); + nevents = poll(ev->events, nfd, timeout); + if (nevents < 0) { + SERR("poll"); + } +# endif /* USE_KQUEUE */ +# endif /* USE_EPOLL */ + if (ctx->rc != GRN_SUCCESS) { + if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { + ERRCLR(ctx); + } + return ctx->rc; + } + if (timeout < 0 && !nevents) { GRN_LOG(ctx, GRN_LOG_NOTICE, "poll returns 0 events"); } + for (ep = ev->events; nevents; ep++) { + int efd; +# ifdef USE_EPOLL + efd = ep->data.fd; + nevents--; + // todo : com = ep->data.ptr; + if (!grn_hash_get(ctx, ev->hash, &efd, sizeof(grn_sock), (void *)&com)) { + struct epoll_event e; + GRN_LOG(ctx, GRN_LOG_ERROR, "fd(%d) not found in ev->hash", efd); + memset(&e, 0, sizeof(struct epoll_event)); + e.data.fd = efd; + e.events = ep->events; + if (epoll_ctl(ev->epfd, EPOLL_CTL_DEL, efd, &e) == -1) { SERR("epoll_ctl"); } + if (grn_sock_close(efd) == -1) { SOERR("close"); } + continue; + } + if (ep->events & GRN_COM_POLLIN) { grn_com_receiver(ctx, com); } +# else /* USE_EPOLL */ +# ifdef USE_KQUEUE + efd = ep->ident; + nevents--; + // todo : com = ep->udata; + if (!grn_hash_get(ctx, ev->hash, &efd, sizeof(grn_sock), (void *)&com)) { + struct kevent e; + GRN_LOG(ctx, GRN_LOG_ERROR, "fd(%d) not found in ev->set", efd); + EV_SET(&e, efd, ep->filter, EV_DELETE, 0, 0, NULL); + if (kevent(ev->kqfd, &e, 1, NULL, 0, NULL) == -1) { SERR("kevent"); } + if (grn_sock_close(efd) == -1) { SOERR("close"); } + continue; + } + if (ep->filter == GRN_COM_POLLIN) { grn_com_receiver(ctx, com); } +# else + efd = ep->fd; + if (!(ep->events & ep->revents)) { continue; } + nevents--; + if (!grn_hash_get(ctx, ev->hash, &efd, sizeof(grn_sock), (void *)&com)) { + GRN_LOG(ctx, GRN_LOG_ERROR, "fd(%d) not found in ev->hash", efd); + if (grn_sock_close(efd) == -1) { SOERR("close"); } + continue; + } + if (ep->revents & GRN_COM_POLLIN) { grn_com_receiver(ctx, com); } +# endif /* USE_KQUEUE */ +# endif /* USE_EPOLL */ + } +#endif /* USE_SELECT */ + /* todo : + while (!(msg = (grn_com_msg *)grn_com_queue_deque(&recv_old))) { + grn_msg_close(ctx, msg); + } + */ + return GRN_SUCCESS; +} + +grn_rc +grn_com_send_http(grn_ctx *ctx, grn_com *cs, const char *path, uint32_t path_len, int flags) +{ + ssize_t ret; + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_PUTS(ctx, &buf, "GET "); + grn_bulk_write(ctx, &buf, path, path_len); + GRN_TEXT_PUTS(ctx, &buf, " HTTP/1.0\r\n\r\n"); + // todo : refine + if ((ret = send(cs->fd, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf), MSG_NOSIGNAL|flags)) == -1) { + SOERR("send"); + } + if (ret != GRN_BULK_VSIZE(&buf)) { + GRN_LOG(ctx, GRN_LOG_NOTICE, "send %d != %d", (int)ret, (int)GRN_BULK_VSIZE(&buf)); + } + grn_obj_close(ctx, &buf); + return ctx->rc; +} + +grn_rc +grn_com_send(grn_ctx *ctx, grn_com *cs, + grn_com_header *header, const char *body, uint32_t size, int flags) +{ + grn_rc rc = GRN_SUCCESS; + size_t whole_size = sizeof(grn_com_header) + size; + ssize_t ret; + header->size = htonl(size); + GRN_LOG(ctx, GRN_LOG_INFO, "send (%d,%x,%d,%02x,%02x,%04x)", size, header->flags, header->proto, header->qtype, header->level, header->status); + + if (size) { +#ifdef WIN32 + WSABUF wsabufs[2]; + DWORD n_sent; + wsabufs[0].buf = (char *)header; + wsabufs[0].len = sizeof(grn_com_header); + wsabufs[1].buf = (char *)body; + wsabufs[1].len = size; + if (WSASend(cs->fd, wsabufs, 2, &n_sent, 0, NULL, NULL) == SOCKET_ERROR) { + SOERR("WSASend"); + } + ret = n_sent; +#else /* WIN32 */ + struct iovec msg_iov[2]; + struct msghdr msg; + memset(&msg, 0, sizeof(struct msghdr)); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = msg_iov; + msg.msg_iovlen = 2; + msg_iov[0].iov_base = (char*) header; + msg_iov[0].iov_len = sizeof(grn_com_header); + msg_iov[1].iov_base = (char *)body; + msg_iov[1].iov_len = size; + if ((ret = sendmsg(cs->fd, &msg, MSG_NOSIGNAL|flags)) == -1) { + SOERR("sendmsg"); + rc = ctx->rc; + } +#endif /* WIN32 */ + } else { + if ((ret = send(cs->fd, (const void *)header, whole_size, MSG_NOSIGNAL|flags)) == -1) { + SOERR("send"); + rc = ctx->rc; + } + } + if ((size_t) ret != whole_size) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "sendmsg(%" GRN_FMT_SOCKET "): %" GRN_FMT_LLD " < %" GRN_FMT_LLU, + cs->fd, (long long int)ret, (unsigned long long int)whole_size); + rc = ctx->rc; + } + return rc; +} + +#define RETRY_MAX 10 + +static const char * +scan_delimiter(const char *p, const char *e) +{ + while (p + 4 <= e) { + if (p[3] == '\n') { + if (p[2] == '\r') { + if (p[1] == '\n') { + if (p[0] == '\r') { return p + 4; } else { p += 2; } + } else { p += 2; } + } else { p += 4; } + } else { p += p[3] == '\r' ? 1 : 4; } + } + return NULL; +} + +#define BUFSIZE 4096 + +static grn_rc +grn_com_recv_text(grn_ctx *ctx, grn_com *com, + grn_com_header *header, grn_obj *buf, ssize_t ret) +{ + const char *p; + int retry = 0; + grn_bulk_write(ctx, buf, (char *)header, ret); + if ((p = scan_delimiter(GRN_BULK_HEAD(buf), GRN_BULK_CURR(buf)))) { + header->qtype = *GRN_BULK_HEAD(buf); + header->proto = GRN_COM_PROTO_HTTP; + header->size = GRN_BULK_VSIZE(buf); + goto exit; + } + for (;;) { + if (grn_bulk_reserve(ctx, buf, BUFSIZE)) { return ctx->rc; } + if ((ret = recv(com->fd, GRN_BULK_CURR(buf), BUFSIZE, 0)) < 0) { + SOERR("recv text"); + if (ctx->rc == GRN_OPERATION_WOULD_BLOCK || + ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { + ERRCLR(ctx); + continue; + } + goto exit; + } + if (ret) { + off_t o = GRN_BULK_VSIZE(buf); + p = GRN_BULK_CURR(buf); + GRN_BULK_INCR_LEN(buf, ret); + if (scan_delimiter(p - (o > 3 ? 3 : o), p + ret)) { + break; + } + } else { + if (++retry > RETRY_MAX) { + // ERR(GRN_RETRY_MAX, "retry max in recv text"); + goto exit; + } + } + } + header->qtype = *GRN_BULK_HEAD(buf); + header->proto = GRN_COM_PROTO_HTTP; + header->size = GRN_BULK_VSIZE(buf); +exit : + if (header->qtype == 'H') { + //todo : refine + /* + GRN_BULK_REWIND(buf); + grn_bulk_reserve(ctx, buf, BUFSIZE); + if ((ret = recv(com->fd, GRN_BULK_CURR(buf), BUFSIZE, 0)) < 0) { + SOERR("recv text body"); + } else { + GRN_BULK_CURR(buf) += ret; + } + */ + } + return ctx->rc; +} + +grn_rc +grn_com_recv(grn_ctx *ctx, grn_com *com, grn_com_header *header, grn_obj *buf) +{ + ssize_t ret; + int retry = 0; + byte *p = (byte *)header; + size_t rest = sizeof(grn_com_header); + do { + if ((ret = recv(com->fd, p, rest, 0)) < 0) { + SOERR("recv size"); + GRN_LOG(ctx, GRN_LOG_ERROR, "recv error (%" GRN_FMT_SOCKET ")", com->fd); + if (ctx->rc == GRN_OPERATION_WOULD_BLOCK || + ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { + ERRCLR(ctx); + continue; + } + goto exit; + } + if (ret) { + if (header->proto < 0x80) { + return grn_com_recv_text(ctx, com, header, buf, ret); + } + rest -= ret, p += ret; + } else { + if (++retry > RETRY_MAX) { + // ERR(GRN_RETRY_MAX, "retry max in recv header (%d)", com->fd); + goto exit; + } + } + } while (rest); + GRN_LOG(ctx, GRN_LOG_INFO, + "recv (%u,%x,%d,%02x,%02x,%04x)", + (uint32_t)ntohl(header->size), + header->flags, + header->proto, + header->qtype, + header->level, + header->status); + { + uint8_t proto = header->proto; + size_t value_size = ntohl(header->size); + GRN_BULK_REWIND(buf); + switch (proto) { + case GRN_COM_PROTO_GQTP : + case GRN_COM_PROTO_MBREQ : + if (GRN_BULK_WSIZE(buf) < value_size) { + if (grn_bulk_resize(ctx, buf, value_size)) { + goto exit; + } + } + retry = 0; + for (rest = value_size; rest;) { + if ((ret = recv(com->fd, GRN_BULK_CURR(buf), rest, MSG_WAITALL)) < 0) { + SOERR("recv body"); + if (ctx->rc == GRN_OPERATION_WOULD_BLOCK || + ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { + ERRCLR(ctx); + continue; + } + goto exit; + } + if (ret) { + rest -= ret; + GRN_BULK_INCR_LEN(buf, ret); + } else { + if (++retry > RETRY_MAX) { + // ERR(GRN_RETRY_MAX, "retry max in recv body"); + goto exit; + } + } + } + break; + default : + GRN_LOG(ctx, GRN_LOG_ERROR, "illegal header: %d", proto); + ctx->rc = GRN_INVALID_FORMAT; + goto exit; + } + } +exit : + return ctx->rc; +} + +grn_com * +grn_com_copen(grn_ctx *ctx, grn_com_event *ev, const char *dest, int port) +{ + grn_sock fd = -1; + grn_com *cs = NULL; + + struct addrinfo hints, *addrinfo_list, *addrinfo_ptr; + char port_string[16]; + int getaddrinfo_result; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; +#ifdef AI_NUMERICSERV + hints.ai_flags = AI_NUMERICSERV; +#endif + grn_snprintf(port_string, sizeof(port_string), sizeof(port_string), + "%d", port); + + getaddrinfo_result = getaddrinfo(dest, port_string, &hints, &addrinfo_list); + if (getaddrinfo_result != 0) { + switch (getaddrinfo_result) { +#ifdef EAI_MEMORY + case EAI_MEMORY: + ERR(GRN_NO_MEMORY_AVAILABLE, "getaddrinfo: <%s:%s>: %s", + dest, port_string, gai_strerror(getaddrinfo_result)); + break; +#endif +#ifdef EAI_SYSTEM + case EAI_SYSTEM: + SOERR("getaddrinfo"); + break; +#endif + default: + ERR(GRN_INVALID_ARGUMENT, "getaddrinfo: <%s:%s>: %s", + dest, port_string, gai_strerror(getaddrinfo_result)); + break; + } + return NULL; + } + + for (addrinfo_ptr = addrinfo_list; addrinfo_ptr; + addrinfo_ptr = addrinfo_ptr->ai_next) { + fd = socket(addrinfo_ptr->ai_family, addrinfo_ptr->ai_socktype, + addrinfo_ptr->ai_protocol); + if (fd == -1) { + SOERR("socket"); + continue; + } +#ifdef TCP_NODELAY + { + static const int value = 1; + if (setsockopt(fd, 6, TCP_NODELAY, + (const char *)&value, sizeof(value)) != 0) { + SOERR("setsockopt"); + grn_sock_close(fd); + continue; + } + } +#endif + if (connect(fd, addrinfo_ptr->ai_addr, addrinfo_ptr->ai_addrlen) != 0) { + SOERR("connect"); + grn_sock_close(fd); + continue; + } + + break; + } + + freeaddrinfo(addrinfo_list); + + if (!addrinfo_ptr) { + return NULL; + } + ctx->errlvl = GRN_OK; + ctx->rc = GRN_SUCCESS; + + if (ev) { + grn_com_event_add(ctx, ev, fd, GRN_COM_POLLIN, &cs); + } else { + cs = GRN_CALLOC(sizeof(grn_com)); + if (cs) { + cs->fd = fd; + } + } + if (!cs) { + grn_sock_close(fd); + } + return cs; +} + +void +grn_com_close_(grn_ctx *ctx, grn_com *com) +{ + grn_sock fd = com->fd; + if (shutdown(fd, SHUT_RDWR) == -1) { /* SOERR("shutdown"); */ } + if (grn_sock_close(fd) == -1) { + SOERR("close"); + } else { + com->closed = 1; + } +} + +grn_rc +grn_com_close(grn_ctx *ctx, grn_com *com) +{ + grn_sock fd = com->fd; + grn_com_event *ev = com->ev; + if (ev) { + grn_com *acceptor = ev->acceptor; + grn_com_event_del(ctx, ev, fd); + if (acceptor) { grn_com_event_start_accept(ctx, ev); } + } + if (!com->closed) { grn_com_close_(ctx, com); } + if (!ev) { GRN_FREE(com); } + return GRN_SUCCESS; +} + +grn_rc +grn_com_sopen(grn_ctx *ctx, grn_com_event *ev, + const char *bind_address, int port, grn_msg_handler *func, + struct hostent *he) +{ + grn_sock lfd = -1; + grn_com *cs = NULL; + int getaddrinfo_result; + struct addrinfo *bind_address_info = NULL; + struct addrinfo hints; + char port_string[6]; /* ceil(log10(65535)) + 1 ('\0')*/ + + GRN_API_ENTER; + if (!bind_address) { + bind_address = "0.0.0.0"; + } + grn_snprintf(port_string, sizeof(port_string), sizeof(port_string), + "%d", port); + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; +#ifdef AI_NUMERICSERV + hints.ai_flags = AI_NUMERICSERV; +#endif + getaddrinfo_result = getaddrinfo(bind_address, port_string, + &hints, &bind_address_info); + if (getaddrinfo_result != 0) { + switch (getaddrinfo_result) { +#ifdef EAI_MEMORY + case EAI_MEMORY: + ERR(GRN_NO_MEMORY_AVAILABLE, + "getaddrinfo: <%s:%s>: %s", + bind_address, port_string, gai_strerror(getaddrinfo_result)); + break; +#endif +#ifdef EAI_SYSTEM + case EAI_SYSTEM: + SOERR("getaddrinfo"); + break; +#endif + default: + ERR(GRN_INVALID_ARGUMENT, + "getaddrinfo: <%s:%s>: %s", + bind_address, port_string, gai_strerror(getaddrinfo_result)); + break; + } + goto exit; + } + if ((lfd = socket(bind_address_info->ai_family, SOCK_STREAM, 0)) == -1) { + SOERR("socket"); + goto exit; + } + grn_memcpy(&ev->curr_edge_id.addr, he->h_addr, he->h_length); + ev->curr_edge_id.port = htons(port); + ev->curr_edge_id.sid = 0; + { + int v = 1; +#ifdef TCP_NODELAY + if (setsockopt(lfd, SOL_TCP, TCP_NODELAY, (void *) &v, sizeof(int)) == -1) { + SOERR("setsockopt"); + goto exit; + } +#endif + if (setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, (void *) &v, sizeof(int)) == -1) { + SOERR("setsockopt"); + goto exit; + } + } + if (bind(lfd, bind_address_info->ai_addr, bind_address_info->ai_addrlen) < 0) { + SOERR("bind"); + goto exit; + } + if (listen(lfd, LISTEN_BACKLOG) < 0) { + SOERR("listen"); + goto exit; + } + if (ev) { + if (grn_com_event_add(ctx, ev, lfd, GRN_COM_POLLIN, &cs)) { goto exit; } + ev->acceptor = cs; + ev->msg_handler = func; + cs->has_sid = 0; + cs->closed = 0; + cs->opaque = NULL; + GRN_COM_QUEUE_INIT(&cs->new_); + } else { + if (!(cs = GRN_MALLOC(sizeof(grn_com)))) { goto exit; } + cs->fd = lfd; + } + cs->accepting = GRN_TRUE; +exit : + if (!cs && lfd != 1) { grn_sock_close(lfd); } + if (bind_address_info) { freeaddrinfo(bind_address_info); } + GRN_API_RETURN(ctx->rc); +} + + +grn_hash *grn_edges = NULL; +void (*grn_dispatcher)(grn_ctx *ctx, grn_edge *edge); + +void +grn_edges_init(grn_ctx *ctx, void (*dispatcher)(grn_ctx *ctx, grn_edge *edge)) +{ + grn_edges = grn_hash_create(ctx, NULL, sizeof(grn_com_addr), sizeof(grn_edge), 0); + grn_dispatcher = dispatcher; +} + +void +grn_edges_fin(grn_ctx *ctx) +{ + grn_hash_close(ctx, grn_edges); +} + +grn_edge * +grn_edges_add(grn_ctx *ctx, grn_com_addr *addr, int *added) +{ + if (grn_io_lock(ctx, grn_edges->io, grn_lock_timeout)) { + return NULL; + } else { + grn_edge *edge; + grn_id id = grn_hash_add(ctx, grn_edges, addr, sizeof(grn_com_addr), + (void **)&edge, added); + grn_io_unlock(grn_edges->io); + if (id) { edge->id = id; } + return edge; + } +} + +void +grn_edges_delete(grn_ctx *ctx, grn_edge *edge) +{ + if (!grn_io_lock(ctx, grn_edges->io, grn_lock_timeout)) { + grn_hash_delete_by_id(ctx, grn_edges, edge->id, NULL); + grn_io_unlock(grn_edges->io); + } +} + +grn_edge * +grn_edges_add_communicator(grn_ctx *ctx, grn_com_addr *addr) +{ + int added; + grn_edge *edge = grn_edges_add(ctx, addr, &added); + if (added) { + grn_ctx_init(&edge->ctx, 0); + GRN_COM_QUEUE_INIT(&edge->recv_new); + GRN_COM_QUEUE_INIT(&edge->send_old); + edge->com = NULL; + edge->stat = 0 /*EDGE_IDLE*/; + edge->flags = GRN_EDGE_COMMUNICATOR; + } + return edge; +} + +void +grn_edge_dispatch(grn_ctx *ctx, grn_edge *edge, grn_obj *msg) +{ + grn_com_queue_enque(ctx, &edge->recv_new, (grn_com_queue_entry *)msg); + grn_dispatcher(ctx, edge); +} diff --git a/storage/mroonga/vendor/groonga/lib/command.c b/storage/mroonga/vendor/groonga/lib/command.c new file mode 100644 index 00000000..3da5871b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/command.c @@ -0,0 +1,201 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include + +#include "grn.h" +#include "grn_db.h" +#include "grn_ctx_impl.h" + +struct _grn_command_input { + grn_obj *command; + grn_hash *arguments; +}; + +grn_command_input * +grn_command_input_open(grn_ctx *ctx, grn_obj *command) +{ + grn_command_input *input = NULL; + + GRN_API_ENTER; + input = GRN_MALLOC(sizeof(grn_command_input)); + if (!input) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[command-input] failed to allocate grn_command_input"); + goto exit; + } + + input->command = command; + /* TODO: Allocate by self. */ + { + uint32_t n; + input->arguments = grn_expr_get_vars(ctx, input->command, &n); + } + +exit : + GRN_API_RETURN(input); +} + +grn_rc +grn_command_input_close(grn_ctx *ctx, grn_command_input *input) +{ + GRN_API_ENTER; + + /* TODO: Free input->arguments by self. */ + /* grn_expr_clear_vars(ctx, input->command); */ + GRN_FREE(input); + + GRN_API_RETURN(ctx->rc); +} + +grn_obj * +grn_command_input_add(grn_ctx *ctx, + grn_command_input *input, + const char *name, + int name_size, + grn_bool *added) +{ + grn_obj *argument = NULL; + /* TODO: Use grn_bool */ + int internal_added = GRN_FALSE; + + GRN_API_ENTER; + + if (name_size == -1) { + name_size = strlen(name); + } + if (input->arguments) { + grn_hash_add(ctx, input->arguments, name, name_size, (void **)&argument, + &internal_added); + if (internal_added) { + GRN_TEXT_INIT(argument, 0); + } + } + if (added) { + *added = internal_added; + } + + GRN_API_RETURN(argument); +} + +grn_obj * +grn_command_input_get(grn_ctx *ctx, + grn_command_input *input, + const char *name, + int name_size) +{ + grn_obj *argument = NULL; + + GRN_API_ENTER; + + if (name_size == -1) { + name_size = strlen(name); + } + if (input->arguments) { + grn_hash_get(ctx, input->arguments, name, name_size, (void **)&argument); + } + + GRN_API_RETURN(argument); +} + +grn_obj * +grn_command_input_at(grn_ctx *ctx, + grn_command_input *input, + unsigned int offset) +{ + grn_obj *argument = NULL; + + GRN_API_ENTER; + if (input->arguments) { + argument = (grn_obj *)grn_hash_get_value_(ctx, input->arguments, + offset + 1, NULL); + } + GRN_API_RETURN(argument); +} + +grn_obj * +grn_command_input_get_arguments(grn_ctx *ctx, + grn_command_input *input) +{ + GRN_API_ENTER; + GRN_API_RETURN((grn_obj *)(input->arguments)); +} + +grn_rc +grn_command_register(grn_ctx *ctx, + const char *command_name, + int command_name_size, + grn_command_run_func *run, + grn_expr_var *vars, + unsigned int n_vars, + void *user_data) +{ + GRN_API_ENTER; + + if (command_name_size == -1) { + command_name_size = strlen(command_name); + } + + { + grn_obj *command_object; + command_object = grn_proc_create(ctx, + command_name, + command_name_size, + GRN_PROC_COMMAND, + NULL, NULL, NULL, n_vars, vars); + if (!command_object) { + GRN_PLUGIN_ERROR(ctx, GRN_COMMAND_ERROR, + "[command][%.*s] failed to grn_proc_create()", + command_name_size, command_name); + GRN_API_RETURN(ctx->rc); + } + + { + grn_proc *command = (grn_proc *)command_object; + command->callbacks.command.run = run; + command->user_data = user_data; + } + } + + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_rc +grn_command_run(grn_ctx *ctx, + grn_obj *command, + grn_command_input *input) +{ + grn_proc *proc; + + GRN_API_ENTER; + + proc = (grn_proc *)command; + if (proc->callbacks.command.run) { + proc->callbacks.command.run(ctx, command, input, proc->user_data); + } else { + /* TODO: REMOVE ME. For backward compatibility. */ + uint32_t stack_curr = ctx->impl->stack_curr; + grn_proc_call(ctx, command, 0, command); + if (ctx->impl->stack_curr > stack_curr) { + grn_ctx_pop(ctx); + } + } + + GRN_API_RETURN(ctx->rc); +} + diff --git a/storage/mroonga/vendor/groonga/lib/config.c b/storage/mroonga/vendor/groonga/lib/config.c new file mode 100644 index 00000000..6664e127 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/config.c @@ -0,0 +1,289 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_ctx_impl.h" +#include "grn_config.h" + +#include + +grn_rc +grn_config_set(grn_ctx *ctx, + const char *key, int32_t key_size, + const char *value, int32_t value_size) +{ + grn_obj *db; + grn_hash *config; + void *packed_value; + grn_id id; + + GRN_API_ENTER; + + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "[config][set] DB isn't initialized"); + GRN_API_RETURN(ctx->rc); + } + + if (key_size == -1) { + key_size = strlen(key); + } + if (key_size > GRN_CONFIG_MAX_KEY_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[config][set] too large key: max=<%d>: <%d>", + GRN_CONFIG_MAX_KEY_SIZE, key_size); + GRN_API_RETURN(ctx->rc); + } + + if (value_size == -1) { + value_size = strlen(value); + } + if (value_size > (int32_t) GRN_CONFIG_MAX_VALUE_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[config][set] too large value: max=<%" GRN_FMT_SIZE ">: <%d>", + GRN_CONFIG_MAX_VALUE_SIZE, value_size); + GRN_API_RETURN(ctx->rc); + } + + config = ((grn_db *)db)->config; + { + grn_rc rc; + rc = grn_io_lock(ctx, config->io, grn_lock_timeout); + if (rc != GRN_SUCCESS) { + if (ctx->rc == GRN_SUCCESS) { + ERR(rc, "[config][set] failed to lock"); + } + GRN_API_RETURN(rc); + } + id = grn_hash_add(ctx, config, key, key_size, &packed_value, NULL); + grn_io_unlock(config->io); + } + if (id == GRN_ID_NIL && ctx->rc == GRN_SUCCESS) { + ERR(GRN_INVALID_ARGUMENT, + "[config][set] failed to set: name=<%.*s>: <%d>", + key_size, key, value_size); + } + + *((uint32_t *)packed_value) = (uint32_t)value_size; + grn_memcpy((char *)packed_value + sizeof(uint32_t), + value, value_size); + ((char *)packed_value)[sizeof(uint32_t) + value_size] = '\0'; + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_config_get(grn_ctx *ctx, + const char *key, int32_t key_size, + const char **value, uint32_t *value_size) +{ + grn_obj *db; + grn_hash *config; + grn_id id; + void *packed_value; + + GRN_API_ENTER; + + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "[config][get] DB isn't initialized"); + GRN_API_RETURN(ctx->rc); + } + + if (key_size == -1) { + key_size = strlen(key); + } + if (key_size > GRN_CONFIG_MAX_KEY_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[config][get] too large key: max=<%d>: <%d>", + GRN_CONFIG_MAX_KEY_SIZE, key_size); + GRN_API_RETURN(ctx->rc); + } + + config = ((grn_db *)db)->config; + id = grn_hash_get(ctx, config, key, key_size, &packed_value); + if (id == GRN_ID_NIL) { + *value = NULL; + *value_size = 0; + GRN_API_RETURN(GRN_SUCCESS); + } + + *value = (char *)packed_value + sizeof(uint32_t); + *value_size = *((uint32_t *)packed_value); + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_rc +grn_config_delete(grn_ctx *ctx, + const char *key, int key_size) +{ + grn_obj *db; + grn_hash *config; + + GRN_API_ENTER; + + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "[config][delete] DB isn't initialized"); + GRN_API_RETURN(ctx->rc); + } + + if (key_size == -1) { + key_size = strlen(key); + } + if (key_size > GRN_CONFIG_MAX_KEY_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[config][delete] too large key: max=<%d>: <%d>", + GRN_CONFIG_MAX_KEY_SIZE, key_size); + GRN_API_RETURN(ctx->rc); + } + + config = ((grn_db *)db)->config; + { + grn_rc rc; + rc = grn_io_lock(ctx, config->io, grn_lock_timeout); + if (rc != GRN_SUCCESS) { + if (ctx->rc == GRN_SUCCESS) { + ERR(rc, "[config][delete] failed to lock"); + } + GRN_API_RETURN(rc); + } + rc = grn_hash_delete(ctx, config, key, key_size, NULL); + grn_io_unlock(config->io); + if (rc != GRN_SUCCESS) { + if (ctx->rc == GRN_SUCCESS) { + ERR(rc, "[config][delete] failed to delete"); + } + } + } + + GRN_API_RETURN(ctx->rc); +} + +grn_obj * +grn_config_cursor_open(grn_ctx *ctx) +{ + grn_obj *db; + grn_hash *config; + grn_config_cursor *cursor; + grn_id id; + + GRN_API_ENTER; + + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "[config][cursor][open] DB isn't initialized"); + GRN_API_RETURN(NULL); + } + config = ((grn_db *)db)->config; + + cursor = GRN_MALLOCN(grn_config_cursor, 1); + if (!cursor) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[config][cursor][open] failed to allocate memory for config cursor"); + GRN_API_RETURN(NULL); + } + + GRN_DB_OBJ_SET_TYPE(cursor, GRN_CURSOR_CONFIG); + cursor->hash_cursor = grn_hash_cursor_open(ctx, config, + NULL, -1, + NULL, -1, + 0, -1, 0); + if (!cursor->hash_cursor) { + GRN_FREE(cursor); + ERR(GRN_NO_MEMORY_AVAILABLE, + "[config][cursor][open] failed to allocate memory for hash cursor"); + GRN_API_RETURN(NULL); + } + + id = grn_obj_register(ctx, ctx->impl->db, NULL, 0); + DB_OBJ(cursor)->header.domain = GRN_ID_NIL; + DB_OBJ(cursor)->range = GRN_ID_NIL; + grn_db_obj_init(ctx, ctx->impl->db, id, DB_OBJ(cursor)); + + GRN_API_RETURN((grn_obj *)cursor); +} + +grn_rc +grn_config_cursor_close(grn_ctx *ctx, grn_config_cursor *cursor) +{ + grn_hash_cursor_close(ctx, cursor->hash_cursor); + GRN_FREE(cursor); + + return GRN_SUCCESS; +} + +grn_bool +grn_config_cursor_next(grn_ctx *ctx, grn_obj *cursor) +{ + grn_bool have_next; + grn_config_cursor *config_cursor = (grn_config_cursor *)cursor; + + GRN_API_ENTER; + + have_next = grn_hash_cursor_next(ctx, config_cursor->hash_cursor) != GRN_ID_NIL; + + GRN_API_RETURN(have_next); +} + +uint32_t +grn_config_cursor_get_key(grn_ctx *ctx, grn_obj *cursor, const char **key) +{ + void *key_raw; + uint32_t key_size; + grn_config_cursor *config_cursor = (grn_config_cursor *)cursor; + + GRN_API_ENTER; + + key_size = grn_hash_cursor_get_key(ctx, config_cursor->hash_cursor, &key_raw); + *key = key_raw; + + GRN_API_RETURN(key_size); +} + +uint32_t +grn_config_cursor_get_value(grn_ctx *ctx, grn_obj *cursor, const char **value) +{ + void *value_raw; + uint32_t value_size; + uint32_t value_size_raw; + grn_config_cursor *config_cursor = (grn_config_cursor *)cursor; + + GRN_API_ENTER; + + value_size_raw = grn_hash_cursor_get_value(ctx, + config_cursor->hash_cursor, + &value_raw); + *value = (char *)value_raw + sizeof(uint32_t); + value_size = *((uint32_t *)value_raw); + + GRN_API_RETURN(value_size); +} + +/* Deprecated since 5.1.2. Use grn_config_* instead. */ +grn_rc +grn_conf_set(grn_ctx *ctx, + const char *key, int32_t key_size, + const char *value, int32_t value_size) +{ + return grn_config_set(ctx, key, key_size, value, value_size); +} + +grn_rc +grn_conf_get(grn_ctx *ctx, + const char *key, int32_t key_size, + const char **value, uint32_t *value_size) +{ + return grn_config_get(ctx, key, key_size, value, value_size); +} + diff --git a/storage/mroonga/vendor/groonga/lib/cpp_sources.am b/storage/mroonga/vendor/groonga/lib/cpp_sources.am new file mode 100644 index 00000000..c1d09a97 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/cpp_sources.am @@ -0,0 +1,3 @@ +libgroonga_cpp_source = \ + arrow.cpp \ + dat.cpp diff --git a/storage/mroonga/vendor/groonga/lib/ctx.c b/storage/mroonga/vendor/groonga/lib/ctx.c new file mode 100644 index 00000000..1fd912d4 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ctx.c @@ -0,0 +1,1873 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include +#include "grn_request_canceler.h" +#include "grn_request_timer.h" +#include "grn_tokenizers.h" +#include "grn_ctx_impl.h" +#include "grn_ii.h" +#include "grn_pat.h" +#include "grn_index_column.h" +#include "grn_proc.h" +#include "grn_plugin.h" +#include "grn_snip.h" +#include "grn_output.h" +#include "grn_normalizer.h" +#include "grn_mrb.h" +#include "grn_ctx_impl_mrb.h" +#include "grn_logger.h" +#include "grn_cache.h" +#include "grn_expr.h" +#include +#include +#include + +#ifdef GRN_WITH_ONIGMO +# define GRN_SUPPORT_REGEXP +#endif /* GRN_WITH_ONIGMO */ + +#ifdef GRN_SUPPORT_REGEXP +# include +#endif /* GRN_SUPPORT_REGEXP */ + +#ifdef WIN32 +# include +#else /* WIN32 */ +# include +#endif /* WIN32 */ + +#define GRN_CTX_INITIALIZER(enc) \ + { GRN_SUCCESS, 0, enc, 0, GRN_LOG_NOTICE,\ + GRN_CTX_FIN, 0, 0, 0, 0, {0}, NULL, NULL, NULL, NULL, NULL, \ + {NULL, NULL,NULL, NULL,NULL, NULL,NULL, NULL,NULL, NULL,NULL, NULL,NULL, NULL,NULL, NULL}, ""} + +#define GRN_CTX_CLOSED(ctx) ((ctx)->stat == GRN_CTX_FIN) + +grn_ctx grn_gctx = GRN_CTX_INITIALIZER(GRN_ENC_DEFAULT); +int grn_pagesize; +grn_critical_section grn_glock; +uint32_t grn_gtick; +int grn_lock_timeout = GRN_LOCK_TIMEOUT; + +#ifdef USE_UYIELD +int grn_uyield_count = 0; +#endif + +static grn_bool grn_ctx_per_db = GRN_FALSE; + +static void +grn_init_from_env(void) +{ + { + char grn_ctx_per_db_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_CTX_PER_DB", + grn_ctx_per_db_env, + GRN_ENV_BUFFER_SIZE); + if (grn_ctx_per_db_env[0] && strcmp(grn_ctx_per_db_env, "yes") == 0) { + grn_ctx_per_db = GRN_TRUE; + } + } + + grn_alloc_init_from_env(); + grn_mrb_init_from_env(); + grn_ctx_impl_mrb_init_from_env(); + grn_io_init_from_env(); + grn_ii_init_from_env(); + grn_db_init_from_env(); + grn_expr_init_from_env(); + grn_index_column_init_from_env(); + grn_proc_init_from_env(); + grn_plugin_init_from_env(); +} + +static void +grn_init_external_libraries(void) +{ +#ifdef GRN_SUPPORT_REGEXP + onig_init(); +#endif /* GRN_SUPPORT_REGEXP */ +} + +static void +grn_fin_external_libraries(void) +{ +#ifdef GRN_SUPPORT_REGEXP + onig_end(); +#endif /* GRN_SUPPORT_REGEXP */ +} + +void +grn_sleep(uint32_t seconds) +{ +#ifdef WIN32 + Sleep(seconds * 1000); +#else // WIN32 + sleep(seconds); +#endif // WIN32 +} + +void +grn_nanosleep(uint64_t nanoseconds) +{ +#ifdef WIN32 + Sleep((DWORD)(nanoseconds / 1000000)); +#else // WIN32 + struct timespec interval; + interval.tv_sec = (time_t)(nanoseconds / 1000000000); + interval.tv_nsec = (long)(nanoseconds % 1000000000); + nanosleep(&interval, NULL); +#endif // WIN32 +} + +const char * +grn_get_global_error_message(void) +{ + return grn_gctx.errbuf; +} + +static void +grn_loader_init(grn_loader *loader) +{ + GRN_TEXT_INIT(&loader->values, 0); + GRN_UINT32_INIT(&loader->level, GRN_OBJ_VECTOR); + GRN_PTR_INIT(&loader->columns, GRN_OBJ_VECTOR, GRN_ID_NIL); + GRN_UINT32_INIT(&loader->ids, GRN_OBJ_VECTOR); + GRN_INT32_INIT(&loader->return_codes, GRN_OBJ_VECTOR); + GRN_TEXT_INIT(&loader->error_messages, GRN_OBJ_VECTOR); + loader->id_offset = -1; + loader->key_offset = -1; + loader->table = NULL; + loader->last = NULL; + loader->ifexists = NULL; + loader->each = NULL; + loader->values_size = 0; + loader->nrecords = 0; + loader->stat = GRN_LOADER_BEGIN; + loader->columns_status = GRN_LOADER_COLUMNS_UNSET; + loader->rc = GRN_SUCCESS; + loader->errbuf[0] = '\0'; + loader->output_ids = GRN_FALSE; + loader->output_errors = GRN_FALSE; +} + +void +grn_ctx_loader_clear(grn_ctx *ctx) +{ + grn_loader *loader = &ctx->impl->loader; + grn_obj *v = (grn_obj *)(GRN_BULK_HEAD(&loader->values)); + grn_obj *ve = (grn_obj *)(GRN_BULK_CURR(&loader->values)); + grn_obj **p = (grn_obj **)GRN_BULK_HEAD(&loader->columns); + uint32_t i = GRN_BULK_VSIZE(&loader->columns) / sizeof(grn_obj *); + if (ctx->impl->db) { while (i--) { grn_obj_unlink(ctx, *p++); } } + if (loader->ifexists) { grn_obj_unlink(ctx, loader->ifexists); } + if (loader->each) { grn_obj_unlink(ctx, loader->each); } + while (v < ve) { GRN_OBJ_FIN(ctx, v++); } + GRN_OBJ_FIN(ctx, &loader->values); + GRN_OBJ_FIN(ctx, &loader->level); + GRN_OBJ_FIN(ctx, &loader->columns); + GRN_OBJ_FIN(ctx, &loader->ids); + GRN_OBJ_FIN(ctx, &loader->return_codes); + GRN_OBJ_FIN(ctx, &loader->error_messages); + grn_loader_init(loader); +} + +#define IMPL_SIZE ((sizeof(struct _grn_ctx_impl) + (grn_pagesize - 1)) & ~(grn_pagesize - 1)) + +#ifdef GRN_WITH_MESSAGE_PACK +static int +grn_msgpack_buffer_write(void *data, const char *buf, msgpack_size_t len) +{ + grn_ctx *ctx = (grn_ctx *)data; + return grn_bulk_write(ctx, ctx->impl->output.buf, buf, len); +} +#endif + +static grn_rc +grn_ctx_impl_init(grn_ctx *ctx) +{ + grn_io_mapinfo mi; + if (!(ctx->impl = grn_io_anon_map(ctx, &mi, IMPL_SIZE))) { + return ctx->rc; + } + grn_alloc_init_ctx_impl(ctx); + ctx->impl->encoding = ctx->encoding; + ctx->impl->lifoseg = -1; + ctx->impl->currseg = -1; + CRITICAL_SECTION_INIT(ctx->impl->lock); + if (!(ctx->impl->values = grn_array_create(ctx, NULL, sizeof(grn_db_obj *), + GRN_ARRAY_TINY))) { + CRITICAL_SECTION_FIN(ctx->impl->lock); + grn_io_anon_unmap(ctx, &mi, IMPL_SIZE); + ctx->impl = NULL; + return ctx->rc; + } + if (!(ctx->impl->temporary_columns = grn_pat_create(ctx, NULL, + GRN_TABLE_MAX_KEY_SIZE, + sizeof(grn_obj *), + 0))) { + grn_array_close(ctx, ctx->impl->values); + CRITICAL_SECTION_FIN(ctx->impl->lock); + grn_io_anon_unmap(ctx, &mi, IMPL_SIZE); + ctx->impl = NULL; + return ctx->rc; + } + if (!(ctx->impl->ios = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, + sizeof(grn_io *), + GRN_OBJ_KEY_VAR_SIZE|GRN_HASH_TINY))) { + grn_array_close(ctx, ctx->impl->values); + grn_pat_close(ctx, ctx->impl->temporary_columns); + CRITICAL_SECTION_FIN(ctx->impl->lock); + grn_io_anon_unmap(ctx, &mi, IMPL_SIZE); + ctx->impl = NULL; + return ctx->rc; + } + ctx->impl->db = NULL; + + ctx->impl->expr_vars = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_obj *), 0); + ctx->impl->stack_curr = 0; + ctx->impl->curr_expr = NULL; + GRN_TEXT_INIT(&ctx->impl->current_request_id, 0); + ctx->impl->current_request_timer_id = NULL; + ctx->impl->parser = NULL; + + GRN_TEXT_INIT(&ctx->impl->output.names, GRN_OBJ_VECTOR); + GRN_UINT32_INIT(&ctx->impl->output.levels, GRN_OBJ_VECTOR); + + ctx->impl->command.flags = 0; + if (ctx == &grn_gctx) { + ctx->impl->command.version = GRN_COMMAND_VERSION_STABLE; + } else { + ctx->impl->command.version = grn_get_default_command_version(); + } + ctx->impl->command.keep.command = NULL; + ctx->impl->command.keep.version = ctx->impl->command.version; + + if (ctx == &grn_gctx) { + ctx->impl->match_escalation_threshold = + GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD; + } else { + ctx->impl->match_escalation_threshold = + grn_get_default_match_escalation_threshold(); + } + + ctx->impl->finalizer = NULL; + + ctx->impl->com = NULL; + ctx->impl->output.buf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT); + ctx->impl->output.func = NULL; + ctx->impl->output.data.ptr = NULL; +#ifdef GRN_WITH_MESSAGE_PACK + msgpack_packer_init(&ctx->impl->output.msgpacker, + ctx, grn_msgpack_buffer_write); +#endif + ctx->impl->tv.tv_sec = 0; + ctx->impl->tv.tv_nsec = 0; + ctx->impl->edge = NULL; + grn_loader_init(&ctx->impl->loader); + ctx->impl->plugin_path = NULL; + + GRN_TEXT_INIT(&ctx->impl->query_log_buf, 0); + + ctx->impl->previous_errbuf[0] = '\0'; + ctx->impl->n_same_error_messages = 0; + + grn_ctx_impl_mrb_init(ctx); + + GRN_TEXT_INIT(&(ctx->impl->temporary_open_spaces.stack), 0); + ctx->impl->temporary_open_spaces.current = NULL; + + return ctx->rc; +} + +void +grn_ctx_set_keep_command(grn_ctx *ctx, grn_obj *command) +{ + ctx->impl->command.keep.command = command; + ctx->impl->command.keep.version = ctx->impl->command.version; +} + +static void +grn_ctx_impl_clear_n_same_error_messagges(grn_ctx *ctx) +{ + if (ctx->impl->n_same_error_messages == 0) { + return; + } + + GRN_LOG(ctx, GRN_LOG_NOTICE, "(%u same messages are truncated)", + ctx->impl->n_same_error_messages); + ctx->impl->n_same_error_messages = 0; +} + +grn_bool +grn_ctx_impl_should_log(grn_ctx *ctx) +{ + if (!ctx->impl) { + return GRN_TRUE; + } + + if (strcmp(ctx->errbuf, ctx->impl->previous_errbuf) == 0) { + ctx->impl->n_same_error_messages++; + return GRN_FALSE; + } + + return GRN_TRUE; +} + +void +grn_ctx_impl_set_current_error_message(grn_ctx *ctx) +{ + if (!ctx->impl) { + return; + } + + grn_ctx_impl_clear_n_same_error_messagges(ctx); + grn_strcpy(ctx->impl->previous_errbuf, GRN_CTX_MSGSIZE, ctx->errbuf); +} + +static grn_rc +grn_ctx_init_internal(grn_ctx *ctx, int flags) +{ + if (!ctx) { return GRN_INVALID_ARGUMENT; } + // if (ctx->stat != GRN_CTX_FIN) { return GRN_INVALID_ARGUMENT; } + ctx->rc = GRN_SUCCESS; + ERRCLR(ctx); + ctx->flags = flags; + if (grn_ctx_per_db) { + ctx->flags |= GRN_CTX_PER_DB; + } + ctx->stat = GRN_CTX_INITED; + ctx->encoding = grn_gctx.encoding; + ctx->seqno = 0; + ctx->seqno2 = 0; + ctx->subno = 0; + ctx->impl = NULL; + ctx->user_data.ptr = NULL; + CRITICAL_SECTION_ENTER(grn_glock); + ctx->next = grn_gctx.next; + ctx->prev = &grn_gctx; + grn_gctx.next->prev = ctx; + grn_gctx.next = ctx; + CRITICAL_SECTION_LEAVE(grn_glock); + ctx->errline = 0; + ctx->errfile = ""; + ctx->errfunc = ""; + ctx->trace[0] = NULL; + ctx->errbuf[0] = '\0'; + return GRN_SUCCESS; +} + +grn_rc +grn_ctx_init(grn_ctx *ctx, int flags) +{ + grn_rc rc; + + rc = grn_ctx_init_internal(ctx, flags); + if (rc == GRN_SUCCESS) { + grn_ctx_impl_init(ctx); + rc = ctx->rc; + if (rc != GRN_SUCCESS) { + grn_ctx_fin(ctx); + if (flags & GRN_CTX_ALLOCATED) { + CRITICAL_SECTION_ENTER(grn_glock); + ctx->next->prev = ctx->prev; + ctx->prev->next = ctx->next; + CRITICAL_SECTION_LEAVE(grn_glock); + } + } + } + + return rc; +} + +grn_ctx * +grn_ctx_open(int flags) +{ + grn_ctx *ctx = GRN_GMALLOCN(grn_ctx, 1); + if (ctx) { + grn_ctx_init(ctx, flags|GRN_CTX_ALLOCATED); + if (ERRP(ctx, GRN_ERROR)) { + GRN_GFREE(ctx); + ctx = NULL; + } + } + return ctx; +} + +grn_rc +grn_ctx_fin(grn_ctx *ctx) +{ + grn_rc rc = GRN_SUCCESS; + if (!ctx) { return GRN_INVALID_ARGUMENT; } + if (ctx->stat == GRN_CTX_FIN) { return GRN_INVALID_ARGUMENT; } + if (!(ctx->flags & GRN_CTX_ALLOCATED)) { + CRITICAL_SECTION_ENTER(grn_glock); + ctx->next->prev = ctx->prev; + ctx->prev->next = ctx->next; + CRITICAL_SECTION_LEAVE(grn_glock); + } + if (ctx->impl) { + grn_ctx_impl_clear_n_same_error_messagges(ctx); + if (ctx->impl->finalizer) { + ctx->impl->finalizer(ctx, 0, NULL, &(ctx->user_data)); + } + { + grn_obj *stack; + grn_obj *spaces; + unsigned int i, n_spaces; + + stack = &(ctx->impl->temporary_open_spaces.stack); + spaces = (grn_obj *)GRN_BULK_HEAD(stack); + n_spaces = GRN_BULK_VSIZE(stack) / sizeof(grn_obj); + for (i = 0; i < n_spaces; i++) { + grn_obj *space = spaces + (n_spaces - i - 1); + GRN_OBJ_FIN(ctx, space); + } + GRN_OBJ_FIN(ctx, stack); + } + grn_ctx_impl_mrb_fin(ctx); + grn_ctx_loader_clear(ctx); + if (ctx->impl->parser) { + grn_expr_parser_close(ctx); + } + GRN_OBJ_FIN(ctx, &ctx->impl->current_request_id); + if (ctx->impl->values) { +#ifndef USE_MEMORY_DEBUG + grn_db_obj *o; + GRN_ARRAY_EACH(ctx, ctx->impl->values, 0, 0, id, &o, { + grn_obj_close(ctx, *((grn_obj **)o)); + }); +#endif + grn_array_close(ctx, ctx->impl->values); + } + if (ctx->impl->temporary_columns) { +#ifndef USE_MEMORY_DEBUG + grn_obj *value; + GRN_PAT_EACH(ctx, ctx->impl->temporary_columns, id, NULL, NULL, &value, { + grn_obj_close(ctx, *((grn_obj **)value)); + }); +#endif + grn_pat_close(ctx, ctx->impl->temporary_columns); + } + if (ctx->impl->ios) { + grn_hash_close(ctx, ctx->impl->ios); + } + if (ctx->impl->com) { + if (ctx->stat != GRN_CTX_QUIT) { + int flags; + char *str; + unsigned int str_len; + grn_ctx_send(ctx, "quit", 4, GRN_CTX_HEAD); + grn_ctx_recv(ctx, &str, &str_len, &flags); + } + grn_ctx_send(ctx, "ACK", 3, GRN_CTX_HEAD); + rc = grn_com_close(ctx, ctx->impl->com); + } + GRN_OBJ_FIN(ctx, &ctx->impl->query_log_buf); + GRN_OBJ_FIN(ctx, &ctx->impl->output.names); + GRN_OBJ_FIN(ctx, &ctx->impl->output.levels); + rc = grn_obj_close(ctx, ctx->impl->output.buf); + { + grn_hash **vp; + grn_obj *value; + GRN_HASH_EACH(ctx, ctx->impl->expr_vars, eid, NULL, NULL, &vp, { + if (*vp) { + GRN_HASH_EACH(ctx, *vp, id, NULL, NULL, &value, { + GRN_OBJ_FIN(ctx, value); + }); + } + grn_hash_close(ctx, *vp); + }); + } + grn_hash_close(ctx, ctx->impl->expr_vars); + if (ctx->impl->db && ctx->flags & GRN_CTX_PER_DB) { + grn_obj *db = ctx->impl->db; + ctx->impl->db = NULL; + grn_obj_close(ctx, db); + } + grn_alloc_fin_ctx_impl(ctx); + grn_alloc_info_dump(ctx); + grn_alloc_info_free(ctx); + CRITICAL_SECTION_FIN(ctx->impl->lock); + { + grn_io_mapinfo mi; + mi.map = (void *)ctx->impl; + grn_io_anon_unmap(ctx, &mi, IMPL_SIZE); + } + ctx->impl = NULL; + } + ctx->stat = GRN_CTX_FIN; + return rc; +} + +grn_rc +grn_ctx_set_finalizer(grn_ctx *ctx, grn_proc_func *finalizer) +{ + if (!ctx) { return GRN_INVALID_ARGUMENT; } + if (!ctx->impl) { + if (ERRP(ctx, GRN_ERROR)) { return ctx->rc; } + } + ctx->impl->finalizer = finalizer; + return GRN_SUCCESS; +} + +grn_timeval grn_starttime; + +static void +check_overcommit_memory(grn_ctx *ctx) +{ + FILE *file; + int value; + file = grn_fopen("/proc/sys/vm/overcommit_memory", "r"); + if (!file) { return; } + value = fgetc(file); + if (value != '1') { + GRN_LOG(ctx, GRN_LOG_NOTICE, + "vm.overcommit_memory kernel parameter should be 1: <%c>: " + "See INFO level log to resolve this", + value); + GRN_LOG(ctx, GRN_LOG_INFO, + "Some processings with vm.overcommit_memory != 1 " + "may break DB under low memory condition."); + GRN_LOG(ctx, GRN_LOG_INFO, + "To set vm.overcommit_memory to 1"); + GRN_LOG(ctx, GRN_LOG_INFO, + "add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and " + "restart your system or"); + GRN_LOG(ctx, GRN_LOG_INFO, + "run 'sudo /sbin/sysctl vm.overcommit_memory=1' command."); + } + fclose(file); +} + +grn_rc +grn_init(void) +{ + grn_rc rc; + grn_ctx *ctx = &grn_gctx; + grn_init_from_env(); + grn_init_external_libraries(); + grn_alloc_info_init(); + grn_logger_init(); + grn_query_logger_init(); + CRITICAL_SECTION_INIT(grn_glock); + grn_gtick = 0; + ctx->next = ctx; + ctx->prev = ctx; + rc = grn_ctx_init_internal(ctx, 0); + if (rc) { + goto fail_ctx_init_internal; + } + ctx->encoding = grn_encoding_parse(GRN_DEFAULT_ENCODING); + rc = grn_timeval_now(ctx, &grn_starttime); + if (rc) { + goto fail_start_time; + } +#ifdef WIN32 + { + SYSTEM_INFO si; + GetSystemInfo(&si); + grn_pagesize = si.dwAllocationGranularity; + } +#else /* WIN32 */ + if ((grn_pagesize = sysconf(_SC_PAGESIZE)) == -1) { + SERR("_SC_PAGESIZE"); + rc = ctx->rc; + goto fail_page_size; + } +#endif /* WIN32 */ + if (grn_pagesize & (grn_pagesize - 1)) { + GRN_LOG(ctx, GRN_LOG_CRIT, "pagesize=%x", grn_pagesize); + } + // expand_stack(); + if ((rc = grn_com_init())) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_com_init failed (%d)", rc); + goto fail_com; + } + if ((rc = grn_ctx_impl_init(ctx))) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_ctx_impl_init failed (%d)", rc); + goto fail_ctx_impl; + } + if ((rc = grn_plugins_init())) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_plugins_init failed (%d)", rc); + goto fail_plugins; + } + if ((rc = grn_normalizer_init())) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_normalizer_init failed (%d)", rc); + goto fail_normalizer; + } + if ((rc = grn_tokenizers_init())) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_tokenizers_init failed (%d)", rc); + goto fail_tokenizer; + } + grn_cache_init(); + if (!grn_request_canceler_init()) { + rc = ctx->rc; + GRN_LOG(ctx, GRN_LOG_ALERT, + "failed to initialize request canceler (%d)", rc); + goto fail_request_canceler; + } + if (!grn_request_timer_init()) { + rc = ctx->rc; + GRN_LOG(ctx, GRN_LOG_ALERT, + "failed to initialize request timer (%d)", rc); + goto fail_request_timer; + } + GRN_LOG(ctx, GRN_LOG_NOTICE, "grn_init: <%s>", grn_get_version()); + check_overcommit_memory(ctx); + return rc; + +fail_request_timer: + grn_request_canceler_fin(); +fail_request_canceler: + grn_cache_fin(); +fail_tokenizer: + grn_normalizer_fin(); +fail_normalizer: + grn_plugins_fin(); +fail_plugins: + grn_ctx_fin(ctx); +fail_ctx_impl: + grn_com_fin(); +fail_com: +#ifndef WIN32 +fail_page_size: +#endif /* WIN32 */ +fail_start_time: +fail_ctx_init_internal: + GRN_LOG(ctx, GRN_LOG_NOTICE, "grn_init: <%s>: failed", grn_get_version()); + grn_query_logger_fin(ctx); + grn_logger_fin(ctx); + CRITICAL_SECTION_FIN(grn_glock); + grn_alloc_info_fin(); + grn_fin_external_libraries(); + return rc; +} + +grn_encoding +grn_get_default_encoding(void) +{ + return grn_gctx.encoding; +} + +grn_rc +grn_set_default_encoding(grn_encoding encoding) +{ + switch (encoding) { + case GRN_ENC_DEFAULT : + grn_gctx.encoding = grn_encoding_parse(GRN_DEFAULT_ENCODING); + return GRN_SUCCESS; + case GRN_ENC_NONE : + case GRN_ENC_EUC_JP : + case GRN_ENC_UTF8 : + case GRN_ENC_SJIS : + case GRN_ENC_LATIN1 : + case GRN_ENC_KOI8R : + grn_gctx.encoding = encoding; + return GRN_SUCCESS; + default : + return GRN_INVALID_ARGUMENT; + } +} + +grn_command_version +grn_get_default_command_version(void) +{ + return grn_ctx_get_command_version(&grn_gctx); +} + +grn_rc +grn_set_default_command_version(grn_command_version version) +{ + return grn_ctx_set_command_version(&grn_gctx, version); +} + +long long int +grn_get_default_match_escalation_threshold(void) +{ + return grn_ctx_get_match_escalation_threshold(&grn_gctx); +} + +grn_rc +grn_set_default_match_escalation_threshold(long long int threshold) +{ + return grn_ctx_set_match_escalation_threshold(&grn_gctx, threshold); +} + +int +grn_get_lock_timeout(void) +{ + return grn_lock_timeout; +} + +grn_rc +grn_set_lock_timeout(int timeout) +{ + grn_lock_timeout = timeout; + return GRN_SUCCESS; +} + +grn_rc +grn_fin(void) +{ + grn_ctx *ctx, *ctx_; + if (grn_gctx.stat == GRN_CTX_FIN) { return GRN_INVALID_ARGUMENT; } + for (ctx = grn_gctx.next; ctx != &grn_gctx; ctx = ctx_) { + ctx_ = ctx->next; + if (ctx->stat != GRN_CTX_FIN) { grn_ctx_fin(ctx); } + if (ctx->flags & GRN_CTX_ALLOCATED) { + ctx->next->prev = ctx->prev; + ctx->prev->next = ctx->next; + GRN_GFREE(ctx); + } + } + grn_query_logger_fin(ctx); + grn_request_timer_fin(); + grn_request_canceler_fin(); + grn_cache_fin(); + grn_tokenizers_fin(); + grn_normalizer_fin(); + grn_plugins_fin(); + grn_ctx_fin(ctx); + grn_com_fin(); + GRN_LOG(ctx, GRN_LOG_NOTICE, "grn_fin (%d)", grn_alloc_count()); + grn_logger_fin(ctx); + CRITICAL_SECTION_FIN(grn_glock); + grn_alloc_info_fin(); + grn_fin_external_libraries(); + return GRN_SUCCESS; +} + +grn_rc +grn_ctx_connect(grn_ctx *ctx, const char *host, int port, int flags) +{ + GRN_API_ENTER; + if (!ctx->impl) { goto exit; } + { + grn_com *com = grn_com_copen(ctx, NULL, host, port); + if (com) { + ctx->impl->com = com; + } + } +exit : + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_ctx_close(grn_ctx *ctx) +{ + grn_rc rc = grn_ctx_fin(ctx); + CRITICAL_SECTION_ENTER(grn_glock); + ctx->next->prev = ctx->prev; + ctx->prev->next = ctx->next; + CRITICAL_SECTION_LEAVE(grn_glock); + GRN_GFREE(ctx); + return rc; +} + +grn_command_version +grn_ctx_get_command_version(grn_ctx *ctx) +{ + if (ctx->impl) { + return ctx->impl->command.version; + } else { + return GRN_COMMAND_VERSION_STABLE; + } +} + +grn_rc +grn_ctx_set_command_version(grn_ctx *ctx, grn_command_version version) +{ + switch (version) { + case GRN_COMMAND_VERSION_DEFAULT : + ctx->impl->command.version = GRN_COMMAND_VERSION_STABLE; + return GRN_SUCCESS; + default : + if (GRN_COMMAND_VERSION_MIN <= version && + version <= GRN_COMMAND_VERSION_MAX) { + ctx->impl->command.version = version; + return GRN_SUCCESS; + } else { + return GRN_UNSUPPORTED_COMMAND_VERSION; + } + } +} + +grn_content_type +grn_ctx_get_output_type(grn_ctx *ctx) +{ + if (ctx->impl) { + return ctx->impl->output.type; + } else { + return GRN_CONTENT_NONE; + } +} + +grn_rc +grn_ctx_set_output_type(grn_ctx *ctx, grn_content_type type) +{ + grn_rc rc = GRN_SUCCESS; + + if (ctx->impl) { + ctx->impl->output.type = type; + switch (ctx->impl->output.type) { + case GRN_CONTENT_NONE : + ctx->impl->output.mime_type = "application/octet-stream"; + break; + case GRN_CONTENT_TSV : + ctx->impl->output.mime_type = "text/tab-separated-values"; + break; + case GRN_CONTENT_JSON : + ctx->impl->output.mime_type = "application/json"; + break; + case GRN_CONTENT_XML : + ctx->impl->output.mime_type = "text/xml"; + break; + case GRN_CONTENT_MSGPACK : + ctx->impl->output.mime_type = "application/x-msgpack"; + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + ctx->impl->output.mime_type = "text/x-groonga-command-list"; + break; + } + } else { + rc = GRN_INVALID_ARGUMENT; + } + + return rc; +} + +const char * +grn_ctx_get_mime_type(grn_ctx *ctx) +{ + if (ctx->impl) { + return ctx->impl->output.mime_type; + } else { + return NULL; + } +} + +long long int +grn_ctx_get_match_escalation_threshold(grn_ctx *ctx) +{ + if (ctx->impl) { + return ctx->impl->match_escalation_threshold; + } else { + return GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD; + } +} + +grn_rc +grn_ctx_set_match_escalation_threshold(grn_ctx *ctx, long long int threshold) +{ + ctx->impl->match_escalation_threshold = threshold; + return GRN_SUCCESS; +} + +grn_content_type +grn_get_ctype(grn_obj *var) +{ + return grn_content_type_parse(NULL, var, GRN_CONTENT_JSON); +} + +grn_content_type +grn_content_type_parse(grn_ctx *ctx, + grn_obj *var, + grn_content_type default_value) +{ + grn_content_type ct = default_value; + if (var->header.domain == GRN_DB_INT32) { + ct = GRN_INT32_VALUE(var); + } else if (GRN_TEXT_LEN(var)) { + switch (*(GRN_TEXT_VALUE(var))) { + case 't' : + case 'T' : + ct = GRN_CONTENT_TSV; + break; + case 'j' : + case 'J' : + ct = GRN_CONTENT_JSON; + break; + case 'x' : + case 'X' : + ct = GRN_CONTENT_XML; + break; + } + } + return ct; +} + +static void +get_content_mime_type(grn_ctx *ctx, const char *p, const char *pe) +{ + ctx->impl->output.type = GRN_CONTENT_NONE; + ctx->impl->output.mime_type = "application/octet-stream"; + + if (p + 2 <= pe) { + switch (*p) { + case 'c' : + if (p + 3 == pe && !memcmp(p, "css", 3)) { + ctx->impl->output.type = GRN_CONTENT_NONE; + ctx->impl->output.mime_type = "text/css"; + } + break; + case 'g' : + if (p + 3 == pe && !memcmp(p, "gif", 3)) { + ctx->impl->output.type = GRN_CONTENT_NONE; + ctx->impl->output.mime_type = "image/gif"; + } + break; + case 'h' : + if (p + 4 == pe && !memcmp(p, "html", 4)) { + ctx->impl->output.type = GRN_CONTENT_NONE; + ctx->impl->output.mime_type = "text/html"; + } + break; + case 'j' : + if (!memcmp(p, "js", 2)) { + if (p + 2 == pe) { + ctx->impl->output.type = GRN_CONTENT_NONE; + ctx->impl->output.mime_type = "text/javascript"; + } else if (p + 4 == pe && !memcmp(p + 2, "on", 2)) { + ctx->impl->output.type = GRN_CONTENT_JSON; + ctx->impl->output.mime_type = "application/json"; + } + } else if (p + 3 == pe && !memcmp(p, "jpg", 3)) { + ctx->impl->output.type = GRN_CONTENT_NONE; + ctx->impl->output.mime_type = "image/jpeg"; + } + break; +#ifdef GRN_WITH_MESSAGE_PACK + case 'm' : + if (p + 7 == pe && !memcmp(p, "msgpack", 7)) { + ctx->impl->output.type = GRN_CONTENT_MSGPACK; + ctx->impl->output.mime_type = "application/x-msgpack"; + } + break; +#endif + case 'p' : + if (p + 3 == pe && !memcmp(p, "png", 3)) { + ctx->impl->output.type = GRN_CONTENT_NONE; + ctx->impl->output.mime_type = "image/png"; + } + break; + case 't' : + if (p + 3 == pe && !memcmp(p, "txt", 3)) { + ctx->impl->output.type = GRN_CONTENT_NONE; + ctx->impl->output.mime_type = "text/plain"; + } else if (p + 3 == pe && !memcmp(p, "tsv", 3)) { + ctx->impl->output.type = GRN_CONTENT_TSV; + ctx->impl->output.mime_type = "text/tab-separated-values"; + } + break; + case 'x': + if (p + 3 == pe && !memcmp(p, "xml", 3)) { + ctx->impl->output.type = GRN_CONTENT_XML; + ctx->impl->output.mime_type = "text/xml"; + } + break; + } + } +} + +static void +grn_str_get_mime_type(grn_ctx *ctx, const char *p, const char *pe, + const char **key_end, const char **filename_end) +{ + const char *pd = NULL; + for (; p < pe && *p != '?' && *p != '#'; p++) { + if (*p == '.') { pd = p; } + } + *filename_end = p; + if (pd && pd < p) { + get_content_mime_type(ctx, pd + 1, p); + *key_end = pd; + } else { + *key_end = pe; + } +} + +static void +get_command_version(grn_ctx *ctx, const char *p, const char *pe) +{ + grn_command_version version; + const char *rest; + + version = grn_atoui(p, pe, &rest); + if (pe == rest) { + grn_rc rc; + rc = grn_ctx_set_command_version(ctx, version); + if (rc == GRN_UNSUPPORTED_COMMAND_VERSION) { + ERR(rc, + "unsupported command version is specified: %d: " + "stable command version: %d: " + "available command versions: %d-%d", + version, + GRN_COMMAND_VERSION_STABLE, + GRN_COMMAND_VERSION_MIN, GRN_COMMAND_VERSION_MAX); + } + } +} + +#define INDEX_HTML "index.html" +#define OUTPUT_TYPE "output_type" +#define COMMAND_VERSION "command_version" +#define REQUEST_ID "request_id" +#define REQUEST_TIMEOUT "request_timeout" +#define OUTPUT_PRETTY "output_pretty" +#define EXPR_MISSING "expr_missing" +#define OUTPUT_TYPE_LEN (sizeof(OUTPUT_TYPE) - 1) +#define COMMAND_VERSION_LEN (sizeof(COMMAND_VERSION) - 1) +#define REQUEST_ID_LEN (sizeof(REQUEST_ID) - 1) +#define REQUEST_TIMEOUT_LEN (sizeof(REQUEST_TIMEOUT) - 1) +#define OUTPUT_PRETTY_LEN (sizeof(OUTPUT_PRETTY) - 1) + +#define HTTP_QUERY_PAIR_DELIMITER "=" +#define HTTP_QUERY_PAIRS_DELIMITERS "&;" + +static inline int +command_proc_p(grn_obj *expr) +{ + return (expr->header.type == GRN_PROC && + ((grn_proc *)expr)->type == GRN_PROC_COMMAND); +} + +grn_obj * +grn_ctx_qe_exec_uri(grn_ctx *ctx, const char *path, uint32_t path_len) +{ + grn_obj buf, *expr, *val; + grn_obj request_id; + double request_timeout; + const char *p = path, *e = path + path_len, *v, *key_end, *filename_end; + + request_timeout = grn_get_default_request_timeout(); + + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_INIT(&request_id, 0); + p = grn_text_urldec(ctx, &buf, p, e, '?'); + if (!GRN_TEXT_LEN(&buf)) { GRN_TEXT_SETS(ctx, &buf, INDEX_HTML); } + v = GRN_TEXT_VALUE(&buf); + grn_str_get_mime_type(ctx, v, GRN_BULK_CURR(&buf), &key_end, &filename_end); + if ((GRN_TEXT_LEN(&buf) >= 2 && v[0] == 'd' && v[1] == '/')) { + const char *command_name = v + 2; + int command_name_size = key_end - command_name; + expr = grn_ctx_get(ctx, command_name, command_name_size); + if (expr && command_proc_p(expr)) { + while (p < e) { + int l; + GRN_BULK_REWIND(&buf); + p = grn_text_cgidec(ctx, &buf, p, e, HTTP_QUERY_PAIR_DELIMITER); + v = GRN_TEXT_VALUE(&buf); + l = GRN_TEXT_LEN(&buf); + if (l == OUTPUT_TYPE_LEN && !memcmp(v, OUTPUT_TYPE, OUTPUT_TYPE_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_cgidec(ctx, &buf, p, e, HTTP_QUERY_PAIRS_DELIMITERS); + v = GRN_TEXT_VALUE(&buf); + get_content_mime_type(ctx, v, GRN_BULK_CURR(&buf)); + } else if (l == COMMAND_VERSION_LEN && + !memcmp(v, COMMAND_VERSION, COMMAND_VERSION_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_cgidec(ctx, &buf, p, e, HTTP_QUERY_PAIRS_DELIMITERS); + get_command_version(ctx, GRN_TEXT_VALUE(&buf), GRN_BULK_CURR(&buf)); + if (ctx->rc) { goto exit; } + } else if (l == REQUEST_ID_LEN && + !memcmp(v, REQUEST_ID, REQUEST_ID_LEN)) { + GRN_BULK_REWIND(&request_id); + p = grn_text_cgidec(ctx, &request_id, p, e, + HTTP_QUERY_PAIRS_DELIMITERS); + } else if (l == REQUEST_TIMEOUT_LEN && + !memcmp(v, REQUEST_TIMEOUT, REQUEST_TIMEOUT_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_cgidec(ctx, &buf, p, e, HTTP_QUERY_PAIRS_DELIMITERS); + GRN_TEXT_PUTC(ctx, &buf, '\0'); + request_timeout = strtod(GRN_TEXT_VALUE(&buf), NULL); + } else if (l == OUTPUT_PRETTY_LEN && + !memcmp(v, OUTPUT_PRETTY, OUTPUT_PRETTY_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_cgidec(ctx, &buf, p, e, HTTP_QUERY_PAIRS_DELIMITERS); + if (GRN_TEXT_LEN(&buf) == strlen("yes") && + !memcmp(GRN_TEXT_VALUE(&buf), "yes", GRN_TEXT_LEN(&buf))) { + ctx->impl->output.is_pretty = GRN_TRUE; + } else { + ctx->impl->output.is_pretty = GRN_FALSE; + } + } else { + if (!(val = grn_expr_get_or_add_var(ctx, expr, v, l))) { + val = &buf; + } + grn_obj_reinit(ctx, val, GRN_DB_TEXT, 0); + p = grn_text_cgidec(ctx, val, p, e, HTTP_QUERY_PAIRS_DELIMITERS); + } + } + if (request_timeout > 0 && GRN_TEXT_LEN(&request_id) == 0) { + grn_text_printf(ctx, &request_id, "%p", ctx); + } + if (GRN_TEXT_LEN(&request_id) > 0) { + GRN_TEXT_SET(ctx, &ctx->impl->current_request_id, + GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id)); + grn_request_canceler_register(ctx, + GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id)); + if (request_timeout > 0.0) { + ctx->impl->current_request_timer_id = + grn_request_timer_register(GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id), + request_timeout); + } + } + ctx->impl->curr_expr = expr; + grn_expr_exec(ctx, expr, 0); + } else { + ERR(GRN_INVALID_ARGUMENT, "invalid command name: %.*s", + command_name_size, command_name); + } + } else if ((expr = grn_ctx_get(ctx, GRN_EXPR_MISSING_NAME, + strlen(GRN_EXPR_MISSING_NAME)))) { + if ((val = grn_expr_get_var_by_offset(ctx, expr, 0))) { + grn_obj_reinit(ctx, val, GRN_DB_TEXT, 0); + GRN_TEXT_SET(ctx, val, v, filename_end - v); + } + ctx->impl->curr_expr = expr; + grn_expr_exec(ctx, expr, 0); + } +exit : + GRN_OBJ_FIN(ctx, &request_id); + GRN_OBJ_FIN(ctx, &buf); + + return expr; +} + +grn_obj * +grn_ctx_qe_exec(grn_ctx *ctx, const char *str, uint32_t str_len) +{ + char tok_type; + int offset = 0; + grn_obj buf, *expr = NULL, *val = NULL; + grn_obj request_id; + double request_timeout; + const char *p = str, *e = str + str_len, *v; + + request_timeout = grn_get_default_request_timeout(); + + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_INIT(&request_id, 0); + p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type); + expr = grn_ctx_get(ctx, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); + while (p < e) { + GRN_BULK_REWIND(&buf); + p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type); + v = GRN_TEXT_VALUE(&buf); + switch (tok_type) { + case GRN_TOK_VOID : + p = e; + break; + case GRN_TOK_SYMBOL : + if (GRN_TEXT_LEN(&buf) > 2 && v[0] == '-' && v[1] == '-') { + int l = GRN_TEXT_LEN(&buf) - 2; + v += 2; + if (l == OUTPUT_TYPE_LEN && !memcmp(v, OUTPUT_TYPE, OUTPUT_TYPE_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type); + v = GRN_TEXT_VALUE(&buf); + get_content_mime_type(ctx, v, GRN_BULK_CURR(&buf)); + } else if (l == COMMAND_VERSION_LEN && + !memcmp(v, COMMAND_VERSION, COMMAND_VERSION_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type); + get_command_version(ctx, GRN_TEXT_VALUE(&buf), GRN_BULK_CURR(&buf)); + if (ctx->rc) { goto exit; } + } else if (l == REQUEST_ID_LEN && + !memcmp(v, REQUEST_ID, REQUEST_ID_LEN)) { + GRN_BULK_REWIND(&request_id); + p = grn_text_unesc_tok(ctx, &request_id, p, e, &tok_type); + } else if (l == REQUEST_TIMEOUT_LEN && + !memcmp(v, REQUEST_TIMEOUT, REQUEST_TIMEOUT_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type); + GRN_TEXT_PUTC(ctx, &buf, '\0'); + request_timeout = strtod(GRN_TEXT_VALUE(&buf), NULL); + } else if (l == OUTPUT_PRETTY_LEN && + !memcmp(v, OUTPUT_PRETTY, OUTPUT_PRETTY_LEN)) { + GRN_BULK_REWIND(&buf); + p = grn_text_unesc_tok(ctx, &buf, p, e, &tok_type); + if (GRN_TEXT_LEN(&buf) == strlen("yes") && + !memcmp(GRN_TEXT_VALUE(&buf), "yes", GRN_TEXT_LEN(&buf))) { + ctx->impl->output.is_pretty = GRN_TRUE; + } else { + ctx->impl->output.is_pretty = GRN_FALSE; + } + } else if (expr && (val = grn_expr_get_or_add_var(ctx, expr, v, l))) { + grn_obj_reinit(ctx, val, GRN_DB_TEXT, 0); + p = grn_text_unesc_tok(ctx, val, p, e, &tok_type); + } else { + p = e; + } + break; + } + // fallthru + case GRN_TOK_STRING : + case GRN_TOK_QUOTE : + if (expr && (val = grn_expr_get_var_by_offset(ctx, expr, offset++))) { + grn_obj_reinit(ctx, val, GRN_DB_TEXT, 0); + GRN_TEXT_PUT(ctx, val, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); + } else { + p = e; + } + break; + } + } + if (request_timeout > 0 && GRN_TEXT_LEN(&request_id) == 0) { + grn_text_printf(ctx, &request_id, "%p", ctx); + } + if (GRN_TEXT_LEN(&request_id) > 0) { + GRN_TEXT_SET(ctx, &ctx->impl->current_request_id, + GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id)); + grn_request_canceler_register(ctx, + GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id)); + if (request_timeout > 0.0) { + ctx->impl->current_request_timer_id = + grn_request_timer_register(GRN_TEXT_VALUE(&request_id), + GRN_TEXT_LEN(&request_id), + request_timeout); + } + } + ctx->impl->curr_expr = expr; + if (expr && command_proc_p(expr)) { + grn_expr_exec(ctx, expr, 0); + } else { + GRN_BULK_REWIND(&buf); + grn_text_unesc_tok(ctx, &buf, str, str + str_len, &tok_type); + if (GRN_TEXT_LEN(&buf)) { + ERR(GRN_INVALID_ARGUMENT, "invalid command name: %.*s", + (int)GRN_TEXT_LEN(&buf), GRN_TEXT_VALUE(&buf)); + } + } +exit : + GRN_OBJ_FIN(ctx, &request_id); + GRN_OBJ_FIN(ctx, &buf); + + return expr; +} + +grn_rc +grn_ctx_sendv(grn_ctx *ctx, int argc, char **argv, int flags) +{ + grn_obj buf; + GRN_API_ENTER; + GRN_TEXT_INIT(&buf, 0); + while (argc--) { + // todo : encode into json like syntax + GRN_TEXT_PUTS(ctx, &buf, *argv); + argv++; + if (argc) { GRN_TEXT_PUTC(ctx, &buf, ' '); } + } + grn_ctx_send(ctx, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf), flags); + GRN_OBJ_FIN(ctx, &buf); + GRN_API_RETURN(ctx->rc); +} + +static int +comment_command_p(const char *command, unsigned int length) +{ + const char *p, *e; + + e = command + length; + for (p = command; p < e; p++) { + switch (*p) { + case '#' : + return GRN_TRUE; + case ' ' : + case '\t' : + break; + default : + return GRN_FALSE; + } + } + return GRN_FALSE; +} + +unsigned int +grn_ctx_send(grn_ctx *ctx, const char *str, unsigned int str_len, int flags) +{ + if (!ctx) { return 0; } + GRN_API_ENTER; + if (ctx->impl) { + if ((flags & GRN_CTX_MORE)) { flags |= GRN_CTX_QUIET; } + if (ctx->stat == GRN_CTX_QUIT) { flags |= GRN_CTX_QUIT; } + + ctx->impl->command.flags = flags; + if (ctx->impl->com) { + grn_rc rc; + grn_com_header sheader; + grn_timeval_now(ctx, &ctx->impl->tv); + sheader.proto = GRN_COM_PROTO_GQTP; + sheader.qtype = 0; + sheader.keylen = 0; + sheader.level = 0; + sheader.flags = flags; + sheader.status = 0; + sheader.opaque = 0; + sheader.cas = 0; + if ((rc = grn_com_send(ctx, ctx->impl->com, &sheader, (char *)str, str_len, 0))) { + ERR(rc, "grn_com_send failed"); + } + goto exit; + } else { + grn_command_version command_version; + grn_obj *expr = NULL; + + command_version = grn_ctx_get_command_version(ctx); + if (ctx->impl->command.keep.command) { + grn_obj *val; + expr = ctx->impl->command.keep.command; + ctx->impl->command.keep.command = NULL; + grn_ctx_set_command_version(ctx, ctx->impl->command.keep.version); + if ((val = grn_expr_get_var_by_offset(ctx, expr, 0))) { + grn_obj_reinit(ctx, val, GRN_DB_TEXT, 0); + GRN_TEXT_PUT(ctx, val, str, str_len); + } + grn_expr_exec(ctx, expr, 0); + } else { + if (comment_command_p(str, str_len)) { goto output; }; + GRN_BULK_REWIND(ctx->impl->output.buf); + ctx->impl->output.type = GRN_CONTENT_JSON; + ctx->impl->output.mime_type = "application/json"; + ctx->impl->output.is_pretty = GRN_FALSE; + grn_timeval_now(ctx, &ctx->impl->tv); + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_COMMAND, + ">", "%.*s", str_len, str); + if (str_len && *str == '/') { + expr = grn_ctx_qe_exec_uri(ctx, str + 1, str_len - 1); + } else { + expr = grn_ctx_qe_exec(ctx, str, str_len); + } + } + if (ctx->stat == GRN_CTX_QUITTING) { ctx->stat = GRN_CTX_QUIT; } + if (ctx->impl->command.keep.command) { + ERRCLR(ctx); + } else { + if (ctx->impl->current_request_timer_id) { + void *timer_id = ctx->impl->current_request_timer_id; + ctx->impl->current_request_timer_id = NULL; + grn_request_timer_unregister(timer_id); + } + if (GRN_TEXT_LEN(&ctx->impl->current_request_id) > 0) { + grn_obj *request_id = &ctx->impl->current_request_id; + grn_request_canceler_unregister(ctx, + GRN_TEXT_VALUE(request_id), + GRN_TEXT_LEN(request_id)); + GRN_BULK_REWIND(&ctx->impl->current_request_id); + } + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_RESULT_CODE, + "<", "rc=%d", ctx->rc); + } + output : + if (!(ctx->impl->command.flags & GRN_CTX_QUIET) && + ctx->impl->output.func) { + ctx->impl->output.func(ctx, GRN_CTX_TAIL, ctx->impl->output.data.ptr); + } + if (expr) { grn_expr_clear_vars(ctx, expr); } + grn_ctx_set_command_version(ctx, command_version); + goto exit; + } + } + ERR(GRN_INVALID_ARGUMENT, "invalid ctx assigned"); +exit : + GRN_API_RETURN(0); +} + +unsigned int +grn_ctx_recv(grn_ctx *ctx, char **str, unsigned int *str_len, int *flags) +{ + if (!ctx) { return GRN_INVALID_ARGUMENT; } + + *flags = 0; + + if (ctx->stat == GRN_CTX_QUIT) { + grn_bool have_buffer = GRN_FALSE; + + if (ctx->impl && + !ctx->impl->com && + GRN_TEXT_LEN(ctx->impl->output.buf) > 0) { + have_buffer = GRN_TRUE; + } + + *flags |= GRN_CTX_QUIT; + if (!have_buffer) { + *str = NULL; + *str_len = 0; + return 0; + } + } + + GRN_API_ENTER; + if (ctx->impl) { + if (ctx->impl->com) { + grn_com_header header; + if (grn_com_recv(ctx, ctx->impl->com, &header, ctx->impl->output.buf)) { + *str = NULL; + *str_len = 0; + *flags = 0; + } else { + *str = GRN_BULK_HEAD(ctx->impl->output.buf); + *str_len = GRN_BULK_VSIZE(ctx->impl->output.buf); + if (header.flags & GRN_CTX_QUIT) { + ctx->stat = GRN_CTX_QUIT; + *flags |= GRN_CTX_QUIT; + } else { + if (!(header.flags & GRN_CTX_TAIL)) { + *flags |= GRN_CTX_MORE; + } + } + ctx->impl->output.type = header.qtype; + ctx->rc = (int16_t)ntohs(header.status); + ctx->errbuf[0] = '\0'; + ctx->errline = 0; + ctx->errfile = NULL; + ctx->errfunc = NULL; + } + goto exit; + } else { + grn_obj *buf = ctx->impl->output.buf; + unsigned int head = 0, tail = GRN_BULK_VSIZE(buf); + *str = GRN_BULK_HEAD(buf) + head; + *str_len = tail - head; + GRN_BULK_REWIND(ctx->impl->output.buf); + goto exit; + } + } + ERR(GRN_INVALID_ARGUMENT, "invalid ctx assigned"); +exit : + GRN_API_RETURN(0); +} + +void +grn_ctx_stream_out_func(grn_ctx *ctx, int flags, void *stream) +{ + if (ctx && ctx->impl) { + grn_obj *buf = ctx->impl->output.buf; + uint32_t size = GRN_BULK_VSIZE(buf); + if (size) { + if (fwrite(GRN_BULK_HEAD(buf), 1, size, (FILE *)stream)) { + fputc('\n', (FILE *)stream); + fflush((FILE *)stream); + } + GRN_BULK_REWIND(buf); + } + } +} + +void +grn_ctx_recv_handler_set(grn_ctx *ctx, void (*func)(grn_ctx *, int, void *), void *func_arg) +{ + if (ctx && ctx->impl) { + ctx->impl->output.func = func; + ctx->impl->output.data.ptr = func_arg; + } +} + +grn_rc +grn_ctx_info_get(grn_ctx *ctx, grn_ctx_info *info) +{ + if (!ctx || !ctx->impl) { return GRN_INVALID_ARGUMENT; } + if (ctx->impl->com) { + info->fd = ctx->impl->com->fd; + info->com_status = ctx->impl->com_status; + info->outbuf = ctx->impl->output.buf; + info->stat = ctx->stat; + } else { + info->fd = -1; + info->com_status = 0; + info->outbuf = ctx->impl->output.buf; + info->stat = ctx->stat; + } + return GRN_SUCCESS; +} + +#define DB_P(s) ((s) && (s)->header.type == GRN_DB) + +grn_rc +grn_ctx_use(grn_ctx *ctx, grn_obj *db) +{ + GRN_API_ENTER; + if (db && !DB_P(db)) { + ctx->rc = GRN_INVALID_ARGUMENT; + } else { + if (!ctx->rc) { + ctx->impl->db = db; + if (db) { + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + grn_obj_get_info(ctx, db, GRN_INFO_ENCODING, &buf); + ctx->encoding = *(grn_encoding *)GRN_BULK_HEAD(&buf); + grn_obj_close(ctx, &buf); + } + } + } + GRN_API_RETURN(ctx->rc); +} + +/* don't handle error inside logger functions */ + +void +grn_ctx_log(grn_ctx *ctx, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + grn_ctx_logv(ctx, fmt, ap); + va_end(ap); +} + +void +grn_ctx_logv(grn_ctx *ctx, const char *fmt, va_list ap) +{ + char buffer[GRN_CTX_MSGSIZE]; + grn_vsnprintf(buffer, GRN_CTX_MSGSIZE, fmt, ap); + grn_strcpy(ctx->errbuf, GRN_CTX_MSGSIZE, buffer); +} + +void +grn_assert(grn_ctx *ctx, int cond, const char* file, int line, const char* func) +{ + if (!cond) { + GRN_LOG(ctx, GRN_LOG_WARNING, "ASSERT fail on %s %s:%d", func, file, line); + } +} + +const char * +grn_get_version(void) +{ + return GRN_VERSION; +} + +const char * +grn_get_package(void) +{ + return PACKAGE; +} + +const char * +grn_get_package_label(void) +{ + return PACKAGE_LABEL; +} + +#if defined(HAVE_SIGNAL_H) && !defined(WIN32) +static int segv_received = 0; +static void +segv_handler(int signal_number, siginfo_t *info, void *context) +{ + grn_ctx *ctx = &grn_gctx; + + if (segv_received) { + GRN_LOG(ctx, GRN_LOG_CRIT, "SEGV received in SEGV handler."); + exit(EXIT_FAILURE); + } + segv_received = 1; + + GRN_LOG(ctx, GRN_LOG_CRIT, "-- CRASHED!!! --"); +#ifdef HAVE_BACKTRACE +# define N_TRACE_LEVEL 1024 + { + static void *trace[N_TRACE_LEVEL]; + int n = backtrace(trace, N_TRACE_LEVEL); + char **symbols = backtrace_symbols(trace, n); + int i; + + if (symbols) { + for (i = 0; i < n; i++) { + GRN_LOG(ctx, GRN_LOG_CRIT, "%s", symbols[i]); + } + free(symbols); + } + } +#else /* HAVE_BACKTRACE */ + GRN_LOG(ctx, GRN_LOG_CRIT, "backtrace() isn't available."); +#endif /* HAVE_BACKTRACE */ + GRN_LOG(ctx, GRN_LOG_CRIT, "----------------"); + abort(); +} +#endif /* defined(HAVE_SIGNAL_H) && !defined(WIN32) */ + +grn_rc +grn_set_segv_handler(void) +{ + grn_rc rc = GRN_SUCCESS; +#if defined(HAVE_SIGNAL_H) && !defined(WIN32) + grn_ctx *ctx = &grn_gctx; + struct sigaction action; + + sigemptyset(&action.sa_mask); + action.sa_sigaction = segv_handler; + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + + if (sigaction(SIGSEGV, &action, NULL)) { + SERR("failed to set SIGSEGV action"); + rc = ctx->rc; + }; +#endif + return rc; +} + +#if defined(HAVE_SIGNAL_H) && !defined(WIN32) +static struct sigaction old_int_handler; +static void +int_handler(int signal_number, siginfo_t *info, void *context) +{ + grn_gctx.stat = GRN_CTX_QUIT; + sigaction(signal_number, &old_int_handler, NULL); +} + +static struct sigaction old_term_handler; +static void +term_handler(int signal_number, siginfo_t *info, void *context) +{ + grn_gctx.stat = GRN_CTX_QUIT; + sigaction(signal_number, &old_term_handler, NULL); +} +#endif /* defined(HAVE_SIGNAL_H) && !defined(WIN32) */ + +grn_rc +grn_set_int_handler(void) +{ + grn_rc rc = GRN_SUCCESS; +#if defined(HAVE_SIGNAL_H) && !defined(WIN32) + grn_ctx *ctx = &grn_gctx; + struct sigaction action; + + sigemptyset(&action.sa_mask); + action.sa_sigaction = int_handler; + action.sa_flags = SA_SIGINFO; + + if (sigaction(SIGINT, &action, &old_int_handler)) { + SERR("failed to set SIGINT action"); + rc = ctx->rc; + } +#endif + return rc; +} + +grn_rc +grn_set_term_handler(void) +{ + grn_rc rc = GRN_SUCCESS; +#if defined(HAVE_SIGNAL_H) && !defined(WIN32) + grn_ctx *ctx = &grn_gctx; + struct sigaction action; + + sigemptyset(&action.sa_mask); + action.sa_sigaction = term_handler; + action.sa_flags = SA_SIGINFO; + + if (sigaction(SIGTERM, &action, &old_term_handler)) { + SERR("failed to set SIGTERM action"); + rc = ctx->rc; + } +#endif + return rc; +} + +void +grn_ctx_output_flush(grn_ctx *ctx, int flags) +{ + if (flags & GRN_CTX_QUIET) { + return; + } + if (!ctx->impl->output.func) { + return; + } + ctx->impl->output.func(ctx, 0, ctx->impl->output.data.ptr); +} + +void +grn_ctx_output_array_open(grn_ctx *ctx, const char *name, int nelements) +{ + grn_output_array_open(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + name, nelements); +} + +void +grn_ctx_output_array_close(grn_ctx *ctx) +{ + grn_output_array_close(ctx, + ctx->impl->output.buf, + ctx->impl->output.type); +} + +void +grn_ctx_output_map_open(grn_ctx *ctx, const char *name, int nelements) +{ + grn_output_map_open(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + name, nelements); +} + +void +grn_ctx_output_map_close(grn_ctx *ctx) +{ + grn_output_map_close(ctx, + ctx->impl->output.buf, + ctx->impl->output.type); +} + +void +grn_ctx_output_null(grn_ctx *ctx) +{ + grn_output_null(ctx, + ctx->impl->output.buf, + ctx->impl->output.type); +} + +void +grn_ctx_output_int32(grn_ctx *ctx, int value) +{ + grn_output_int32(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + value); +} + +void +grn_ctx_output_int64(grn_ctx *ctx, int64_t value) +{ + grn_output_int64(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + value); +} + +void +grn_ctx_output_uint64(grn_ctx *ctx, uint64_t value) +{ + grn_output_uint64(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + value); +} + +void +grn_ctx_output_float(grn_ctx *ctx, double value) +{ + grn_output_float(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + value); +} + +void +grn_ctx_output_cstr(grn_ctx *ctx, const char *value) +{ + grn_output_cstr(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + value); +} + +void +grn_ctx_output_str(grn_ctx *ctx, const char *value, unsigned int value_len) +{ + grn_output_str(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + value, value_len); +} + +void +grn_ctx_output_bool(grn_ctx *ctx, grn_bool value) +{ + grn_output_bool(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + value); +} + +void +grn_ctx_output_obj(grn_ctx *ctx, grn_obj *value, grn_obj_format *format) +{ + grn_output_obj(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + value, format); +} + +void +grn_ctx_output_result_set_open(grn_ctx *ctx, + grn_obj *result_set, + grn_obj_format *format, + uint32_t n_additional_elements) +{ + grn_output_result_set_open(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + result_set, + format, + n_additional_elements); +} + +void +grn_ctx_output_result_set_close(grn_ctx *ctx, + grn_obj *result_set, + grn_obj_format *format) +{ + grn_output_result_set_close(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + result_set, + format); +} + +void +grn_ctx_output_result_set(grn_ctx *ctx, + grn_obj *result_set, + grn_obj_format *format) +{ + grn_output_result_set(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + result_set, + format); +} + +void +grn_ctx_output_table_columns(grn_ctx *ctx, grn_obj *table, + grn_obj_format *format) +{ + grn_output_table_columns(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + table, + format); +} + +void +grn_ctx_output_table_records(grn_ctx *ctx, grn_obj *table, + grn_obj_format *format) +{ + grn_output_table_records(ctx, + ctx->impl->output.buf, + ctx->impl->output.type, + table, + format); +} diff --git a/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c b/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c new file mode 100644 index 00000000..7f554f3f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ctx_impl_mrb.c @@ -0,0 +1,324 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_ctx_impl.h" + +#include + +#ifdef GRN_WITH_MRUBY +# include "grn_ctx_impl_mrb.h" + +# include "grn_mrb.h" +# include "mrb/mrb_converter.h" +# include "mrb/mrb_error.h" +# include "mrb/mrb_id.h" +# include "mrb/mrb_operator.h" +# include "mrb/mrb_command_version.h" +# include "mrb/mrb_ctx.h" +# include "mrb/mrb_logger.h" +# include "mrb/mrb_query_logger.h" +# include "mrb/mrb_void.h" +# include "mrb/mrb_bulk.h" +# include "mrb/mrb_pointer.h" +# include "mrb/mrb_cache.h" +# include "mrb/mrb_object.h" +# include "mrb/mrb_object_flags.h" +# include "mrb/mrb_database.h" +# include "mrb/mrb_indexable.h" +# include "mrb/mrb_table.h" +# include "mrb/mrb_array.h" +# include "mrb/mrb_hash_table.h" +# include "mrb/mrb_patricia_trie.h" +# include "mrb/mrb_double_array_trie.h" +# include "mrb/mrb_table_group_flags.h" +# include "mrb/mrb_table_group_result.h" +# include "mrb/mrb_table_sort_flags.h" +# include "mrb/mrb_table_sort_key.h" +# include "mrb/mrb_record.h" +# include "mrb/mrb_column.h" +# include "mrb/mrb_fixed_size_column.h" +# include "mrb/mrb_variable_size_column.h" +# include "mrb/mrb_index_column.h" +# include "mrb/mrb_index_cursor.h" +# include "mrb/mrb_type.h" +# include "mrb/mrb_expr.h" +# include "mrb/mrb_accessor.h" +# include "mrb/mrb_procedure.h" +# include "mrb/mrb_command.h" +# include "mrb/mrb_command_input.h" +# include "mrb/mrb_table_cursor.h" +# include "mrb/mrb_table_cursor_flags.h" +# include "mrb/mrb_content_type.h" +# include "mrb/mrb_writer.h" +# include "mrb/mrb_config.h" +# include "mrb/mrb_eval_context.h" +# include "mrb/mrb_thread.h" +# include "mrb/mrb_window_definition.h" + +# include +# include +# include +#endif /* GRN_WITH_MRUBY */ + +static grn_bool grn_ctx_impl_mrb_mruby_enabled = GRN_TRUE; + +void +grn_ctx_impl_mrb_init_from_env(void) +{ + { + char grn_mruby_enabled_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_MRUBY_ENABLED", + grn_mruby_enabled_env, + GRN_ENV_BUFFER_SIZE); + if (grn_mruby_enabled_env[0] && + strcmp(grn_mruby_enabled_env, "no") == 0) { + grn_ctx_impl_mrb_mruby_enabled = GRN_FALSE; + } + } +} + +#ifdef GRN_WITH_MRUBY +static mrb_value +mrb_kernel_load(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *path; + + mrb_get_args(mrb, "z", &path); + + grn_mrb_load(ctx, path); + if (mrb->exc) { + mrb_exc_raise(mrb, mrb_obj_value(mrb->exc)); + } + + grn_mrb_ctx_check(mrb); + + return mrb_true_value(); +} + +static mrb_value +mrb_groonga_init(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = mrb->ud; + + mrb_undef_class_method(mrb, ctx->impl->mrb.module, "init"); + + mrb_define_class(mrb, "LoadError", mrb_class_get(mrb, "ScriptError")); + mrb_define_method(mrb, mrb->kernel_module, + "load", mrb_kernel_load, MRB_ARGS_REQ(1)); + + { + mrb_value load_path; + const char *plugins_dir; + const char *system_ruby_scripts_dir; + + load_path = mrb_ary_new(mrb); + plugins_dir = grn_plugin_get_system_plugins_dir(); + mrb_ary_push(mrb, load_path, + mrb_str_new_cstr(mrb, plugins_dir)); + system_ruby_scripts_dir = grn_mrb_get_system_ruby_scripts_dir(ctx); + mrb_ary_push(mrb, load_path, + mrb_str_new_cstr(mrb, system_ruby_scripts_dir)); + mrb_gv_set(mrb, mrb_intern_cstr(mrb, "$LOAD_PATH"), load_path); + } + + grn_mrb_load(ctx, "require.rb"); + grn_mrb_load(ctx, "initialize/pre.rb"); + + grn_mrb_converter_init(ctx); + grn_mrb_error_init(ctx); + grn_mrb_id_init(ctx); + grn_mrb_operator_init(ctx); + grn_mrb_command_version_init(ctx); + grn_mrb_ctx_init(ctx); + grn_mrb_logger_init(ctx); + grn_mrb_query_logger_init(ctx); + grn_mrb_void_init(ctx); + grn_mrb_bulk_init(ctx); + grn_mrb_pointer_init(ctx); + grn_mrb_cache_init(ctx); + grn_mrb_object_init(ctx); + grn_mrb_object_flags_init(ctx); + grn_mrb_database_init(ctx); + grn_mrb_indexable_init(ctx); + grn_mrb_table_init(ctx); + grn_mrb_array_init(ctx); + grn_mrb_hash_table_init(ctx); + grn_mrb_patricia_trie_init(ctx); + grn_mrb_double_array_trie_init(ctx); + grn_mrb_table_group_flags_init(ctx); + grn_mrb_table_group_result_init(ctx); + grn_mrb_table_sort_flags_init(ctx); + grn_mrb_table_sort_key_init(ctx); + grn_mrb_record_init(ctx); + grn_mrb_column_init(ctx); + grn_mrb_fixed_size_column_init(ctx); + grn_mrb_variable_size_column_init(ctx); + grn_mrb_index_column_init(ctx); + grn_mrb_index_cursor_init(ctx); + grn_mrb_type_init(ctx); + grn_mrb_expr_init(ctx); + grn_mrb_accessor_init(ctx); + grn_mrb_procedure_init(ctx); + grn_mrb_command_init(ctx); + grn_mrb_command_input_init(ctx); + grn_mrb_table_cursor_init(ctx); + grn_mrb_table_cursor_flags_init(ctx); + grn_mrb_content_type_init(ctx); + grn_mrb_writer_init(ctx); + grn_mrb_config_init(ctx); + grn_mrb_eval_context_init(ctx); + grn_mrb_thread_init(ctx); + grn_mrb_window_definition_init(ctx); + + grn_mrb_load(ctx, "initialize/post.rb"); + + return mrb_nil_value(); +} + +static void +grn_ctx_impl_mrb_init_bindings(grn_ctx *ctx) +{ + mrb_state *mrb = ctx->impl->mrb.state; + + mrb->ud = ctx; + ctx->impl->mrb.module = mrb_define_module(mrb, "Groonga"); + mrb_define_const(mrb, + ctx->impl->mrb.module, + "ORDER_BY_ESTIMATED_SIZE", + grn_mrb_is_order_by_estimated_size_enabled() ? + mrb_true_value() : + mrb_false_value()); + mrb_define_class_method(mrb, ctx->impl->mrb.module, + "init", mrb_groonga_init, MRB_ARGS_NONE()); + mrb_funcall(mrb, mrb_obj_value(ctx->impl->mrb.module), "init", 0); +} + +#ifndef USE_MEMORY_DEBUG +static void * +grn_ctx_impl_mrb_allocf(mrb_state *mrb, void *ptr, size_t size, void *ud) +{ + grn_ctx *ctx = ud; + + if (size == 0) { + if (ptr) { + grn_free(ctx, ptr, __FILE__, __LINE__, __FUNCTION__); + } + return NULL; + } else { + if (ptr) { + return grn_realloc(ctx, ptr, size, __FILE__, __LINE__, __FUNCTION__); + } else { + return grn_malloc(ctx, size, __FILE__, __LINE__, __FUNCTION__); + } + } +} +#endif /* USE_MEMORY_DEBUG */ + +static void +grn_ctx_impl_mrb_init_lazy(grn_ctx *ctx) +{ + if (!grn_ctx_impl_mrb_mruby_enabled) { + ctx->impl->mrb.state = NULL; + ctx->impl->mrb.base_directory[0] = '\0'; + ctx->impl->mrb.module = NULL; + ctx->impl->mrb.object_class = NULL; + ctx->impl->mrb.checked_procs = NULL; + ctx->impl->mrb.registered_plugins = NULL; + ctx->impl->mrb.builtin.time_class = NULL; + ctx->impl->mrb.groonga.operator_class = NULL; + } else { + mrb_state *mrb; +#ifdef USE_MEMORY_DEBUG + mrb = mrb_open(); +#else /* USE_MEMORY_DEBUG */ + mrb = mrb_open_allocf(grn_ctx_impl_mrb_allocf, ctx); +#endif /* USE_MEMORY_DEBUG */ + ctx->impl->mrb.state = mrb; + ctx->impl->mrb.base_directory[0] = '\0'; + grn_ctx_impl_mrb_init_bindings(ctx); + if (ctx->impl->mrb.state->exc) { + mrb_value reason; + reason = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0); + ERR(GRN_UNKNOWN_ERROR, + "failed to initialize mruby: %.*s", + (int)RSTRING_LEN(reason), + RSTRING_PTR(reason)); + mrb_close(ctx->impl->mrb.state); + ctx->impl->mrb.state = NULL; + } else { + ctx->impl->mrb.checked_procs = + grn_hash_create(ctx, NULL, sizeof(grn_id), 0, GRN_HASH_TINY); + ctx->impl->mrb.registered_plugins = + grn_hash_create(ctx, NULL, sizeof(grn_id), 0, GRN_HASH_TINY); + GRN_VOID_INIT(&(ctx->impl->mrb.buffer.from)); + GRN_VOID_INIT(&(ctx->impl->mrb.buffer.to)); + ctx->impl->mrb.builtin.time_class = mrb_class_get(mrb, "Time"); + } + } +} + +static void +grn_ctx_impl_mrb_fin_real(grn_ctx *ctx) +{ + if (ctx->impl->mrb.state) { + mrb_close(ctx->impl->mrb.state); + ctx->impl->mrb.state = NULL; + grn_hash_close(ctx, ctx->impl->mrb.checked_procs); + grn_hash_close(ctx, ctx->impl->mrb.registered_plugins); + GRN_OBJ_FIN(ctx, &(ctx->impl->mrb.buffer.from)); + GRN_OBJ_FIN(ctx, &(ctx->impl->mrb.buffer.to)); + } +} +#else /* GRN_WITH_MRUBY */ +static void +grn_ctx_impl_mrb_init_lazy(grn_ctx *ctx) +{ +} + +static void +grn_ctx_impl_mrb_fin_real(grn_ctx *ctx) +{ +} +#endif /* GRN_WITH_MRUBY */ + +void +grn_ctx_impl_mrb_init(grn_ctx *ctx) +{ + ctx->impl->mrb.initialized = GRN_FALSE; +} + +void +grn_ctx_impl_mrb_fin(grn_ctx *ctx) +{ + if (!ctx->impl->mrb.initialized) { + return; + } + + ctx->impl->mrb.initialized = GRN_FALSE; + grn_ctx_impl_mrb_fin_real(ctx); +} + +void +grn_ctx_impl_mrb_ensure_init(grn_ctx *ctx) +{ + if (!ctx->impl->mrb.initialized) { + ctx->impl->mrb.initialized = GRN_TRUE; + grn_ctx_impl_mrb_init_lazy(ctx); + } +} diff --git a/storage/mroonga/vendor/groonga/lib/dat.cpp b/storage/mroonga/vendor/groonga/lib/dat.cpp new file mode 100644 index 00000000..1446be7c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat.cpp @@ -0,0 +1,1338 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include +#include +#include +#include +#include "grn_str.h" +#include "grn_io.h" +#include "grn_dat.h" +#include "grn_util.h" +#include "grn_normalizer.h" + +#include "dat/trie.hpp" +#include "dat/cursor-factory.hpp" + +namespace { + +const uint32_t FILE_ID_LENGTH = 3; + +class CriticalSection { + public: + CriticalSection() : lock_(NULL) {} + explicit CriticalSection(grn_critical_section *lock) : lock_(lock) { + CRITICAL_SECTION_ENTER(*lock_); + } + ~CriticalSection() { + leave(); + } + + void enter(grn_critical_section *lock) { + leave(); + lock_ = lock; + } + void leave() { + if (lock_ != NULL) { + CRITICAL_SECTION_LEAVE(*lock_); + lock_ = NULL; + } + } + + private: + grn_critical_section *lock_; + + // Disallows copy and assignment. + CriticalSection(const CriticalSection &); + CriticalSection &operator=(const CriticalSection &); +}; + +/* + grn_dat_remove_file() removes a file specified by `path' and then returns + true on success, false on failure. Note that grn_dat_remove_file() does not + change `ctx->rc'. + */ +bool +grn_dat_remove_file(grn_ctx *ctx, const char *path) +{ + struct stat stat; + + if (::stat(path, &stat) == -1) { + return false; + } + + if (grn_unlink(path) == -1) { + const char *system_message = grn_strerror(errno); + GRN_LOG(ctx, GRN_LOG_WARNING, + "[dat][remove-file] failed to remove path: %s: <%s>", + system_message, path); + return false; + } + + GRN_LOG(ctx, GRN_LOG_INFO, + "[dat][remove-file] removed: <%s>", path); + return true; +} + +grn_rc +grn_dat_translate_error_code(grn::dat::ErrorCode error_code) { + switch (error_code) { + case grn::dat::PARAM_ERROR: { + return GRN_INVALID_ARGUMENT; + } + case grn::dat::IO_ERROR: { + return GRN_INPUT_OUTPUT_ERROR; + } + case grn::dat::FORMAT_ERROR: { + return GRN_INVALID_FORMAT; + } + case grn::dat::MEMORY_ERROR: { + return GRN_NO_MEMORY_AVAILABLE; + } + case grn::dat::SIZE_ERROR: + case grn::dat::UNEXPECTED_ERROR: { + return GRN_UNKNOWN_ERROR; + } + case grn::dat::STATUS_ERROR: { + return GRN_FILE_CORRUPT; + } + default: { + return GRN_UNKNOWN_ERROR; + } + } +} + +void +grn_dat_init(grn_ctx *, grn_dat *dat) +{ + GRN_DB_OBJ_SET_TYPE(dat, GRN_TABLE_DAT_KEY); + dat->io = NULL; + dat->header = NULL; + dat->file_id = 0; + dat->encoding = GRN_ENC_DEFAULT; + dat->trie = NULL; + dat->old_trie = NULL; + dat->tokenizer = NULL; + dat->normalizer = NULL; + GRN_PTR_INIT(&(dat->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL); + CRITICAL_SECTION_INIT(dat->lock); + dat->is_dirty = GRN_FALSE; +} + +void +grn_dat_fin(grn_ctx *ctx, grn_dat *dat) +{ + CRITICAL_SECTION_FIN(dat->lock); + delete static_cast(dat->old_trie); + delete static_cast(dat->trie); + dat->old_trie = NULL; + dat->trie = NULL; + if (dat->io) { + if (dat->is_dirty) { + uint32_t n_dirty_opens; + GRN_ATOMIC_ADD_EX(&(dat->header->n_dirty_opens), -1, n_dirty_opens); + } + grn_io_close(ctx, dat->io); + dat->io = NULL; + } + GRN_OBJ_FIN(ctx, &(dat->token_filters)); +} + +/* + grn_dat_generate_trie_path() generates the path from `base_path' and + `file_id'. The generated path is stored in `trie_path'. + */ +void +grn_dat_generate_trie_path(const char *base_path, char *trie_path, uint32_t file_id) +{ + if (!base_path || !base_path[0]) { + trie_path[0] = '\0'; + return; + } + const size_t len = std::strlen(base_path); + grn_memcpy(trie_path, base_path, len); + trie_path[len] = '.'; + grn_itoh(file_id % (1U << (4 * FILE_ID_LENGTH)), + trie_path + len + 1, FILE_ID_LENGTH); + trie_path[len + 1 + FILE_ID_LENGTH] = '\0'; +} + +bool +grn_dat_open_trie_if_needed(grn_ctx *ctx, grn_dat *dat) +{ + if (!dat) { + ERR(GRN_INVALID_ARGUMENT, "dat is null"); + return false; + } + + const uint32_t file_id = dat->header->file_id; + if (!file_id || (dat->trie && (file_id <= dat->file_id))) { + /* + There is no need to open file when no trie file is available or the + current trie file is the latest one. + */ + return true; + } + + CriticalSection critical_section(&dat->lock); + + if (dat->trie && (file_id <= dat->file_id)) { + /* + There is no need to open file if the latest file has been opened by + another thread. + */ + return true; + } + + char trie_path[PATH_MAX]; + grn_dat_generate_trie_path(grn_io_path(dat->io), trie_path, file_id); + grn::dat::Trie * const trie = static_cast(dat->trie); + grn::dat::Trie * const old_trie = static_cast(dat->old_trie); + grn::dat::Trie * const new_trie = new (std::nothrow) grn::dat::Trie; + if (!new_trie) { + MERR("new grn::dat::Trie failed"); + return false; + } + + if (trie_path[0] == '\0') { + try { + new_trie->create(trie_path); + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::create failed: %s", + ex.what()); + delete new_trie; + return false; + } + } else { + try { + new_trie->open(trie_path); + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::open failed: %s", + ex.what()); + delete new_trie; + return false; + } + } + + dat->old_trie = trie; + dat->trie = new_trie; + dat->file_id = file_id; + + critical_section.leave(); + + delete old_trie; + if (file_id >= 3) { + grn_dat_generate_trie_path(grn_io_path(dat->io), trie_path, file_id - 2); + grn_dat_remove_file(ctx, trie_path); + } + return true; +} + +bool grn_dat_rebuild_trie(grn_ctx *ctx, grn_dat *dat) { + const grn::dat::Trie * const trie = static_cast(dat->trie); + grn::dat::Trie * const new_trie = new (std::nothrow) grn::dat::Trie; + if (!new_trie) { + MERR("new grn::dat::Trie failed"); + return false; + } + + const uint32_t file_id = dat->header->file_id; + char trie_path[PATH_MAX]; + grn_dat_generate_trie_path(grn_io_path(dat->io), trie_path, file_id + 1); + + for (uint64_t file_size = trie->file_size() * 2;; file_size *= 2) { + try { + new_trie->create(*trie, trie_path, file_size); + } catch (const grn::dat::SizeError &) { + continue; + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::open failed: %s", + ex.what()); + delete new_trie; + return false; + } + break; + } + + grn::dat::Trie * const old_trie = static_cast(dat->old_trie); + dat->old_trie = dat->trie; + dat->trie = new_trie; + dat->header->file_id = dat->file_id = file_id + 1; + + delete old_trie; + if (file_id >= 2) { + char trie_path[PATH_MAX]; + grn_dat_generate_trie_path(grn_io_path(dat->io), trie_path, file_id - 1); + grn_dat_remove_file(ctx, trie_path); + } + return true; +} + +void grn_dat_cursor_init(grn_ctx *, grn_dat_cursor *cursor) { + GRN_DB_OBJ_SET_TYPE(cursor, GRN_CURSOR_TABLE_DAT_KEY); + cursor->dat = NULL; + cursor->cursor = NULL; + cursor->key = &grn::dat::Key::invalid_key(); + cursor->curr_rec = GRN_ID_NIL; +} + +void grn_dat_cursor_fin(grn_ctx *, grn_dat_cursor *cursor) { + delete static_cast(cursor->cursor); + cursor->dat = NULL; + cursor->cursor = NULL; + cursor->key = &grn::dat::Key::invalid_key(); + cursor->curr_rec = GRN_ID_NIL; +} + +} // namespace + +extern "C" { + +grn_dat * +grn_dat_create(grn_ctx *ctx, const char *path, uint32_t, + uint32_t, uint32_t flags) +{ + if (path) { + if (path[0] == '\0') { + path = NULL; + } else if (std::strlen(path) >= (PATH_MAX - (FILE_ID_LENGTH + 1))) { + ERR(GRN_FILENAME_TOO_LONG, "too long path"); + return NULL; + } + } + + grn_dat * const dat = static_cast(GRN_CALLOC(sizeof(grn_dat))); + if (!dat) { + return NULL; + } + grn_dat_init(ctx, dat); + + dat->io = grn_io_create(ctx, path, sizeof(struct grn_dat_header), + 4096, 0, grn_io_auto, GRN_IO_EXPIRE_SEGMENT); + if (!dat->io) { + GRN_FREE(dat); + return NULL; + } + grn_io_set_type(dat->io, GRN_TABLE_DAT_KEY); + + dat->header = static_cast(grn_io_header(dat->io)); + if (!dat->header) { + grn_io_close(ctx, dat->io); + grn_dat_remove_file(ctx, path); + GRN_FREE(dat); + return NULL; + } + const grn_encoding encoding = (ctx->encoding != GRN_ENC_DEFAULT) ? + ctx->encoding : grn_gctx.encoding; + dat->header->flags = flags; + dat->header->encoding = encoding; + dat->header->tokenizer = GRN_ID_NIL; + dat->header->file_id = 0; + if (dat->header->flags & GRN_OBJ_KEY_NORMALIZE) { + dat->header->flags &= ~GRN_OBJ_KEY_NORMALIZE; + dat->normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + dat->header->normalizer = grn_obj_id(ctx, dat->normalizer); + } else { + dat->normalizer = NULL; + dat->header->normalizer = GRN_ID_NIL; + } + dat->encoding = encoding; + dat->tokenizer = NULL; + GRN_PTR_INIT(&(dat->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL); + + dat->obj.header.flags = dat->header->flags; + + return dat; +} + +grn_dat * +grn_dat_open(grn_ctx *ctx, const char *path) +{ + if (path && (std::strlen(path) >= (PATH_MAX - (FILE_ID_LENGTH + 1)))) { + ERR(GRN_FILENAME_TOO_LONG, "too long path"); + return NULL; + } + + grn_dat * const dat = static_cast(GRN_MALLOC(sizeof(grn_dat))); + if (!dat) { + return NULL; + } + + grn_dat_init(ctx, dat); + dat->io = grn_io_open(ctx, path, grn_io_auto); + if (!dat->io) { + GRN_FREE(dat); + return NULL; + } + + dat->header = (struct grn_dat_header *)grn_io_header(dat->io); + if (!dat->header) { + grn_io_close(ctx, dat->io); + GRN_FREE(dat); + return NULL; + } + dat->file_id = dat->header->file_id; + dat->encoding = dat->header->encoding; + dat->tokenizer = grn_ctx_at(ctx, dat->header->tokenizer); + if (dat->header->flags & GRN_OBJ_KEY_NORMALIZE) { + dat->header->flags &= ~GRN_OBJ_KEY_NORMALIZE; + dat->normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + dat->header->normalizer = grn_obj_id(ctx, dat->normalizer); + } else { + dat->normalizer = grn_ctx_at(ctx, dat->header->normalizer); + } + GRN_PTR_INIT(&(dat->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL); + dat->obj.header.flags = dat->header->flags; + return dat; +} + +grn_rc +grn_dat_close(grn_ctx *ctx, grn_dat *dat) +{ + if (dat) { + grn_dat_fin(ctx, dat); + GRN_FREE(dat); + } + return GRN_SUCCESS; +} + +grn_rc +grn_dat_remove(grn_ctx *ctx, const char *path) +{ + if (!path) { + ERR(GRN_INVALID_ARGUMENT, "path is null"); + return GRN_INVALID_ARGUMENT; + } + + grn_dat * const dat = grn_dat_open(ctx, path); + if (!dat) { + return ctx->rc; + } + const uint32_t file_id = dat->header->file_id; + grn_dat_close(ctx, dat); + + /* + grn_dat_remove() tries to remove (file_id + 1)th trie file because + grn::dat::Trie::create() might leave an incomplete file on failure. + */ + char trie_path[PATH_MAX]; + grn_dat_generate_trie_path(path, trie_path, file_id + 1); + grn_dat_remove_file(ctx, trie_path); + for (uint32_t i = file_id; i > 0; --i) { + grn_dat_generate_trie_path(path, trie_path, i); + if (!grn_dat_remove_file(ctx, trie_path)) { + break; + } + } + + /* + grn_io_remove() reports an error when it fails to remove `path'. + */ + return grn_io_remove(ctx, path); +} + +grn_id +grn_dat_get(grn_ctx *ctx, grn_dat *dat, const void *key, + unsigned int key_size, void **) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return GRN_ID_NIL; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + return GRN_ID_NIL; + } + grn::dat::UInt32 key_pos; + try { + if (trie->search(key, key_size, &key_pos)) { + return trie->get_key(key_pos).id(); + } + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::search failed: %s", + ex.what()); + } + return GRN_ID_NIL; +} + +grn_id +grn_dat_add(grn_ctx *ctx, grn_dat *dat, const void *key, + unsigned int key_size, void **, int *added) +{ + if (!key_size) { + return GRN_ID_NIL; + } else if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return GRN_ID_NIL; + } + + if (!dat->trie) { + char trie_path[PATH_MAX]; + grn_dat_generate_trie_path(grn_io_path(dat->io), trie_path, 1); + grn::dat::Trie * const new_trie = new (std::nothrow) grn::dat::Trie; + if (!new_trie) { + MERR("new grn::dat::Trie failed"); + return GRN_ID_NIL; + } + try { + new_trie->create(trie_path); + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::create failed: %s", + ex.what()); + delete new_trie; + return GRN_ID_NIL; + } + dat->trie = new_trie; + dat->file_id = dat->header->file_id = 1; + } + + grn::dat::Trie * const trie = static_cast(dat->trie); + try { + grn::dat::UInt32 key_pos; + const bool res = trie->insert(key, key_size, &key_pos); + if (added) { + *added = res ? 1 : 0; + } + return trie->get_key(key_pos).id(); + } catch (const grn::dat::SizeError &) { + if (!grn_dat_rebuild_trie(ctx, dat)) { + return GRN_ID_NIL; + } + grn::dat::Trie * const new_trie = static_cast(dat->trie); + grn::dat::UInt32 key_pos; + const bool res = new_trie->insert(key, key_size, &key_pos); + if (added) { + *added = res ? 1 : 0; + } + return new_trie->get_key(key_pos).id(); + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::insert failed: %s", + ex.what()); + return GRN_ID_NIL; + } +} + +int +grn_dat_get_key(grn_ctx *ctx, grn_dat *dat, grn_id id, void *keybuf, int bufsize) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return 0; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + return 0; + } + const grn::dat::Key &key = trie->ith_key(id); + if (!key.is_valid()) { + return 0; + } + if (keybuf && (bufsize >= (int)key.length())) { + grn_memcpy(keybuf, key.ptr(), key.length()); + } + return (int)key.length(); +} + +int +grn_dat_get_key2(grn_ctx *ctx, grn_dat *dat, grn_id id, grn_obj *bulk) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return 0; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + return 0; + } + const grn::dat::Key &key = trie->ith_key(id); + if (!key.is_valid()) { + return 0; + } + if (bulk->header.impl_flags & GRN_OBJ_REFER) { + bulk->u.b.head = static_cast(const_cast(key.ptr())); + bulk->u.b.curr = bulk->u.b.head + key.length(); + } else { + grn_bulk_write(ctx, bulk, static_cast(key.ptr()), key.length()); + } + return (int)key.length(); +} + +grn_rc +grn_dat_delete_by_id(grn_ctx *ctx, grn_dat *dat, grn_id id, + grn_table_delete_optarg *optarg) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return ctx->rc; + } else if (!dat->trie || (id == GRN_ID_NIL)) { + return GRN_INVALID_ARGUMENT; + } + + if (optarg && optarg->func) { + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie->ith_entry(id).is_valid()) { + return GRN_INVALID_ARGUMENT; + } else if (!optarg->func(ctx, reinterpret_cast(dat), id, optarg->func_arg)) { + return GRN_SUCCESS; + } + } + + try { + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie->remove(id)) { + return GRN_INVALID_ARGUMENT; + } + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::remove failed: %s", + ex.what()); + return ctx->rc; + } + return GRN_SUCCESS; +} + +grn_rc +grn_dat_delete(grn_ctx *ctx, grn_dat *dat, const void *key, unsigned int key_size, + grn_table_delete_optarg *optarg) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return ctx->rc; + } else if (!dat->trie || !key || !key_size) { + return GRN_INVALID_ARGUMENT; + } + + if (optarg && optarg->func) { + try { + const grn::dat::Trie * const trie = static_cast(dat->trie); + grn::dat::UInt32 key_pos; + if (!trie->search(key, key_size, &key_pos)) { + return GRN_INVALID_ARGUMENT; + } else if (!optarg->func(ctx, reinterpret_cast(dat), + trie->get_key(key_pos).id(), optarg->func_arg)) { + return GRN_SUCCESS; + } + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::search failed: %s", + ex.what()); + return ctx->rc; + } + } + + try { + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie->remove(key, key_size)) { + return GRN_INVALID_ARGUMENT; + } + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::remove failed: %s", + ex.what()); + return ctx->rc; + } + return GRN_SUCCESS; +} + +grn_rc +grn_dat_update_by_id(grn_ctx *ctx, grn_dat *dat, grn_id src_key_id, + const void *dest_key, unsigned int dest_key_size) +{ + if (!dest_key_size) { + return GRN_INVALID_ARGUMENT; + } else if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return ctx->rc; + } else if (!dat->trie) { + return GRN_INVALID_ARGUMENT; + } + try { + try { + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie->update(src_key_id, dest_key, dest_key_size)) { + return GRN_INVALID_ARGUMENT; + } + } catch (const grn::dat::SizeError &) { + if (!grn_dat_rebuild_trie(ctx, dat)) { + return ctx->rc; + } + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie->update(src_key_id, dest_key, dest_key_size)) { + return GRN_INVALID_ARGUMENT; + } + } + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::update failed: %s", + ex.what()); + return ctx->rc; + } + return GRN_SUCCESS; +} + +grn_rc +grn_dat_update(grn_ctx *ctx, grn_dat *dat, + const void *src_key, unsigned int src_key_size, + const void *dest_key, unsigned int dest_key_size) +{ + if (!dest_key_size) { + return GRN_INVALID_ARGUMENT; + } else if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return ctx->rc; + } else if (!dat->trie) { + return GRN_INVALID_ARGUMENT; + } + try { + try { + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie->update(src_key, src_key_size, dest_key, dest_key_size)) { + return GRN_INVALID_ARGUMENT; + } + } catch (const grn::dat::SizeError &) { + if (!grn_dat_rebuild_trie(ctx, dat)) { + return ctx->rc; + } + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie->update(src_key, src_key_size, dest_key, dest_key_size)) { + return GRN_INVALID_ARGUMENT; + } + } + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::update failed: %s", + ex.what()); + return ctx->rc; + } + return GRN_SUCCESS; +} + +int +grn_dat_scan(grn_ctx *ctx, grn_dat *dat, const char *str, + unsigned int str_size, grn_dat_scan_hit *scan_hits, + unsigned int max_num_scan_hits, const char **str_rest) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat) || !str || + !(dat->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) || !scan_hits) { + if (str_rest) { + *str_rest = str; + } + return -1; + } + + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + if (str_rest) { + *str_rest = str + str_size; + } + return 0; + } + + if (!max_num_scan_hits || !str_size) { + if (str_rest) { + *str_rest = str; + } + return 0; + } + + unsigned int num_scan_hits = 0; + try { + if (dat->normalizer) { + int flags = GRN_STRING_WITH_CHECKS; + grn_obj * const normalized_string = grn_string_open(ctx, str, str_size, + dat->normalizer, + flags); + if (!normalized_string) { + if (str_rest) { + *str_rest = str; + } + return -1; + } + grn_string_get_normalized(ctx, normalized_string, &str, &str_size, NULL); + const short *checks = grn_string_get_checks(ctx, normalized_string); + unsigned int offset = 0; + while (str_size) { + if (*checks) { + grn::dat::UInt32 key_pos; + if (trie->lcp_search(str, str_size, &key_pos)) { + const grn::dat::Key &key = trie->get_key(key_pos); + const grn::dat::UInt32 key_length = key.length(); + if ((key_length == str_size) || (checks[key_length])) { + unsigned int length = 0; + for (grn::dat::UInt32 i = 0; i < key_length; ++i) { + if (checks[i] > 0) { + length += checks[i]; + } + } + scan_hits[num_scan_hits].id = key.id(); + scan_hits[num_scan_hits].offset = offset; + scan_hits[num_scan_hits].length = length; + offset += length; + str += key_length; + str_size -= key_length; + checks += key_length; + if (++num_scan_hits >= max_num_scan_hits) { + break; + } + continue; + } + } + if (*checks > 0) { + offset += *checks; + } + } + ++str; + --str_size; + ++checks; + } + if (str_rest) { + grn_string_get_original(ctx, normalized_string, str_rest, NULL); + *str_rest += offset; + } + grn_obj_close(ctx, normalized_string); + } else { + const char * const begin = str; + while (str_size) { + grn::dat::UInt32 key_pos; + if (trie->lcp_search(str, str_size, &key_pos)) { + const grn::dat::Key &key = trie->get_key(key_pos); + scan_hits[num_scan_hits].id = key.id(); + scan_hits[num_scan_hits].offset = str - begin; + scan_hits[num_scan_hits].length = key.length(); + str += key.length(); + str_size -= key.length(); + if (++num_scan_hits >= max_num_scan_hits) { + break; + } + } else { + const int char_length = grn_charlen(ctx, str, str + str_size); + if (char_length) { + str += char_length; + str_size -= char_length; + } else { + ++str; + --str_size; + } + } + } + if (str_rest) { + *str_rest = str; + } + } + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::lcp_search failed: %s", + ex.what()); + if (str_rest) { + *str_rest = str; + } + return -1; + } + return static_cast(num_scan_hits); +} + +grn_id +grn_dat_lcp_search(grn_ctx *ctx, grn_dat *dat, + const void *key, unsigned int key_size) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat) || !key || + !(dat->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE)) { + return GRN_ID_NIL; + } + + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + return GRN_ID_NIL; + } + + try { + grn::dat::UInt32 key_pos; + if (!trie->lcp_search(key, key_size, &key_pos)) { + return GRN_ID_NIL; + } + return trie->get_key(key_pos).id(); + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::PrefixCursor::open failed: %s", + ex.what()); + return GRN_ID_NIL; + } +} + +unsigned int +grn_dat_size(grn_ctx *ctx, grn_dat *dat) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return 0; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (trie) { + return trie->num_keys(); + } + return 0; +} + +grn_dat_cursor * +grn_dat_cursor_open(grn_ctx *ctx, grn_dat *dat, + const void *min, unsigned int min_size, + const void *max, unsigned int max_size, + int offset, int limit, int flags) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return NULL; + } + + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + grn_dat_cursor * const dc = + static_cast(GRN_MALLOC(sizeof(grn_dat_cursor))); + if (dc) { + grn_dat_cursor_init(ctx, dc); + } + return dc; + } + + grn_dat_cursor * const dc = + static_cast(GRN_MALLOC(sizeof(grn_dat_cursor))); + if (!dc) { + return NULL; + } + grn_dat_cursor_init(ctx, dc); + + try { + if ((flags & GRN_CURSOR_BY_ID) != 0) { + dc->cursor = grn::dat::CursorFactory::open(*trie, + min, min_size, max, max_size, offset, limit, + grn::dat::ID_RANGE_CURSOR | + ((flags & GRN_CURSOR_DESCENDING) ? grn::dat::DESCENDING_CURSOR : 0) | + ((flags & GRN_CURSOR_GT) ? grn::dat::EXCEPT_LOWER_BOUND : 0) | + ((flags & GRN_CURSOR_LT) ? grn::dat::EXCEPT_UPPER_BOUND : 0)); + } else if ((flags & GRN_CURSOR_PREFIX) != 0) { + if (max && max_size) { + if ((dat->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) != 0) { + dc->cursor = grn::dat::CursorFactory::open(*trie, + NULL, min_size, max, max_size, offset, limit, + grn::dat::PREFIX_CURSOR | grn::dat::DESCENDING_CURSOR); + } else { + // TODO: near + } + } else if (min && min_size) { + if ((flags & GRN_CURSOR_RK) != 0) { + // TODO: rk search + } else { + dc->cursor = grn::dat::CursorFactory::open(*trie, + min, min_size, NULL, 0, offset, limit, + grn::dat::PREDICTIVE_CURSOR | + ((flags & GRN_CURSOR_DESCENDING) ? grn::dat::DESCENDING_CURSOR : 0) | + ((flags & GRN_CURSOR_GT) ? grn::dat::EXCEPT_EXACT_MATCH : 0)); + } + } + } else { + dc->cursor = grn::dat::CursorFactory::open(*trie, + min, min_size, max, max_size, offset, limit, + grn::dat::KEY_RANGE_CURSOR | + ((flags & GRN_CURSOR_DESCENDING) ? grn::dat::DESCENDING_CURSOR : 0) | + ((flags & GRN_CURSOR_GT) ? grn::dat::EXCEPT_LOWER_BOUND : 0) | + ((flags & GRN_CURSOR_LT) ? grn::dat::EXCEPT_UPPER_BOUND : 0)); + } + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::CursorFactory::open failed: %s", + ex.what()); + GRN_FREE(dc); + return NULL; + } + if (!dc->cursor) { + ERR(GRN_INVALID_ARGUMENT, "unsupported query"); + GRN_FREE(dc); + return NULL; + } + dc->dat = dat; + return dc; +} + +grn_id +grn_dat_cursor_next(grn_ctx *ctx, grn_dat_cursor *c) +{ + if (!c || !c->cursor) { + return GRN_ID_NIL; + } + try { + grn::dat::Cursor * const cursor = static_cast(c->cursor); + const grn::dat::Key &key = cursor->next(); + c->key = &key; + c->curr_rec = key.is_valid() ? key.id() : GRN_ID_NIL; + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Cursor::next failed: %s", + ex.what()); + return GRN_ID_NIL; + } + return c->curr_rec; +} + +void +grn_dat_cursor_close(grn_ctx *ctx, grn_dat_cursor *c) +{ + if (c) { + grn_dat_cursor_fin(ctx, c); + GRN_FREE(c); + } +} + +int +grn_dat_cursor_get_key(grn_ctx *ctx, grn_dat_cursor *c, const void **key) +{ + if (c) { + const grn::dat::Key &key_ref = *static_cast(c->key); + if (key_ref.is_valid()) { + *key = key_ref.ptr(); + return (int)key_ref.length(); + } + } + return 0; +} + +grn_rc +grn_dat_cursor_delete(grn_ctx *ctx, grn_dat_cursor *c, + grn_table_delete_optarg *optarg) +{ + if (!c || !c->cursor) { + return GRN_INVALID_ARGUMENT; + } else if (!grn_dat_open_trie_if_needed(ctx, c->dat)) { + return ctx->rc; + } + grn::dat::Trie * const trie = static_cast(c->dat->trie); + if (!trie) { + return GRN_INVALID_ARGUMENT; + } + try { + if (trie->remove(c->curr_rec)) { + return GRN_SUCCESS; + } + } catch (const grn::dat::Exception &ex) { + ERR(grn_dat_translate_error_code(ex.code()), + "grn::dat::Trie::remove failed: %s", + ex.what()); + return GRN_INVALID_ARGUMENT; + } + return GRN_INVALID_ARGUMENT; +} + +grn_id +grn_dat_curr_id(grn_ctx *ctx, grn_dat *dat) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return GRN_ID_NIL; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (trie) { + return trie->max_key_id(); + } + return GRN_ID_NIL; +} + +grn_rc +grn_dat_truncate(grn_ctx *ctx, grn_dat *dat) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return ctx->rc; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie || !trie->max_key_id()) { + return GRN_SUCCESS; + } + + char trie_path[PATH_MAX]; + grn_dat_generate_trie_path(grn_io_path(dat->io), trie_path, dat->header->file_id + 1); + try { + grn::dat::Trie().create(trie_path); + } catch (const grn::dat::Exception &ex) { + const grn_rc error_code = grn_dat_translate_error_code(ex.code()); + ERR(error_code, "grn::dat::Trie::create failed: %s", ex.what()); + return error_code; + } + ++dat->header->file_id; + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return ctx->rc; + } + return GRN_SUCCESS; +} + +const char * +_grn_dat_key(grn_ctx *ctx, grn_dat *dat, grn_id id, uint32_t *key_size) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + *key_size = 0; + return NULL; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + *key_size = 0; + return NULL; + } + const grn::dat::Key &key = trie->ith_key(id); + if (!key.is_valid()) { + *key_size = 0; + return NULL; + } + *key_size = key.length(); + return static_cast(key.ptr()); +} + +grn_id +grn_dat_next(grn_ctx *ctx, grn_dat *dat, grn_id id) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return GRN_ID_NIL; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + return GRN_ID_NIL; + } + while (id < trie->max_key_id()) { + if (trie->ith_key(++id).is_valid()) { + return id; + } + } + return GRN_ID_NIL; +} + +grn_id +grn_dat_at(grn_ctx *ctx, grn_dat *dat, grn_id id) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return GRN_ID_NIL; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + return GRN_ID_NIL; + } + const grn::dat::Key &key = trie->ith_key(id); + if (!key.is_valid()) { + return GRN_ID_NIL; + } + return id; +} + +grn_rc +grn_dat_clear_status_flags(grn_ctx *ctx, grn_dat *dat) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return ctx->rc; + } + grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + return GRN_INVALID_ARGUMENT; + } + trie->clear_status_flags(); + return GRN_SUCCESS; +} + +grn_rc +grn_dat_repair(grn_ctx *ctx, grn_dat *dat) +{ + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return ctx->rc; + } + const grn::dat::Trie * const trie = static_cast(dat->trie); + if (!trie) { + return GRN_INVALID_ARGUMENT; + } + + char trie_path[PATH_MAX]; + grn_dat_generate_trie_path(grn_io_path(dat->io), trie_path, dat->header->file_id + 1); + try { + grn::dat::Trie().repair(*trie, trie_path); + } catch (const grn::dat::Exception &ex) { + const grn_rc error_code = grn_dat_translate_error_code(ex.code()); + ERR(error_code, "grn::dat::Trie::create failed: %s", ex.what()); + return error_code; + } + ++dat->header->file_id; + if (!grn_dat_open_trie_if_needed(ctx, dat)) { + return ctx->rc; + } + return GRN_SUCCESS; +} + +grn_rc +grn_dat_flush(grn_ctx *ctx, grn_dat *dat) +{ + if (!dat->io) { + return GRN_SUCCESS; + } + + grn_rc rc = grn_io_flush(ctx, dat->io); + if (rc != GRN_SUCCESS) { + return rc; + } + + if (dat->trie) { + grn::dat::Trie * const trie = static_cast(dat->trie); + try { + trie->flush(); + } catch (const grn::dat::Exception &ex) { + const grn_rc error_code = grn_dat_translate_error_code(ex.code()); + if (error_code == GRN_INPUT_OUTPUT_ERROR) { + SERR("grn::dat::Trie::flush failed: %s", ex.what()); + } else { + ERR(error_code, "grn::dat::Trie::flush failed: %s", ex.what()); + } + return error_code; + } + } + + return GRN_SUCCESS; +} + +grn_rc +grn_dat_dirty(grn_ctx *ctx, grn_dat *dat) +{ + if (!dat->io) { + return GRN_SUCCESS; + } + + grn_rc rc = GRN_SUCCESS; + + { + CriticalSection critical_section(&dat->lock); + if (!dat->is_dirty) { + uint32_t n_dirty_opens; + dat->is_dirty = GRN_TRUE; + GRN_ATOMIC_ADD_EX(&(dat->header->n_dirty_opens), 1, n_dirty_opens); + rc = grn_io_flush(ctx, dat->io); + } + } + + return rc; +} + +grn_bool +grn_dat_is_dirty(grn_ctx *ctx, grn_dat *dat) +{ + if (!dat->header) { + return GRN_FALSE; + } + + return dat->header->n_dirty_opens > 0; +} + +grn_rc +grn_dat_clean(grn_ctx *ctx, grn_dat *dat) +{ + grn_rc rc = GRN_SUCCESS; + + if (!dat->io) { + return rc; + } + + { + CriticalSection critical_section(&dat->lock); + if (dat->is_dirty) { + uint32_t n_dirty_opens; + dat->is_dirty = GRN_FALSE; + GRN_ATOMIC_ADD_EX(&(dat->header->n_dirty_opens), -1, n_dirty_opens); + rc = grn_io_flush(ctx, dat->io); + } + } + + return rc; +} + +grn_rc +grn_dat_clear_dirty(grn_ctx *ctx, grn_dat *dat) +{ + grn_rc rc = GRN_SUCCESS; + + if (!dat->io) { + return rc; + } + + { + CriticalSection critical_section(&dat->lock); + dat->is_dirty = GRN_FALSE; + dat->header->n_dirty_opens = 0; + rc = grn_io_flush(ctx, dat->io); + } + + return rc; +} + +grn_bool +grn_dat_is_corrupt(grn_ctx *ctx, grn_dat *dat) +{ + if (!dat->io) { + return GRN_FALSE; + } + + { + CriticalSection critical_section(&dat->lock); + + if (grn_io_is_corrupt(ctx, dat->io)) { + return GRN_TRUE; + } + + if (dat->header->file_id == 0) { + return GRN_FALSE; + } + + char trie_path[PATH_MAX]; + grn_dat_generate_trie_path(grn_io_path(dat->io), + trie_path, + dat->header->file_id); + struct stat stat; + if (::stat(trie_path, &stat) != 0) { + SERR("[dat][corrupt] used path doesn't exist: <%s>", + trie_path); + return GRN_TRUE; + } + } + + return GRN_FALSE; +} + +size_t +grn_dat_get_disk_usage(grn_ctx *ctx, grn_dat *dat) +{ + if (!dat->io) { + return 0; + } + + { + CriticalSection critical_section(&dat->lock); + size_t usage; + + usage = grn_io_get_disk_usage(ctx, dat->io); + + if (dat->header->file_id == 0) { + return usage; + } + + char trie_path[PATH_MAX]; + grn_dat_generate_trie_path(grn_io_path(dat->io), + trie_path, + dat->header->file_id); + struct stat stat; + if (::stat(trie_path, &stat) == 0) { + usage += stat.st_size; + } + + return usage; + } +} + +} // extern "C" diff --git a/storage/mroonga/vendor/groonga/lib/dat/Makefile.am b/storage/mroonga/vendor/groonga/lib/dat/Makefile.am new file mode 100644 index 00000000..0a58629c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/Makefile.am @@ -0,0 +1,11 @@ +DEFS += -D_REENTRANT $(GRN_DEFS) -DGRN_DAT_EXPORT + +DEFAULT_INCLUDES = \ + -I$(top_builddir) \ + -I$(top_srcdir)/include + +noinst_LTLIBRARIES = libgrndat.la + +include sources.am + +CLEANFILES = *.gcno *.gcda diff --git a/storage/mroonga/vendor/groonga/lib/dat/array.hpp b/storage/mroonga/vendor/groonga/lib/dat/array.hpp new file mode 100644 index 00000000..de60e3bd --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/array.hpp @@ -0,0 +1,98 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "dat.hpp" + +namespace grn { +namespace dat { + +// This class is used to detect an out-of-range access in debug mode. +template +class GRN_DAT_API Array { + public: + Array() : ptr_(NULL), size_(0) {} + Array(void *ptr, UInt32 size) : ptr_(static_cast(ptr)), size_(size) { + GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (size != 0)); + } + template + explicit Array(T (&array)[U]) : ptr_(array), size_(U) {} + ~Array() {} + + const T &operator[](UInt32 i) const { + GRN_DAT_DEBUG_THROW_IF(i >= size_); + return ptr_[i]; + } + T &operator[](UInt32 i) { + GRN_DAT_DEBUG_THROW_IF(i >= size_); + return ptr_[i]; + } + + const T *begin() const { + return ptr(); + } + T *begin() { + return ptr(); + } + + const T *end() const { + return ptr() + size(); + } + T *end() { + return ptr() + size(); + } + + void assign(void *ptr, UInt32 size) { + GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (size != 0)); + ptr_ = static_cast(ptr); + size_ = size; + } + template + void assign(T (&array)[U]) { + assign(array, U); + } + + void swap(Array *rhs) { + T * const temp_ptr = ptr_; + ptr_ = rhs->ptr_; + rhs->ptr_ = temp_ptr; + + const UInt32 temp_size = size_; + size_ = rhs->size_; + rhs->size_ = temp_size; + } + + T *ptr() const { + return ptr_; + } + UInt32 size() const { + return size_; + } + + private: + T *ptr_; + UInt32 size_; + + // Disallows copy and assignment. + Array(const Array &); + Array &operator=(const Array &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/base.hpp b/storage/mroonga/vendor/groonga/lib/dat/base.hpp new file mode 100644 index 00000000..51ec6f2f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/base.hpp @@ -0,0 +1,67 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "dat.hpp" + +namespace grn { +namespace dat { + +// The most significant bit represents whether or not the node is a linker. +// BASE of a linker represents the position of its associated key and BASE of +// a non-linker represents the offset to its child nodes. +class GRN_DAT_API Base { + public: + Base() : value_(0) {} + + bool operator==(const Base &rhs) const { + return value_ == rhs.value_; + } + + bool is_linker() const { + return (value_ & IS_LINKER_FLAG) == IS_LINKER_FLAG; + } + UInt32 offset() const { + GRN_DAT_DEBUG_THROW_IF(is_linker()); + return value_; + } + UInt32 key_pos() const { + GRN_DAT_DEBUG_THROW_IF(!is_linker()); + return value_ & ~IS_LINKER_FLAG; + } + + void set_offset(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF((x & IS_LINKER_FLAG) != 0); + GRN_DAT_DEBUG_THROW_IF(x > MAX_OFFSET); + value_ = x; + } + void set_key_pos(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF((x & IS_LINKER_FLAG) != 0); + GRN_DAT_DEBUG_THROW_IF(x > MAX_OFFSET); + value_ = IS_LINKER_FLAG | x; + } + + private: + UInt32 value_; + + static const UInt32 IS_LINKER_FLAG = 0x80000000U; +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/block.hpp b/storage/mroonga/vendor/groonga/lib/dat/block.hpp new file mode 100644 index 00000000..34e3620a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/block.hpp @@ -0,0 +1,94 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "dat.hpp" + +namespace grn { +namespace dat { + +class GRN_DAT_API Block { + public: + Block() : next_(0), prev_(0), first_phantom_(0), num_phantoms_(0) {} + + // Blocks in the same level are stored in a doubly-linked list which is + // represented by the following next() and prev(). + UInt32 next() const { + return next_ / BLOCK_SIZE; + } + UInt32 prev() const { + return prev_ / BLOCK_SIZE; + } + + // A level indicates how easyily find_offset() can find a good offset in that + // block. It is easier in lower level blocks. + UInt32 level() const { + return next_ & BLOCK_MASK; + } + // A block level rises when find_offset() fails to find a good offset + // MAX_FAILURE_COUNT times in that block. + UInt32 failure_count() const { + return prev_ & BLOCK_MASK; + } + + UInt32 first_phantom() const { + return first_phantom_; + } + UInt32 num_phantoms() const { + return num_phantoms_; + } + + void set_next(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_BLOCK_ID); + next_ = (next_ & BLOCK_MASK) | (x * BLOCK_SIZE); + } + void set_prev(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_BLOCK_ID); + prev_ = (prev_ & BLOCK_MASK) | (x * BLOCK_SIZE); + } + + void set_level(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_BLOCK_LEVEL); + GRN_DAT_DEBUG_THROW_IF(x > BLOCK_MASK); + next_ = (next_ & ~BLOCK_MASK) | x; + } + void set_failure_count(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_FAILURE_COUNT); + GRN_DAT_DEBUG_THROW_IF(x > BLOCK_MASK); + prev_ = (prev_ & ~BLOCK_MASK) | x; + } + + void set_first_phantom(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x >= BLOCK_SIZE); + first_phantom_ = (UInt16)x; + } + void set_num_phantoms(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > BLOCK_SIZE); + num_phantoms_ = (UInt16)x; + } + + private: + UInt32 next_; + UInt32 prev_; + UInt16 first_phantom_; + UInt16 num_phantoms_; +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/check.hpp b/storage/mroonga/vendor/groonga/lib/dat/check.hpp new file mode 100644 index 00000000..f77148c6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/check.hpp @@ -0,0 +1,149 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "dat.hpp" + +namespace grn { +namespace dat { + +class GRN_DAT_API Check { + public: + Check() : value_(0) {} + + bool operator==(const Check &rhs) const { + return value_ == rhs.value_; + } + + // The most significant bit represents whether or not the node ID is used as + // an offset. Note that the MSB is independent of the other bits. + bool is_offset() const { + return (value_ & IS_OFFSET_FLAG) == IS_OFFSET_FLAG; + } + + UInt32 except_is_offset() const { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + return value_ & ~IS_OFFSET_FLAG; + } + + // A phantom node is a node that has never been used, and such a node is also + // called an empty element. Phantom nodes form a doubly linked list in each + // block, and the linked list is represented by next() and prev(). + bool is_phantom() const { + return (value_ & IS_PHANTOM_FLAG) == IS_PHANTOM_FLAG; + } + + UInt32 next() const { + GRN_DAT_DEBUG_THROW_IF(!is_phantom()); + return (value_ >> NEXT_SHIFT) & BLOCK_MASK; + } + UInt32 prev() const { + GRN_DAT_DEBUG_THROW_IF(!is_phantom()); + return (value_ >> PREV_SHIFT) & BLOCK_MASK; + } + + // A label is attached to each non-phantom node. A label is represented by + // a byte except for a terminal label '\256'. Note that a phantom node always + // returns an invalid label with its phantom bit flag so as to reject invalid + // transitions. + UInt32 label() const { + return value_ & (IS_PHANTOM_FLAG | LABEL_MASK); + } + + // A non-phantom node has the labels of the first child and the next sibling. + // Note that INVALID_LABEL is stored if the node has no child nodes or has + // no more siblings. + UInt32 child() const { + return (value_ >> CHILD_SHIFT) & LABEL_MASK; + } + UInt32 sibling() const { + return (value_ >> SIBLING_SHIFT) & LABEL_MASK; + } + + void set_is_offset(bool x) { + if (x) { + GRN_DAT_DEBUG_THROW_IF(is_offset()); + value_ |= IS_OFFSET_FLAG; + } else { + GRN_DAT_DEBUG_THROW_IF(!is_offset()); + value_ &= ~IS_OFFSET_FLAG; + } + } + + void set_except_is_offset(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + GRN_DAT_DEBUG_THROW_IF((x & IS_OFFSET_FLAG) == IS_OFFSET_FLAG); + value_ = (value_ & IS_OFFSET_FLAG) | x; + } + + // To reject a transition to an incomplete node, set_is_phantom() invalidates + // its label and links when it becomes non-phantom. + void set_is_phantom(bool x) { + if (x) { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + value_ |= IS_PHANTOM_FLAG; + } else { + GRN_DAT_DEBUG_THROW_IF(!is_phantom()); + value_ = (value_ & IS_OFFSET_FLAG) | (INVALID_LABEL << CHILD_SHIFT) | + (INVALID_LABEL << SIBLING_SHIFT) | INVALID_LABEL; + } + } + + void set_next(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(!is_phantom()); + GRN_DAT_DEBUG_THROW_IF(x > BLOCK_MASK); + value_ = (value_ & ~(BLOCK_MASK << NEXT_SHIFT)) | (x << NEXT_SHIFT); + } + void set_prev(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(!is_phantom()); + GRN_DAT_DEBUG_THROW_IF(x > BLOCK_MASK); + value_ = (value_ & ~(BLOCK_MASK << PREV_SHIFT)) | (x << PREV_SHIFT); + } + + void set_label(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + GRN_DAT_DEBUG_THROW_IF(x > MAX_LABEL); + value_ = (value_ & ~LABEL_MASK) | x; + } + + void set_child(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + GRN_DAT_DEBUG_THROW_IF(x > MAX_LABEL); + value_ = (value_ & ~(LABEL_MASK << CHILD_SHIFT)) | (x << CHILD_SHIFT); + } + void set_sibling(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + GRN_DAT_DEBUG_THROW_IF(label() > MAX_LABEL); + GRN_DAT_DEBUG_THROW_IF((sibling() != INVALID_LABEL) && (x == INVALID_LABEL)); + value_ = (value_ & ~(LABEL_MASK << SIBLING_SHIFT)) | (x << SIBLING_SHIFT); + } + + private: + UInt32 value_; + + static const UInt32 IS_OFFSET_FLAG = 1U << 31; + static const UInt32 IS_PHANTOM_FLAG = 1U << 30; + static const UInt32 NEXT_SHIFT = 9; + static const UInt32 PREV_SHIFT = 18; + static const UInt32 CHILD_SHIFT = 9; + static const UInt32 SIBLING_SHIFT = 18; +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/cursor-factory.cpp b/storage/mroonga/vendor/groonga/lib/dat/cursor-factory.cpp new file mode 100644 index 00000000..0e97e527 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/cursor-factory.cpp @@ -0,0 +1,92 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2011 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "cursor-factory.hpp" +#include "id-cursor.hpp" +#include "key-cursor.hpp" +#include "prefix-cursor.hpp" +#include "predictive-cursor.hpp" + +#include + +namespace grn { +namespace dat { + +Cursor *CursorFactory::open(const Trie &trie, + const void *min_ptr, UInt32 min_length, + const void *max_ptr, UInt32 max_length, + UInt32 offset, + UInt32 limit, + UInt32 flags) { + const UInt32 cursor_type = flags & CURSOR_TYPE_MASK; + switch (cursor_type) { + case ID_RANGE_CURSOR: { + IdCursor *cursor = new (std::nothrow) IdCursor; + GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL); + try { + cursor->open(trie, String(min_ptr, min_length), + String(max_ptr, max_length), offset, limit, flags); + } catch (...) { + delete cursor; + throw; + } + return cursor; + } + case KEY_RANGE_CURSOR: { + KeyCursor *cursor = new (std::nothrow) KeyCursor; + GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL); + try { + cursor->open(trie, String(min_ptr, min_length), + String(max_ptr, max_length), offset, limit, flags); + } catch (...) { + delete cursor; + throw; + } + return cursor; + } + case PREFIX_CURSOR: { + PrefixCursor *cursor = new (std::nothrow) PrefixCursor; + GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL); + try { + cursor->open(trie, String(max_ptr, max_length), min_length, + offset, limit, flags); + } catch (...) { + delete cursor; + throw; + } + return cursor; + } + case PREDICTIVE_CURSOR: { + PredictiveCursor *cursor = new (std::nothrow) PredictiveCursor; + GRN_DAT_THROW_IF(MEMORY_ERROR, cursor == NULL); + try { + cursor->open(trie, String(min_ptr, min_length), + offset, limit, flags); + } catch (...) { + delete cursor; + throw; + } + return cursor; + } + default: { + GRN_DAT_THROW(PARAM_ERROR, "unknown cursor type"); + } + } +} + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/cursor-factory.hpp b/storage/mroonga/vendor/groonga/lib/dat/cursor-factory.hpp new file mode 100644 index 00000000..d48ab16d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/cursor-factory.hpp @@ -0,0 +1,44 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "cursor.hpp" + +namespace grn { +namespace dat { + +class Trie; + +class GRN_DAT_API CursorFactory { + public: + static Cursor *open(const Trie &trie, + const void *min_ptr, UInt32 min_length, + const void *max_ptr, UInt32 max_length, + UInt32 offset = 0, + UInt32 limit = MAX_UINT32, + UInt32 flags = 0); + + private: + // Disallows copy and assignment. + CursorFactory(const CursorFactory &); + CursorFactory &operator=(const CursorFactory &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/cursor.hpp b/storage/mroonga/vendor/groonga/lib/dat/cursor.hpp new file mode 100644 index 00000000..357b5250 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/cursor.hpp @@ -0,0 +1,46 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "key.hpp" + +namespace grn { +namespace dat { + +class GRN_DAT_API Cursor { + public: + Cursor() {} + virtual ~Cursor() {} + + virtual void close() = 0; + + virtual const Key &next() = 0; + + virtual UInt32 offset() const = 0; + virtual UInt32 limit() const = 0; + virtual UInt32 flags() const = 0; + + private: + // Disallows copy and assignment. + Cursor(const Cursor &); + Cursor &operator=(const Cursor &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/dat.hpp b/storage/mroonga/vendor/groonga/lib/dat/dat.hpp new file mode 100644 index 00000000..1afbd095 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/dat.hpp @@ -0,0 +1,248 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#ifndef _MSC_VER +# include +# include +#endif // _MSC_VER + +#include +#include + +#ifdef _DEBUG +# include +#endif // _DEBUG + +#ifndef GRN_DAT_API +# ifdef WIN32 +# ifdef GRN_DAT_EXPORT +# define GRN_DAT_API __declspec(dllexport) +# else // GRN_DAT_EXPORT +# define GRN_DAT_API __declspec(dllimport) +# endif // GRN_DAT_EXPORT +# else // WIN32 +# define GRN_DAT_API +# endif // WIN32 +#endif // GRN_DAT_API + +#ifdef WIN32 +# define grn_memcpy(dest, src, n) ::memcpy_s((dest), (n), (src), (n)) +#else // WIN32 +# define grn_memcpy(dest, src, n) std::memcpy((dest), (src), (n)) +#endif // WIN32 + +namespace grn { +namespace dat { + +#ifdef _MSC_VER +typedef unsigned __int8 UInt8; +typedef unsigned __int16 UInt16; +typedef unsigned __int32 UInt32; +typedef unsigned __int64 UInt64; +#else // _MSC_VER +typedef ::uint8_t UInt8; +typedef ::uint16_t UInt16; +typedef ::uint32_t UInt32; +typedef ::uint64_t UInt64; +#endif // _MSC_VER + +const UInt8 MAX_UINT8 = static_cast(0xFFU); +const UInt16 MAX_UINT16 = static_cast(0xFFFFU); +const UInt32 MAX_UINT32 = static_cast(0xFFFFFFFFU); +const UInt64 MAX_UINT64 = static_cast(0xFFFFFFFFFFFFFFFFULL); + +// If a key is a prefix of another key, such a key is associated with a special +// terminal node which has TERMINAL_LABEL. +const UInt16 TERMINAL_LABEL = 0x100; +const UInt16 MIN_LABEL = '\0'; +const UInt16 MAX_LABEL = TERMINAL_LABEL; +const UInt32 INVALID_LABEL = 0x1FF; +const UInt32 LABEL_MASK = 0x1FF; + +// The MSB of BASE is used to represent whether the node is a linker node or +// not and the other 31 bits represent the offset to its child nodes. So, the +// number of nodes is limited to 2^31. +const UInt32 ROOT_NODE_ID = 0; +const UInt32 MAX_NODE_ID = 0x7FFFFFFF; +const UInt32 MAX_NUM_NODES = MAX_NODE_ID + 1; +const UInt32 INVALID_NODE_ID = MAX_NODE_ID + 1; + +// 0 is reserved for non-linker leaf nodes. For example, the root node of an +// initial double-array is a non-linker leaf node. +const UInt32 MAX_OFFSET = MAX_NODE_ID; +const UInt32 INVALID_OFFSET = 0; + +// Phantom nodes are managed in each block because siblings are always put in +// the same block. +const UInt32 BLOCK_SIZE = 0x200; +const UInt32 BLOCK_MASK = 0x1FF; +const UInt32 MAX_BLOCK_ID = MAX_NODE_ID / BLOCK_SIZE; +const UInt32 MAX_NUM_BLOCKS = MAX_BLOCK_ID + 1; + +// Blocks are divided by their levels, which indicate how easily update +// operations can find a good offset in them. The level of a block rises when +// find_offset() fails in that block many times. MAX_FAILURE_COUNT is the +// threshold. Also, in order to limit the time cost, find_offset() scans at +// most MAX_BLOCK_COUNT blocks. +// Larger parameters bring more chances of finding good offsets but it leads to +// more node renumberings, which are costly operations, and thus results in +// a degradation of space/time efficiencies. +const UInt32 MAX_FAILURE_COUNT = 4; +const UInt32 MAX_BLOCK_COUNT = 16; +const UInt32 MAX_BLOCK_LEVEL = 5; + +// Blocks in the same level compose a doubly linked list. The entry block of +// a linked list is called a leader. INVALID_LEADER means that a linked list is +// empty and there exists no leader. +const UInt32 INVALID_LEADER = 0x7FFFFFFF; + +const UInt32 MIN_KEY_ID = 1; +const UInt32 MAX_KEY_ID = MAX_NODE_ID; +const UInt32 INVALID_KEY_ID = 0; + +// A key length is represented as a 12-bit unsigned integer in Key. +// A key ID is represented as a 28-bit unsigned integer in Key. +const UInt32 MAX_KEY_LENGTH = (1U << 12) - 1; +const UInt32 MAX_NUM_KEYS = (1U << 28) - 1; + +const UInt64 MIN_FILE_SIZE = 1 << 16; +const UInt64 DEFAULT_FILE_SIZE = 1 << 20; +const UInt64 MAX_FILE_SIZE = (UInt64)1 << 40; +const double DEFAULT_NUM_NODES_PER_KEY = 4.0; +const double MAX_NUM_NODES_PER_KEY = 16.0; +const double DEFAULT_AVERAGE_KEY_LENGTH = 16.0; +const UInt32 MAX_KEY_BUF_SIZE = 0x80000000U; +const UInt32 MAX_TOTAL_KEY_LENGTH = 0xFFFFFFFFU; + +const UInt32 ID_RANGE_CURSOR = 0x00001; +const UInt32 KEY_RANGE_CURSOR = 0x00002; +const UInt32 PREFIX_CURSOR = 0x00004; +const UInt32 PREDICTIVE_CURSOR = 0x00008; +const UInt32 CURSOR_TYPE_MASK = 0x000FF; + +const UInt32 ASCENDING_CURSOR = 0x00100; +const UInt32 DESCENDING_CURSOR = 0x00200; +const UInt32 CURSOR_ORDER_MASK = 0x00F00; + +const UInt32 EXCEPT_LOWER_BOUND = 0x01000; +const UInt32 EXCEPT_UPPER_BOUND = 0x02000; +const UInt32 EXCEPT_EXACT_MATCH = 0x04000; +const UInt32 CURSOR_OPTIONS_MASK = 0xFF000; + +const UInt32 REMOVING_FLAG = 1U << 0; +const UInt32 INSERTING_FLAG = 1U << 1; +const UInt32 UPDATING_FLAG = 1U << 2; +const UInt32 CHANGING_MASK = REMOVING_FLAG | INSERTING_FLAG | UPDATING_FLAG; + +const UInt32 MKQ_SORT_THRESHOLD = 10; + +enum ErrorCode { + PARAM_ERROR = -1, + IO_ERROR = -2, + FORMAT_ERROR = -3, + MEMORY_ERROR = -4, + SIZE_ERROR = -5, + UNEXPECTED_ERROR = -6, + STATUS_ERROR = -7 +}; + +class Exception : public std::exception { + public: + Exception() throw() + : std::exception(), + file_(""), + line_(-1), + what_("") {} + Exception(const char *file, int line, const char *what) throw() + : std::exception(), + file_(file), + line_(line), + what_((what != NULL) ? what : "") {} + Exception(const Exception &ex) throw() + : std::exception(ex), + file_(ex.file_), + line_(ex.line_), + what_(ex.what_) {} + virtual ~Exception() throw() {} + + virtual ErrorCode code() const throw() = 0; + virtual const char *file() const throw() { + return file_; + } + virtual int line() const throw() { + return line_; + } + virtual const char *what() const throw() { + return what_; + } + + private: + const char *file_; + int line_; + const char *what_; +}; + +template +class Error : public Exception { + public: + Error() throw() + : Exception() {} + Error(const char *file, int line, const char *what) throw() + : Exception(file, line, what) {} + Error(const Error &ex) throw() + : Exception(ex) {} + virtual ~Error() throw() {} + + virtual ErrorCode code() const throw() { + return T; + } +}; + +typedef Error ParamError; +typedef Error IOError; +typedef Error FormatError; +typedef Error MemoryError; +typedef Error SizeError; +typedef Error UnexpectedError; +typedef Error StatusError; + +#define GRN_DAT_INT_TO_STR(value) #value +#define GRN_DAT_LINE_TO_STR(line) GRN_DAT_INT_TO_STR(line) +#define GRN_DAT_LINE_STR GRN_DAT_LINE_TO_STR(__LINE__) + +#define GRN_DAT_THROW(code, msg)\ + (throw grn::dat::Error(__FILE__, __LINE__,\ + __FILE__ ":" GRN_DAT_LINE_STR ": " #code ": " msg)) +#define GRN_DAT_THROW_IF(code, cond)\ + (void)((!(cond)) || (GRN_DAT_THROW(code, #cond), 0)) + +#ifdef _DEBUG + #define GRN_DAT_DEBUG_THROW_IF(cond)\ + GRN_DAT_THROW_IF(grn::dat::UNEXPECTED_ERROR, cond) + #define GRN_DAT_DEBUG_LOG(var)\ + (std::clog << __FILE__ ":" GRN_DAT_LINE_STR ": " #var ": "\ + << (var) << std::endl) +#else // _DEBUG + #define GRN_DAT_DEBUG_THROW_IF(cond) + #define GRN_DAT_DEBUG_LOG(var) +#endif // _DEBUG + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/entry.hpp b/storage/mroonga/vendor/groonga/lib/dat/entry.hpp new file mode 100644 index 00000000..ecb9b53e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/entry.hpp @@ -0,0 +1,59 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "dat.hpp" + +namespace grn { +namespace dat { + +// The most significant bit represents whether or not the entry is valid. +// A valid entry stores the position of its associated key and an invalid entry +// stores the index of the next invalid entry. +class GRN_DAT_API Entry { + public: + Entry() : value_(0) {} + + bool is_valid() const { + return (value_ & IS_VALID_FLAG) == IS_VALID_FLAG; + } + UInt32 key_pos() const { + GRN_DAT_DEBUG_THROW_IF(!is_valid()); + return value_ & ~IS_VALID_FLAG; + } + UInt32 next() const { + GRN_DAT_DEBUG_THROW_IF(is_valid()); + return value_; + } + + void set_key_pos(UInt32 x) { + value_ = IS_VALID_FLAG | x; + } + void set_next(UInt32 x) { + value_ = x; + } + + private: + UInt32 value_; + + static const UInt32 IS_VALID_FLAG = 0x80000000U; +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp b/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp new file mode 100644 index 00000000..7032eff3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/file-impl.cpp @@ -0,0 +1,279 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "file-impl.hpp" + +#include +#include + +#ifdef WIN32 +# ifdef min +# undef min +# endif // min +# ifdef max +# undef max +# endif // max +#else // WIN32 +# include +# include +# include +#endif // WIN32 + +#include +#include + +/* Must be the same value as GRN_OPEN_CREATE_MODE */ +#ifdef WIN32 +# define GRN_IO_FILE_CREATE_MODE (GENERIC_READ | GENERIC_WRITE) +#else /* WIN32 */ +# define GRN_IO_FILE_CREATE_MODE 0640 +#endif /* WIN32 */ + +namespace grn { +namespace dat { + +#ifdef WIN32 + +FileImpl::FileImpl() + : ptr_(NULL), + size_(0), + file_(INVALID_HANDLE_VALUE), + map_(INVALID_HANDLE_VALUE), + addr_(NULL) {} + +FileImpl::~FileImpl() { + if (addr_ != NULL) { + ::UnmapViewOfFile(addr_); + } + + if (map_ != INVALID_HANDLE_VALUE) { + ::CloseHandle(map_); + } + + if (file_ != INVALID_HANDLE_VALUE) { + ::CloseHandle(file_); + } +} + +#else // WIN32 + +FileImpl::FileImpl() + : ptr_(NULL), + size_(0), + fd_(-1), + addr_(MAP_FAILED), + length_(0) {} + +FileImpl::~FileImpl() { + if (addr_ != MAP_FAILED) { + ::munmap(addr_, length_); + } + + if (fd_ != -1) { + ::close(fd_); + } +} + +#endif // WIN32 + +void FileImpl::create(const char *path, UInt64 size) { + GRN_DAT_THROW_IF(PARAM_ERROR, size == 0); + GRN_DAT_THROW_IF(PARAM_ERROR, + size > static_cast(std::numeric_limits< ::size_t>::max())); + + FileImpl new_impl; + new_impl.create_(path, size); + new_impl.swap(this); +} + +void FileImpl::open(const char *path) { + GRN_DAT_THROW_IF(PARAM_ERROR, path == NULL); + GRN_DAT_THROW_IF(PARAM_ERROR, path[0] == '\0'); + + FileImpl new_impl; + new_impl.open_(path); + new_impl.swap(this); +} + +void FileImpl::close() { + FileImpl new_impl; + new_impl.swap(this); +} + +#ifdef WIN32 + +void FileImpl::swap(FileImpl *rhs) { + std::swap(ptr_, rhs->ptr_); + std::swap(size_, rhs->size_); + std::swap(file_, rhs->file_); + std::swap(map_, rhs->map_); + std::swap(addr_, rhs->addr_); +} + +void FileImpl::flush() { + if (!addr_) { + return; + } + + BOOL succeeded = ::FlushViewOfFile(addr_, static_cast(size_)); + GRN_DAT_THROW_IF(IO_ERROR, !succeeded); + + SYSTEMTIME system_time; + GetSystemTime(&system_time); + FILETIME file_time; + succeeded = SystemTimeToFileTime(&system_time, &file_time); + GRN_DAT_THROW_IF(IO_ERROR, !succeeded); + + succeeded = SetFileTime(file_, NULL, NULL, &file_time); + GRN_DAT_THROW_IF(IO_ERROR, !succeeded); +} + +void FileImpl::create_(const char *path, UInt64 size) { + if ((path != NULL) && (path[0] != '\0')) { + file_ = ::CreateFileA(path, GRN_IO_FILE_CREATE_MODE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + GRN_DAT_THROW_IF(IO_ERROR, file_ == INVALID_HANDLE_VALUE); + + const LONG size_low = static_cast(size & 0xFFFFFFFFU); + LONG size_high = static_cast(size >> 32); + const DWORD file_pos = ::SetFilePointer(file_, size_low, &size_high, + FILE_BEGIN); + GRN_DAT_THROW_IF(IO_ERROR, (file_pos == INVALID_SET_FILE_POINTER) && + (::GetLastError() != 0)); + GRN_DAT_THROW_IF(IO_ERROR, ::SetEndOfFile(file_) == 0); + + map_ = ::CreateFileMapping(file_, NULL, PAGE_READWRITE, 0, 0, NULL); + GRN_DAT_THROW_IF(IO_ERROR, map_ == INVALID_HANDLE_VALUE); + } else { + const DWORD size_low = static_cast(size & 0xFFFFFFFFU); + const DWORD size_high = static_cast(size >> 32); + + map_ = ::CreateFileMapping(file_, NULL, PAGE_READWRITE, + size_high, size_low, NULL); + GRN_DAT_THROW_IF(IO_ERROR, map_ == INVALID_HANDLE_VALUE); + } + + addr_ = ::MapViewOfFile(map_, FILE_MAP_WRITE, 0, 0, 0); + GRN_DAT_THROW_IF(IO_ERROR, addr_ == NULL); + + ptr_ = addr_; + size_ = static_cast< ::size_t>(size); +} + +void FileImpl::open_(const char *path) { +#ifdef _MSC_VER + struct __stat64 st; + GRN_DAT_THROW_IF(IO_ERROR, ::_stat64(path, &st) == -1); +#else // _MSC_VER + struct _stat st; + GRN_DAT_THROW_IF(IO_ERROR, ::_stat(path, &st) == -1); +#endif // _MSC_VER + GRN_DAT_THROW_IF(IO_ERROR, st.st_size == 0); + GRN_DAT_THROW_IF(IO_ERROR, + static_cast(st.st_size) > std::numeric_limits< ::size_t>::max()); + + file_ = ::CreateFileA(path, GRN_IO_FILE_CREATE_MODE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + GRN_DAT_THROW_IF(IO_ERROR, file_ == NULL); + + map_ = ::CreateFileMapping(file_, NULL, PAGE_READWRITE, 0, 0, NULL); + GRN_DAT_THROW_IF(IO_ERROR, map_ == NULL); + + addr_ = ::MapViewOfFile(map_, FILE_MAP_WRITE, 0, 0, 0); + GRN_DAT_THROW_IF(IO_ERROR, addr_ == NULL); + + ptr_ = addr_; + size_ = static_cast< ::size_t>(st.st_size); +} + +#else // WIN32 + +void FileImpl::swap(FileImpl *rhs) { + std::swap(ptr_, rhs->ptr_); + std::swap(size_, rhs->size_); + std::swap(fd_, rhs->fd_); + std::swap(addr_, rhs->addr_); + std::swap(length_, rhs->length_); +} + +void FileImpl::flush() { + if (!addr_) { + return; + } + + int result = ::msync(addr_, length_, MS_SYNC); + GRN_DAT_THROW_IF(IO_ERROR, result != 0); +} + +void FileImpl::create_(const char *path, UInt64 size) { + GRN_DAT_THROW_IF(PARAM_ERROR, + size > static_cast(std::numeric_limits< ::off_t>::max())); + + if ((path != NULL) && (path[0] != '\0')) { + fd_ = ::open(path, O_RDWR | O_CREAT | O_TRUNC, GRN_IO_FILE_CREATE_MODE); + GRN_DAT_THROW_IF(IO_ERROR, fd_ == -1); + + const ::off_t file_size = static_cast< ::off_t>(size); + GRN_DAT_THROW_IF(IO_ERROR, ::ftruncate(fd_, file_size) == -1); + } + +#ifdef MAP_ANONYMOUS + const int flags = (fd_ == -1) ? (MAP_PRIVATE | MAP_ANONYMOUS) : MAP_SHARED; +#else // MAP_ANONYMOUS + const int flags = (fd_ == -1) ? (MAP_PRIVATE | MAP_ANON) : MAP_SHARED; +#endif // MAP_ANONYMOUS + + length_ = static_cast< ::size_t>(size); +#ifdef USE_MAP_HUGETLB + addr_ = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, + flags | MAP_HUGETLB, fd_, 0); +#endif // USE_MAP_HUGETLB + if (addr_ == MAP_FAILED) { + addr_ = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, flags, fd_, 0); + GRN_DAT_THROW_IF(IO_ERROR, addr_ == MAP_FAILED); + } + + ptr_ = addr_; + size_ = length_; +} + +void FileImpl::open_(const char *path) { + struct stat st; + GRN_DAT_THROW_IF(IO_ERROR, ::stat(path, &st) == -1); + GRN_DAT_THROW_IF(IO_ERROR, (st.st_mode & S_IFMT) != S_IFREG); + GRN_DAT_THROW_IF(IO_ERROR, st.st_size == 0); + GRN_DAT_THROW_IF(IO_ERROR, + static_cast(st.st_size) > std::numeric_limits< ::size_t>::max()); + + fd_ = ::open(path, O_RDWR); + GRN_DAT_THROW_IF(IO_ERROR, fd_ == -1); + + length_ = static_cast(st.st_size); + addr_ = ::mmap(NULL, length_, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0); + GRN_DAT_THROW_IF(IO_ERROR, addr_ == MAP_FAILED); + + ptr_ = addr_; + size_ = length_; +} + +#endif // WIN32 + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/file-impl.hpp b/storage/mroonga/vendor/groonga/lib/dat/file-impl.hpp new file mode 100644 index 00000000..7b9c8c76 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/file-impl.hpp @@ -0,0 +1,73 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#ifdef WIN32 +# include +#endif // WIN32 + +#include "dat.hpp" + +namespace grn { +namespace dat { + +class FileImpl { + public: + FileImpl(); + ~FileImpl(); + + void create(const char *path, UInt64 size); + void open(const char *path); + void close(); + + void *ptr() const { + return ptr_; + } + UInt64 size() const { + return size_; + } + + void swap(FileImpl *rhs); + + void flush(); + + private: + void *ptr_; + UInt64 size_; + +#ifdef WIN32 + HANDLE file_; + HANDLE map_; + LPVOID addr_; +#else // WIN32 + int fd_; + void *addr_; + ::size_t length_; +#endif // WIN32 + + void create_(const char *path, UInt64 size); + void open_(const char *path); + + // Disallows copy and assignment. + FileImpl(const FileImpl &); + FileImpl &operator=(const FileImpl &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/file.cpp b/storage/mroonga/vendor/groonga/lib/dat/file.cpp new file mode 100644 index 00000000..84f2a1fb --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/file.cpp @@ -0,0 +1,73 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2011-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "file.hpp" +#include "file-impl.hpp" + +#include + +namespace grn { +namespace dat { + +File::File() : impl_(NULL) {} + +File::~File() { + delete impl_; +} + +void File::create(const char *path, UInt64 size) { + File new_file; + new_file.impl_ = new (std::nothrow) FileImpl; + GRN_DAT_THROW_IF(MEMORY_ERROR, new_file.impl_ == NULL); + new_file.impl_->create(path, size); + new_file.swap(this); +} + +void File::open(const char *path) { + File new_file; + new_file.impl_ = new (std::nothrow) FileImpl; + GRN_DAT_THROW_IF(MEMORY_ERROR, new_file.impl_ == NULL); + new_file.impl_->open(path); + new_file.swap(this); +} + +void File::close() { + File().swap(this); +} + +void *File::ptr() const { + return (impl_ != NULL) ? impl_->ptr() : NULL; +} + +UInt64 File::size() const { + return (impl_ != NULL) ? impl_->size() : 0; +} + +void File::swap(File *rhs) { + FileImpl * const temp = impl_; + impl_ = rhs->impl_; + rhs->impl_ = temp; +} + +void File::flush() { + if (impl_) { + impl_->flush(); + } +} + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/file.hpp b/storage/mroonga/vendor/groonga/lib/dat/file.hpp new file mode 100644 index 00000000..722b93dd --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/file.hpp @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "dat.hpp" + +namespace grn { +namespace dat { + +// This implementation class hides environment dependent codes required for +// memory-mapped I/O. +class FileImpl; + +class GRN_DAT_API File { + public: + File(); + ~File(); + + // This function creates a file and maps the entire file to a certain range + // of the address space. Note that a file is truncated if exists. + void create(const char *path, UInt64 size); + + // This function opens a file and maps the entire file to a certain range of + // the address space. + void open(const char *path); + void close(); + + void *ptr() const; + UInt64 size() const; + + void swap(File *rhs); + + void flush(); + + private: + FileImpl *impl_; + + // Disallows copy and assignment. + File(const File &); + File &operator=(const File &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/header.hpp b/storage/mroonga/vendor/groonga/lib/dat/header.hpp new file mode 100644 index 00000000..dbbb1efd --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/header.hpp @@ -0,0 +1,179 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "dat.hpp" + +namespace grn { +namespace dat { + +class GRN_DAT_API Header { + public: + Header() + : file_size_(0), + total_key_length_(0), + next_key_id_(grn::dat::MIN_KEY_ID), + max_key_id_(0), + num_keys_(0), + max_num_keys_(0), + num_phantoms_(0), + num_zombies_(0), + num_blocks_(0), + max_num_blocks_(0), + next_key_pos_(0), + key_buf_size_(0), + status_flags_(0) { + for (UInt32 i = 0; i <= MAX_BLOCK_LEVEL; ++i) { + leaders_[i] = INVALID_LEADER; + } + for (UInt32 i = 0; i < (sizeof(reserved_) / sizeof(*reserved_)); ++i) { + reserved_[i] = 0; + } + } + + UInt64 file_size() const { + return file_size_; + } + UInt32 total_key_length() const { + return total_key_length_; + } + UInt32 min_key_id() const { + return MIN_KEY_ID; + } + UInt32 next_key_id() const { + return next_key_id_; + } + UInt32 max_key_id() const { + return max_key_id_; + } + UInt32 num_keys() const { + return num_keys_; + } + UInt32 max_num_keys() const { + return max_num_keys_; + } + UInt32 num_nodes() const { + return num_blocks() * BLOCK_SIZE; + } + UInt32 num_phantoms() const { + return num_phantoms_; + } + UInt32 num_zombies() const { + return num_zombies_; + } + UInt32 max_num_nodes() const { + return max_num_blocks() * BLOCK_SIZE; + } + UInt32 num_blocks() const { + return num_blocks_; + } + UInt32 max_num_blocks() const { + return max_num_blocks_; + } + UInt32 next_key_pos() const { + return next_key_pos_; + } + UInt32 key_buf_size() const { + return key_buf_size_; + } + UInt32 status_flags() const { + return status_flags_; + } + UInt32 ith_leader(UInt32 i) const { + GRN_DAT_DEBUG_THROW_IF(i > MAX_BLOCK_LEVEL); + return leaders_[i]; + } + + void set_file_size(UInt64 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_FILE_SIZE); + file_size_ = x; + } + void set_total_key_length(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_TOTAL_KEY_LENGTH); + total_key_length_ = x; + } + void set_next_key_id(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF((x - 1) > MAX_KEY_ID); + next_key_id_ = x; + } + void set_max_key_id(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_KEY_ID); + max_key_id_ = x; + } + void set_num_keys(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_NUM_KEYS); + num_keys_ = x; + } + void set_max_num_keys(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_NUM_KEYS); + max_num_keys_ = x; + } + void set_num_phantoms(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > max_num_nodes()); + num_phantoms_ = x; + } + void set_num_zombies(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > max_num_nodes()); + num_zombies_ = x; + } + void set_num_blocks(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > max_num_blocks()); + num_blocks_ = x; + } + void set_max_num_blocks(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_NUM_BLOCKS); + max_num_blocks_ = x; + } + void set_next_key_pos(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > key_buf_size()); + next_key_pos_ = x; + } + void set_key_buf_size(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(x > MAX_KEY_BUF_SIZE); + key_buf_size_ = x; + } + void set_status_flags(UInt32 x) { + status_flags_ = x; + } + void set_ith_leader(UInt32 i, UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(i > MAX_BLOCK_LEVEL); + GRN_DAT_DEBUG_THROW_IF((x != INVALID_LEADER) && (x >= num_blocks())); + leaders_[i] = x; + } + + private: + UInt64 file_size_; + UInt32 total_key_length_; + UInt32 next_key_id_; + UInt32 max_key_id_; + UInt32 num_keys_; + UInt32 max_num_keys_; + UInt32 num_phantoms_; + UInt32 num_zombies_; + UInt32 num_blocks_; + UInt32 max_num_blocks_; + UInt32 next_key_pos_; + UInt32 key_buf_size_; + UInt32 leaders_[MAX_BLOCK_LEVEL + 1]; + UInt32 status_flags_; + UInt32 reserved_[12]; +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp b/storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp new file mode 100644 index 00000000..de969839 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/id-cursor.cpp @@ -0,0 +1,184 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2011 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "id-cursor.hpp" + +#include + +#include "trie.hpp" + +namespace grn { +namespace dat { + +IdCursor::IdCursor() + : trie_(NULL), + offset_(0), + limit_(MAX_UINT32), + flags_(ID_RANGE_CURSOR), + cur_(INVALID_KEY_ID), + end_(INVALID_KEY_ID), + count_(0) {} + +IdCursor::~IdCursor() {} + +void IdCursor::open(const Trie &trie, + const String &min_str, + const String &max_str, + UInt32 offset, + UInt32 limit, + UInt32 flags) { + UInt32 min_id = INVALID_KEY_ID; + if (min_str.ptr() != NULL) { + UInt32 key_pos; + GRN_DAT_THROW_IF(PARAM_ERROR, + !trie.search(min_str.ptr(), min_str.length(), &key_pos)); + min_id = trie.get_key(key_pos).id(); + } + + UInt32 max_id = INVALID_KEY_ID; + if (max_str.ptr() != NULL) { + UInt32 key_pos; + GRN_DAT_THROW_IF(PARAM_ERROR, + !trie.search(max_str.ptr(), max_str.length(), &key_pos)); + max_id = trie.get_key(key_pos).id(); + } + + open(trie, min_id, max_id, offset, limit, flags); +} + +void IdCursor::open(const Trie &trie, + UInt32 min_id, + UInt32 max_id, + UInt32 offset, + UInt32 limit, + UInt32 flags) { + flags = fix_flags(flags); + + IdCursor new_cursor(trie, offset, limit, flags); + new_cursor.init(min_id, max_id); + new_cursor.swap(this); +} + +void IdCursor::close() { + IdCursor new_cursor; + new_cursor.swap(this); +} + +const Key &IdCursor::next() { + if (count_ >= limit_) { + return Key::invalid_key(); + } + while (cur_ != end_) { + const Key &key = trie_->ith_key(cur_); + if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { + ++cur_; + } else { + --cur_; + } + if (key.is_valid()) { + ++count_; + return key; + } + } + return Key::invalid_key(); +} + +IdCursor::IdCursor(const Trie &trie, + UInt32 offset, + UInt32 limit, + UInt32 flags) + : trie_(&trie), + offset_(offset), + limit_(limit), + flags_(flags), + cur_(INVALID_KEY_ID), + end_(INVALID_KEY_ID), + count_(0) {} + +UInt32 IdCursor::fix_flags(UInt32 flags) const { + const UInt32 cursor_type = flags & CURSOR_TYPE_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) && + (cursor_type != ID_RANGE_CURSOR)); + flags |= ID_RANGE_CURSOR; + + const UInt32 cursor_order = flags & CURSOR_ORDER_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_order != 0) && + (cursor_order != ASCENDING_CURSOR) && + (cursor_order != DESCENDING_CURSOR)); + if (cursor_order == 0) { + flags |= ASCENDING_CURSOR; + } + + const UInt32 cursor_options = flags & CURSOR_OPTIONS_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, + cursor_options & ~(EXCEPT_LOWER_BOUND | EXCEPT_UPPER_BOUND)); + + return flags; +} + +void IdCursor::init(UInt32 min_id, UInt32 max_id) { + if (min_id == INVALID_KEY_ID) { + min_id = trie_->min_key_id(); + } else if ((flags_ & EXCEPT_LOWER_BOUND) == EXCEPT_LOWER_BOUND) { + ++min_id; + } + + if (max_id == INVALID_KEY_ID) { + max_id = trie_->max_key_id(); + } else if ((flags_ & EXCEPT_UPPER_BOUND) == EXCEPT_UPPER_BOUND) { + --max_id; + } + + if ((max_id < min_id) || ((max_id - min_id) < offset_)) { + return; + } + + if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { + cur_ = min_id; + end_ = max_id + 1; + for (UInt32 i = 0; (i < offset_) && (cur_ != end_); ++i) { + while (cur_ != end_) { + if (trie_->ith_key(cur_++).is_valid()) { + break; + } + } + } + } else { + cur_ = max_id; + end_ = min_id - 1; + for (UInt32 i = 0; (i < offset_) && (cur_ != end_); ++i) { + while (cur_ != end_) { + if (trie_->ith_key(cur_--).is_valid()) { + break; + } + } + } + } +} + +void IdCursor::swap(IdCursor *cursor) { + std::swap(trie_, cursor->trie_); + std::swap(offset_, cursor->offset_); + std::swap(limit_, cursor->limit_); + std::swap(flags_, cursor->flags_); + std::swap(cur_, cursor->cur_); + std::swap(end_, cursor->end_); + std::swap(count_, cursor->count_); +} + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/id-cursor.hpp b/storage/mroonga/vendor/groonga/lib/dat/id-cursor.hpp new file mode 100644 index 00000000..60953fae --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/id-cursor.hpp @@ -0,0 +1,83 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "cursor.hpp" + +namespace grn { +namespace dat { + +class Trie; + +class GRN_DAT_API IdCursor : public Cursor { + public: + IdCursor(); + ~IdCursor(); + + void open(const Trie &trie, + const String &min_str, + const String &max_str, + UInt32 offset = 0, + UInt32 limit = MAX_UINT32, + UInt32 flags = 0); + + void open(const Trie &trie, + UInt32 min_id, + UInt32 max_id, + UInt32 offset = 0, + UInt32 limit = MAX_UINT32, + UInt32 flags = 0); + + void close(); + + const Key &next(); + + UInt32 offset() const { + return offset_; + } + UInt32 limit() const { + return limit_; + } + UInt32 flags() const { + return flags_; + } + + private: + const Trie *trie_; + UInt32 offset_; + UInt32 limit_; + UInt32 flags_; + + UInt32 cur_; + UInt32 end_; + UInt32 count_; + + IdCursor(const Trie &trie, UInt32 offset, UInt32 limit, UInt32 flags); + + UInt32 fix_flags(UInt32 flags) const; + void init(UInt32 min_id, UInt32 max_id); + void swap(IdCursor *cursor); + + // Disallows copy and assignment. + IdCursor(const IdCursor &); + IdCursor &operator=(const IdCursor &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/key-cursor.cpp b/storage/mroonga/vendor/groonga/lib/dat/key-cursor.cpp new file mode 100644 index 00000000..2ce04fee --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/key-cursor.cpp @@ -0,0 +1,349 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2011 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "key-cursor.hpp" + +#include +#include + +#include "trie.hpp" + +namespace grn { +namespace dat { + +KeyCursor::KeyCursor() + : trie_(NULL), + offset_(0), + limit_(MAX_UINT32), + flags_(KEY_RANGE_CURSOR), + buf_(), + count_(0), + max_count_(0), + finished_(false), + end_buf_(NULL), + end_str_() {} + +KeyCursor::~KeyCursor() { + if (end_buf_ != NULL) { + delete [] end_buf_; + } +} + +void KeyCursor::open(const Trie &trie, + const String &min_str, + const String &max_str, + UInt32 offset, + UInt32 limit, + UInt32 flags) { + GRN_DAT_THROW_IF(PARAM_ERROR, + (min_str.ptr() == NULL) && (min_str.length() != 0)); + GRN_DAT_THROW_IF(PARAM_ERROR, + (max_str.ptr() == NULL) && (max_str.length() != 0)); + + flags = fix_flags(flags); + KeyCursor new_cursor(trie, offset, limit, flags); + new_cursor.init(min_str, max_str); + new_cursor.swap(this); +} + +void KeyCursor::close() { + KeyCursor new_cursor; + new_cursor.swap(this); +} + +const Key &KeyCursor::next() { + if (finished_ || (count_ >= max_count_)) { + return Key::invalid_key(); + } + + if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { + return ascending_next(); + } else { + return descending_next(); + } +} + +KeyCursor::KeyCursor(const Trie &trie, + UInt32 offset, UInt32 limit, UInt32 flags) + : trie_(&trie), + offset_(offset), + limit_(limit), + flags_(flags), + buf_(), + count_(0), + max_count_(0), + finished_(false), + end_buf_(NULL), + end_str_() {} + +UInt32 KeyCursor::fix_flags(UInt32 flags) const { + const UInt32 cursor_type = flags & CURSOR_TYPE_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) && + (cursor_type != KEY_RANGE_CURSOR)); + flags |= KEY_RANGE_CURSOR; + + const UInt32 cursor_order = flags & CURSOR_ORDER_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_order != 0) && + (cursor_order != ASCENDING_CURSOR) && + (cursor_order != DESCENDING_CURSOR)); + if (cursor_order == 0) { + flags |= ASCENDING_CURSOR; + } + + const UInt32 cursor_options = flags & CURSOR_OPTIONS_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, + cursor_options & ~(EXCEPT_LOWER_BOUND | EXCEPT_UPPER_BOUND)); + + return flags; +} + +void KeyCursor::init(const String &min_str, const String &max_str) { + if (offset_ > (MAX_UINT32 - limit_)) { + max_count_ = MAX_UINT32; + } else { + max_count_ = offset_ + limit_; + } + + if (limit_ == 0) { + return; + } + + if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { + ascending_init(min_str, max_str); + } else { + descending_init(min_str, max_str); + } +} + +void KeyCursor::ascending_init(const String &min_str, const String &max_str) { + if (max_str.ptr() != NULL) { + if (max_str.length() != 0) { + end_buf_ = new UInt8[max_str.length()]; + grn_memcpy(end_buf_, max_str.ptr(), max_str.length()); + end_str_.assign(end_buf_, max_str.length()); + } + } + + if ((min_str.ptr() == NULL) || (min_str.length() == 0)) { + buf_.push_back(ROOT_NODE_ID); + return; + } + + UInt32 node_id = ROOT_NODE_ID; + Node node; + for (UInt32 i = 0; i < min_str.length(); ++i) { + node = trie_->ith_node(node_id); + if (node.is_linker()) { + const Key &key = trie_->get_key(node.key_pos()); + const int result = key.str().compare(min_str, i); + if ((result > 0) || ((result == 0) && + ((flags_ & EXCEPT_LOWER_BOUND) != EXCEPT_LOWER_BOUND))) { + buf_.push_back(node_id); + } else if (node.sibling() != INVALID_LABEL) { + buf_.push_back(node_id ^ node.label() ^ node.sibling()); + } + return; + } else if (node.sibling() != INVALID_LABEL) { + buf_.push_back(node_id ^ node.label() ^ node.sibling()); + } + + node_id = node.offset() ^ min_str[i]; + if (trie_->ith_node(node_id).label() != min_str[i]) { + UInt16 label = node.child(); + if (label == TERMINAL_LABEL) { + label = trie_->ith_node(node.offset() ^ label).sibling(); + } + while (label != INVALID_LABEL) { + if (label > min_str[i]) { + buf_.push_back(node.offset() ^ label); + break; + } + label = trie_->ith_node(node.offset() ^ label).sibling(); + } + return; + } + } + + node = trie_->ith_node(node_id); + if (node.is_linker()) { + const Key &key = trie_->get_key(node.key_pos()); + if ((key.length() != min_str.length()) || + ((flags_ & EXCEPT_LOWER_BOUND) != EXCEPT_LOWER_BOUND)) { + buf_.push_back(node_id); + } else if (node.sibling() != INVALID_LABEL) { + buf_.push_back(node_id ^ node.label() ^ node.sibling()); + } + return; + } else if (node.sibling() != INVALID_LABEL) { + buf_.push_back(node_id ^ node.label() ^ node.sibling()); + } + + UInt16 label = node.child(); + if ((label == TERMINAL_LABEL) && + ((flags_ & EXCEPT_LOWER_BOUND) == EXCEPT_LOWER_BOUND)) { + label = trie_->ith_node(node.offset() ^ label).sibling(); + } + if (label != INVALID_LABEL) { + buf_.push_back(node.offset() ^ label); + } +} + +void KeyCursor::descending_init(const String &min_str, const String &max_str) { + if (min_str.ptr() != NULL) { + if (min_str.length() != 0) { + end_buf_ = new UInt8[min_str.length()]; + grn_memcpy(end_buf_, min_str.ptr(), min_str.length()); + end_str_.assign(end_buf_, min_str.length()); + } + } + + if ((max_str.ptr() == NULL) || (max_str.length() == 0)) { + buf_.push_back(ROOT_NODE_ID); + return; + } + + UInt32 node_id = ROOT_NODE_ID; + for (UInt32 i = 0; i < max_str.length(); ++i) { + const Base base = trie_->ith_node(node_id).base(); + if (base.is_linker()) { + const Key &key = trie_->get_key(base.key_pos()); + const int result = key.str().compare(max_str, i); + if ((result < 0) || ((result == 0) && + ((flags_ & EXCEPT_UPPER_BOUND) != EXCEPT_UPPER_BOUND))) { + buf_.push_back(node_id | POST_ORDER_FLAG); + } + return; + } + + UInt32 label = trie_->ith_node(node_id).child(); + if (label == TERMINAL_LABEL) { + node_id = base.offset() ^ label; + buf_.push_back(node_id | POST_ORDER_FLAG); + label = trie_->ith_node(node_id).sibling(); + } + while (label != INVALID_LABEL) { + node_id = base.offset() ^ label; + if (label < max_str[i]) { + buf_.push_back(node_id); + } else if (label > max_str[i]) { + return; + } else { + break; + } + label = trie_->ith_node(node_id).sibling(); + } + if (label == INVALID_LABEL) { + return; + } + } + + const Base base = trie_->ith_node(node_id).base(); + if (base.is_linker()) { + const Key &key = trie_->get_key(base.key_pos()); + if ((key.length() == max_str.length()) && + ((flags_ & EXCEPT_UPPER_BOUND) != EXCEPT_UPPER_BOUND)) { + buf_.push_back(node_id | POST_ORDER_FLAG); + } + return; + } + + UInt16 label = trie_->ith_node(node_id).child(); + if ((label == TERMINAL_LABEL) && + ((flags_ & EXCEPT_UPPER_BOUND) != EXCEPT_UPPER_BOUND)) { + buf_.push_back((base.offset() ^ label) | POST_ORDER_FLAG); + } +} + +void KeyCursor::swap(KeyCursor *cursor) { + std::swap(trie_, cursor->trie_); + std::swap(offset_, cursor->offset_); + std::swap(limit_, cursor->limit_); + std::swap(flags_, cursor->flags_); + buf_.swap(&cursor->buf_); + std::swap(count_, cursor->count_); + std::swap(max_count_, cursor->max_count_); + std::swap(finished_, cursor->finished_); + std::swap(end_buf_, cursor->end_buf_); + end_str_.swap(&cursor->end_str_); +} + +const Key &KeyCursor::ascending_next() { + while (!buf_.empty()) { + const UInt32 node_id = buf_.back(); + buf_.pop_back(); + + const Node node = trie_->ith_node(node_id); + if (node.sibling() != INVALID_LABEL) { + buf_.push_back(node_id ^ node.label() ^ node.sibling()); + } + + if (node.is_linker()) { + const Key &key = trie_->get_key(node.key_pos()); + if (end_buf_ != NULL) { + const int result = key.str().compare(end_str_); + if ((result > 0) || ((result == 0) && + ((flags_ & EXCEPT_UPPER_BOUND) == EXCEPT_UPPER_BOUND))) { + finished_ = true; + return Key::invalid_key(); + } + } + if (count_++ >= offset_) { + return key; + } + } else if (node.child() != INVALID_LABEL) { + buf_.push_back(node.offset() ^ node.child()); + } + } + return Key::invalid_key(); +} + +const Key &KeyCursor::descending_next() { + while (!buf_.empty()) { + const bool post_order = (buf_.back() & POST_ORDER_FLAG) == POST_ORDER_FLAG; + const UInt32 node_id = buf_.back() & ~POST_ORDER_FLAG; + + const Base base = trie_->ith_node(node_id).base(); + if (post_order) { + buf_.pop_back(); + if (base.is_linker()) { + const Key &key = trie_->get_key(base.key_pos()); + if (end_buf_ != NULL) { + const int result = key.str().compare(end_str_); + if ((result < 0) || ((result == 0) && + ((flags_ & EXCEPT_LOWER_BOUND) == EXCEPT_LOWER_BOUND))) { + finished_ = true; + return Key::invalid_key(); + } + } + if (count_++ >= offset_) { + return key; + } + } + } else { + buf_.back() |= POST_ORDER_FLAG; + UInt16 label = trie_->ith_node(node_id).child(); + while (label != INVALID_LABEL) { + buf_.push_back(base.offset() ^ label); + label = trie_->ith_node(base.offset() ^ label).sibling(); + } + } + } + return Key::invalid_key(); +} + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/key-cursor.hpp b/storage/mroonga/vendor/groonga/lib/dat/key-cursor.hpp new file mode 100644 index 00000000..56392b63 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/key-cursor.hpp @@ -0,0 +1,88 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "cursor.hpp" +#include "vector.hpp" + +namespace grn { +namespace dat { + +class Trie; + +class GRN_DAT_API KeyCursor : public Cursor { + public: + KeyCursor(); + ~KeyCursor(); + + void open(const Trie &trie, + const String &min_str, + const String &max_str, + UInt32 offset = 0, + UInt32 limit = MAX_UINT32, + UInt32 flags = 0); + + void close(); + + const Key &next(); + + UInt32 offset() const { + return offset_; + } + UInt32 limit() const { + return limit_; + } + UInt32 flags() const { + return flags_; + } + + private: + const Trie *trie_; + UInt32 offset_; + UInt32 limit_; + UInt32 flags_; + + Vector buf_; + UInt32 count_; + UInt32 max_count_; + bool finished_; + UInt8 *end_buf_; + String end_str_; + + KeyCursor(const Trie &trie, + UInt32 offset, UInt32 limit, UInt32 flags); + + UInt32 fix_flags(UInt32 flags) const; + void init(const String &min_str, const String &max_str); + void ascending_init(const String &min_str, const String &max_str); + void descending_init(const String &min_str, const String &max_str); + void swap(KeyCursor *cursor); + + const Key &ascending_next(); + const Key &descending_next(); + + static const UInt32 POST_ORDER_FLAG = 0x80000000U; + + // Disallows copy and assignment. + KeyCursor(const KeyCursor &); + KeyCursor &operator=(const KeyCursor &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/key.hpp b/storage/mroonga/vendor/groonga/lib/dat/key.hpp new file mode 100644 index 00000000..eb0324cd --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/key.hpp @@ -0,0 +1,110 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "string.hpp" + +namespace grn { +namespace dat { + +class GRN_DAT_API Key { + public: + const UInt8 &operator[](UInt32 i) const { + GRN_DAT_DEBUG_THROW_IF(i >= length()); + return buf_[i]; + } + + bool is_valid() const { + return id() != INVALID_KEY_ID; + } + + String str() const { + return String(ptr(), length()); + } + + const void *ptr() const { + return buf_; + } + UInt32 length() const { + return (length_high_ << 4) | (id_and_length_low_ & 0x0F); + } + UInt32 id() const { + return id_and_length_low_ >> 4; + } + + bool equals_to(const void *ptr, UInt32 length, UInt32 offset = 0) const { + if (length != this->length()) { + return false; + } + for ( ; offset < length; ++offset) { + if ((*this)[offset] != static_cast(ptr)[offset]) { + return false; + } + } + return true; + } + + // Creates an object of Key from given parameters. Then, the created object + // is embedded into a specified buffer. + static const Key &create(UInt32 *buf, UInt32 key_id, + const void *key_ptr, UInt32 key_length) { + GRN_DAT_DEBUG_THROW_IF(buf == NULL); + GRN_DAT_DEBUG_THROW_IF(key_id > MAX_KEY_ID); + GRN_DAT_DEBUG_THROW_IF((key_ptr == NULL) && (key_length != 0)); + GRN_DAT_DEBUG_THROW_IF(key_length > MAX_KEY_LENGTH); + + *buf = (key_id << 4) | (key_length & 0x0F); + UInt8 *ptr = reinterpret_cast(buf + 1); + *ptr++ = key_length >> 4; + for (UInt32 i = 0; i < key_length; ++i) { + ptr[i] = static_cast(key_ptr)[i]; + } + return *reinterpret_cast(buf); + } + + // Calculates how many UInt32s are required for a string. It is guaranteed + // that the estimated size is not less than the actual size. + static UInt32 estimate_size(UInt32 length) { + return 2 + (length / sizeof(UInt32)); + } + + // Returns a reference to an invalid key. + static const Key &invalid_key() { + static const Key invalid_key; + return invalid_key; +// static const UInt32 invalid_key_buf[2] = { INVALID_KEY_ID << 4, 0 }; +// return *reinterpret_cast(invalid_key_buf); + } + + private: + UInt32 id_and_length_low_; + UInt8 length_high_; + UInt8 buf_[3]; + + // Disallows instantiation. + Key() : id_and_length_low_(INVALID_KEY_ID << 4), length_high_(0) {} + ~Key() {} + + // Disallows copy and assignment. + Key(const Key &); + Key &operator=(const Key &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/node.hpp b/storage/mroonga/vendor/groonga/lib/dat/node.hpp new file mode 100644 index 00000000..29febc7d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/node.hpp @@ -0,0 +1,127 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +// See base.hpp and check.hpp for details. +#include "base.hpp" +#include "check.hpp" + +namespace grn { +namespace dat { + +class GRN_DAT_API Node { + public: + Node() : base_(), check_() {} + + Base base() const { + return base_; + } + bool is_linker() const { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + return base_.is_linker(); + } + UInt32 offset() const { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + return base_.offset(); + } + UInt32 key_pos() const { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + return base_.key_pos(); + } + + Check check() const { + return check_; + } + bool is_offset() const { + return check_.is_offset(); + } + UInt32 except_is_offset() const { + return check_.except_is_offset(); + } + bool is_phantom() const { + return check_.is_phantom(); + } + UInt32 next() const { + return check_.next(); + } + UInt32 prev() const { + return check_.prev(); + } + UInt32 label() const { + return check_.label(); + } + UInt32 child() const { + return check_.child(); + } + UInt32 sibling() const { + return check_.sibling(); + } + + void set_base(Base x) { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + base_ = x; + } + void set_offset(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + base_.set_offset(x); + } + void set_key_pos(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(is_phantom()); + base_.set_key_pos(x); + } + + void set_check(Check x) { + check_ = x; + } + void set_is_offset(bool x) { + check_.set_is_offset(x); + } + void set_except_is_offset(UInt32 x) { + check_.set_except_is_offset(x); + } + void set_is_phantom(bool x) { + GRN_DAT_DEBUG_THROW_IF(base_.offset() != INVALID_OFFSET); + check_.set_is_phantom(x); + } + void set_next(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(base_.offset() != INVALID_OFFSET); + check_.set_next(x); + } + void set_prev(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(base_.offset() != INVALID_OFFSET); + check_.set_prev(x); + } + void set_label(UInt32 x) { + GRN_DAT_DEBUG_THROW_IF(offset() != INVALID_OFFSET); + check_.set_label(x); + } + void set_child(UInt32 x) { + check_.set_child(x); + } + void set_sibling(UInt32 x) { + check_.set_sibling(x); + } + + private: + Base base_; + Check check_; +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/predictive-cursor.cpp b/storage/mroonga/vendor/groonga/lib/dat/predictive-cursor.cpp new file mode 100644 index 00000000..67520305 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/predictive-cursor.cpp @@ -0,0 +1,206 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2011 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "predictive-cursor.hpp" + +#include +#include + +#include "trie.hpp" + +namespace grn { +namespace dat { + +PredictiveCursor::PredictiveCursor() + : trie_(NULL), + offset_(0), + limit_(MAX_UINT32), + flags_(PREDICTIVE_CURSOR), + buf_(), + cur_(0), + end_(0), + min_length_(0) {} + +PredictiveCursor::~PredictiveCursor() {} + +void PredictiveCursor::open(const Trie &trie, + const String &str, + UInt32 offset, + UInt32 limit, + UInt32 flags) { + GRN_DAT_THROW_IF(PARAM_ERROR, (str.ptr() == NULL) && (str.length() != 0)); + + flags = fix_flags(flags); + PredictiveCursor new_cursor(trie, offset, limit, flags); + new_cursor.init(str); + new_cursor.swap(this); +} + +void PredictiveCursor::close() { + PredictiveCursor new_cursor; + new_cursor.swap(this); +} + +const Key &PredictiveCursor::next() { + if (cur_ == end_) { + return Key::invalid_key(); + } + + if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { + return ascending_next(); + } else { + return descending_next(); + } +} + +PredictiveCursor::PredictiveCursor(const Trie &trie, + UInt32 offset, UInt32 limit, UInt32 flags) + : trie_(&trie), + offset_(offset), + limit_(limit), + flags_(flags), + buf_(), + cur_(0), + end_(0), + min_length_(0) {} + +UInt32 PredictiveCursor::fix_flags(UInt32 flags) const { + const UInt32 cursor_type = flags & CURSOR_TYPE_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) && + (cursor_type != PREDICTIVE_CURSOR)); + flags |= PREDICTIVE_CURSOR; + + const UInt32 cursor_order = flags & CURSOR_ORDER_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_order != 0) && + (cursor_order != ASCENDING_CURSOR) && + (cursor_order != DESCENDING_CURSOR)); + if (cursor_order == 0) { + flags |= ASCENDING_CURSOR; + } + + const UInt32 cursor_options = flags & CURSOR_OPTIONS_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, cursor_options & ~(EXCEPT_EXACT_MATCH)); + + return flags; +} + +void PredictiveCursor::init(const String &str) { + if (limit_ == 0) { + return; + } + + min_length_ = str.length(); + if ((flags_ & EXCEPT_EXACT_MATCH) == EXCEPT_EXACT_MATCH) { + ++min_length_; + } + end_ = (offset_ > (MAX_UINT32 - limit_)) ? MAX_UINT32 : (offset_ + limit_); + + UInt32 node_id = ROOT_NODE_ID; + for (UInt32 i = 0; i < str.length(); ++i) { + const Base base = trie_->ith_node(node_id).base(); + if (base.is_linker()) { + if (offset_ == 0) { + const Key &key = trie_->get_key(base.key_pos()); + if ((key.length() >= str.length()) && + (key.str().substr(0, str.length()).compare(str, i) == 0)) { + if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { + node_id |= IS_ROOT_FLAG; + } + buf_.push_back(node_id); + } + } + return; + } + + node_id = base.offset() ^ str[i]; + if (trie_->ith_node(node_id).label() != str[i]) { + return; + } + } + + if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { + node_id |= IS_ROOT_FLAG; + } + buf_.push_back(node_id); +} + +void PredictiveCursor::swap(PredictiveCursor *cursor) { + std::swap(trie_, cursor->trie_); + std::swap(offset_, cursor->offset_); + std::swap(limit_, cursor->limit_); + std::swap(flags_, cursor->flags_); + buf_.swap(&cursor->buf_); + std::swap(cur_, cursor->cur_); + std::swap(end_, cursor->end_); + std::swap(min_length_, cursor->min_length_); +} + +const Key &PredictiveCursor::ascending_next() { + while (!buf_.empty()) { + const bool is_root = (buf_.back() & IS_ROOT_FLAG) == IS_ROOT_FLAG; + const UInt32 node_id = buf_.back() & ~IS_ROOT_FLAG; + buf_.pop_back(); + + const Node node = trie_->ith_node(node_id); + if (!is_root && (node.sibling() != INVALID_LABEL)) { + buf_.push_back(node_id ^ node.label() ^ node.sibling()); + } + + if (node.is_linker()) { + const Key &key = trie_->get_key(node.key_pos()); + if (key.length() >= min_length_) { + if (cur_++ >= offset_) { + return key; + } + } + } else if (node.child() != INVALID_LABEL) { + buf_.push_back(node.offset() ^ node.child()); + } + } + return Key::invalid_key(); +} + +const Key &PredictiveCursor::descending_next() { + while (!buf_.empty()) { + const bool post_order = (buf_.back() & POST_ORDER_FLAG) == POST_ORDER_FLAG; + const UInt32 node_id = buf_.back() & ~POST_ORDER_FLAG; + + const Base base = trie_->ith_node(node_id).base(); + if (post_order) { + buf_.pop_back(); + if (base.is_linker()) { + const Key &key = trie_->get_key(base.key_pos()); + if (key.length() >= min_length_) { + if (cur_++ >= offset_) { + return key; + } + } + } + } else { + buf_.back() |= POST_ORDER_FLAG; + UInt16 label = trie_->ith_node(node_id).child(); + while (label != INVALID_LABEL) { + buf_.push_back(base.offset() ^ label); + label = trie_->ith_node(base.offset() ^ label).sibling(); + } + } + } + return Key::invalid_key(); +} + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/predictive-cursor.hpp b/storage/mroonga/vendor/groonga/lib/dat/predictive-cursor.hpp new file mode 100644 index 00000000..88a950b8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/predictive-cursor.hpp @@ -0,0 +1,84 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "cursor.hpp" +#include "vector.hpp" + +namespace grn { +namespace dat { + +class Trie; + +class GRN_DAT_API PredictiveCursor : public Cursor { + public: + PredictiveCursor(); + ~PredictiveCursor(); + + void open(const Trie &trie, + const String &str, + UInt32 offset = 0, + UInt32 limit = MAX_UINT32, + UInt32 flags = 0); + + void close(); + + const Key &next(); + + UInt32 offset() const { + return offset_; + } + UInt32 limit() const { + return limit_; + } + UInt32 flags() const { + return flags_; + } + + private: + const Trie *trie_; + UInt32 offset_; + UInt32 limit_; + UInt32 flags_; + + Vector buf_; + UInt32 cur_; + UInt32 end_; + UInt32 min_length_; + + PredictiveCursor(const Trie &trie, + UInt32 offset, UInt32 limit, UInt32 flags); + + UInt32 fix_flags(UInt32 flags) const; + void init(const String &str); + void swap(PredictiveCursor *cursor); + + const Key &ascending_next(); + const Key &descending_next(); + + static const UInt32 IS_ROOT_FLAG = 0x80000000U; + static const UInt32 POST_ORDER_FLAG = 0x80000000U; + + // Disallows copy and assignment. + PredictiveCursor(const PredictiveCursor &); + PredictiveCursor &operator=(const PredictiveCursor &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/prefix-cursor.cpp b/storage/mroonga/vendor/groonga/lib/dat/prefix-cursor.cpp new file mode 100644 index 00000000..83adeb37 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/prefix-cursor.cpp @@ -0,0 +1,175 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2011 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "prefix-cursor.hpp" + +#include + +#include "trie.hpp" + +namespace grn { +namespace dat { + +PrefixCursor::PrefixCursor() + : trie_(NULL), + offset_(0), + limit_(MAX_UINT32), + flags_(PREFIX_CURSOR), + buf_(), + cur_(0), + end_(0) {} + +PrefixCursor::~PrefixCursor() {} + +void PrefixCursor::open(const Trie &trie, + const String &str, + UInt32 min_length, + UInt32 offset, + UInt32 limit, + UInt32 flags) { + GRN_DAT_THROW_IF(PARAM_ERROR, (str.ptr() == NULL) && (str.length() != 0)); + GRN_DAT_THROW_IF(PARAM_ERROR, min_length > str.length()); + + flags = fix_flags(flags); + PrefixCursor new_cursor(trie, offset, limit, flags); + new_cursor.init(str, min_length); + new_cursor.swap(this); +} + +void PrefixCursor::close() { + PrefixCursor new_cursor; + new_cursor.swap(this); +} + +const Key &PrefixCursor::next() { + if (cur_ == end_) { + return Key::invalid_key(); + } + if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { + return trie_->get_key(buf_[cur_++]); + } else { + return trie_->get_key(buf_[--cur_]); + } +} + +PrefixCursor::PrefixCursor(const Trie &trie, + UInt32 offset, UInt32 limit, UInt32 flags) + : trie_(&trie), + offset_(offset), + limit_(limit), + flags_(flags), + buf_(), + cur_(0), + end_(0) {} + +UInt32 PrefixCursor::fix_flags(UInt32 flags) const { + const UInt32 cursor_type = flags & CURSOR_TYPE_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_type != 0) && + (cursor_type != PREFIX_CURSOR)); + flags |= PREFIX_CURSOR; + + const UInt32 cursor_order = flags & CURSOR_ORDER_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, (cursor_order != 0) && + (cursor_order != ASCENDING_CURSOR) && + (cursor_order != DESCENDING_CURSOR)); + if (cursor_order == 0) { + flags |= ASCENDING_CURSOR; + } + + const UInt32 cursor_options = flags & CURSOR_OPTIONS_MASK; + GRN_DAT_THROW_IF(PARAM_ERROR, cursor_options & ~EXCEPT_EXACT_MATCH); + + return flags; +} + +void PrefixCursor::init(const String &str, UInt32 min_length) { + if ((limit_ == 0) || (offset_ > (str.length() - min_length))) { + return; + } + + UInt32 node_id = ROOT_NODE_ID; + UInt32 i; + for (i = 0; i < str.length(); ++i) { + const Base base = trie_->ith_node(node_id).base(); + if (base.is_linker()) { + const Key &key = trie_->get_key(base.key_pos()); + if ((key.length() >= min_length) && (key.length() <= str.length()) && + (str.substr(0, key.length()).compare(key.str(), i) == 0) && + ((key.length() < str.length()) || + ((flags_ & EXCEPT_EXACT_MATCH) != EXCEPT_EXACT_MATCH))) { + buf_.push_back(base.key_pos()); + } + break; + } + + if ((i >= min_length) && + (trie_->ith_node(node_id).child() == TERMINAL_LABEL)) { + const Base linker_base = + trie_->ith_node(base.offset() ^ TERMINAL_LABEL).base(); + if (linker_base.is_linker()) { + buf_.push_back(linker_base.key_pos()); + } + } + + node_id = base.offset() ^ str[i]; + if (trie_->ith_node(node_id).label() != str[i]) { + break; + } + } + + if ((i == str.length()) && + ((flags_ & EXCEPT_EXACT_MATCH) != EXCEPT_EXACT_MATCH)) { + const Base base = trie_->ith_node(node_id).base(); + if (base.is_linker()) { + const Key &key = trie_->get_key(base.key_pos()); + if ((key.length() >= min_length) && (key.length() <= str.length())) { + buf_.push_back(base.key_pos()); + } + } else if (trie_->ith_node(node_id).child() == TERMINAL_LABEL) { + const Base linker_base = + trie_->ith_node(base.offset() ^ TERMINAL_LABEL).base(); + if (linker_base.is_linker()) { + buf_.push_back(linker_base.key_pos()); + } + } + } + + if (buf_.size() <= offset_) { + return; + } + + if ((flags_ & ASCENDING_CURSOR) == ASCENDING_CURSOR) { + cur_ = offset_; + end_ = (limit_ < (buf_.size() - cur_)) ? (cur_ + limit_) : buf_.size(); + } else { + cur_ = buf_.size() - offset_; + end_ = (limit_ < cur_) ? (cur_ - limit_) : 0; + } +} + +void PrefixCursor::swap(PrefixCursor *cursor) { + std::swap(trie_, cursor->trie_); + std::swap(offset_, cursor->offset_); + std::swap(limit_, cursor->limit_); + std::swap(flags_, cursor->flags_); + buf_.swap(&cursor->buf_); + std::swap(cur_, cursor->cur_); + std::swap(end_, cursor->end_); +} + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/prefix-cursor.hpp b/storage/mroonga/vendor/groonga/lib/dat/prefix-cursor.hpp new file mode 100644 index 00000000..07a59186 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/prefix-cursor.hpp @@ -0,0 +1,78 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "cursor.hpp" +#include "vector.hpp" + +namespace grn { +namespace dat { + +class Trie; + +class GRN_DAT_API PrefixCursor : public Cursor { + public: + PrefixCursor(); + ~PrefixCursor(); + + void open(const Trie &trie, + const String &str, + UInt32 min_length = 0, + UInt32 offset = 0, + UInt32 limit = MAX_UINT32, + UInt32 flags = 0); + + void close(); + + const Key &next(); + + UInt32 offset() const { + return offset_; + } + UInt32 limit() const { + return limit_; + } + UInt32 flags() const { + return flags_; + } + + private: + const Trie *trie_; + UInt32 offset_; + UInt32 limit_; + UInt32 flags_; + + Vector buf_; + UInt32 cur_; + UInt32 end_; + + PrefixCursor(const Trie &trie, + UInt32 offset, UInt32 limit, UInt32 flags); + + UInt32 fix_flags(UInt32 flags) const; + void init(const String &str, UInt32 min_length); + void swap(PrefixCursor *cursor); + + // Disallows copy and assignment. + PrefixCursor(const PrefixCursor &); + PrefixCursor &operator=(const PrefixCursor &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/sources.am b/storage/mroonga/vendor/groonga/lib/dat/sources.am new file mode 100644 index 00000000..26c9f09f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/sources.am @@ -0,0 +1,29 @@ +libgrndat_la_SOURCES = \ + cursor-factory.cpp \ + file-impl.cpp \ + file.cpp \ + id-cursor.cpp \ + key-cursor.cpp \ + predictive-cursor.cpp \ + prefix-cursor.cpp \ + trie.cpp \ + array.hpp \ + base.hpp \ + block.hpp \ + check.hpp \ + cursor-factory.hpp \ + cursor.hpp \ + dat.hpp \ + entry.hpp \ + file-impl.hpp \ + file.hpp \ + header.hpp \ + id-cursor.hpp \ + key-cursor.hpp \ + key.hpp \ + node.hpp \ + predictive-cursor.hpp \ + prefix-cursor.hpp \ + string.hpp \ + trie.hpp \ + vector.hpp diff --git a/storage/mroonga/vendor/groonga/lib/dat/string.hpp b/storage/mroonga/vendor/groonga/lib/dat/string.hpp new file mode 100644 index 00000000..aead21ca --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/string.hpp @@ -0,0 +1,173 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "dat.hpp" + +namespace grn { +namespace dat { + +class GRN_DAT_API String { + public: + String() + : ptr_(NULL), + length_(0) {} + String(const void *ptr, UInt32 length) + : ptr_(static_cast(ptr)), + length_(length) {} + template + explicit String(const char (&str)[T]) + : ptr_(reinterpret_cast(str)), + length_(T - 1) {} + String(const String &rhs) + : ptr_(rhs.ptr_), + length_(rhs.length_) {} + + String &operator=(const String &rhs) { + set_ptr(rhs.ptr()); + set_length(rhs.length()); + return *this; + } + + const UInt8 &operator[](UInt32 i) const { + GRN_DAT_DEBUG_THROW_IF(i >= length_); + return ptr_[i]; + } + + const void *ptr() const { + return ptr_; + } + UInt32 length() const { + return length_; + } + + void set_ptr(const void *x) { + ptr_ = static_cast(x); + } + void set_length(UInt32 x) { + length_ = x; + } + + void assign(const void *ptr, UInt32 length) { + set_ptr(ptr); + set_length(length); + } + + String substr(UInt32 offset = 0) const { + return String(ptr_ + offset, length_ - offset); + } + String substr(UInt32 offset, UInt32 length) const { + return String(ptr_ + offset, length); + } + + // This function returns an integer as follows: + // - a negative value if *this < rhs, + // - zero if *this == rhs, + // - a positive value if *this > rhs, + // but if the offset is too large, the result is undefined. + int compare(const String &rhs, UInt32 offset = 0) const { + GRN_DAT_DEBUG_THROW_IF(offset > length()); + GRN_DAT_DEBUG_THROW_IF(offset > rhs.length()); + + for (UInt32 i = offset; i < length(); ++i) { + if (i >= rhs.length()) { + return 1; + } else if ((*this)[i] != rhs[i]) { + return (*this)[i] - rhs[i]; + } + } + return (length() == rhs.length()) ? 0 : -1; + } + + bool starts_with(const String &str) const { + if (length() < str.length()) { + return false; + } + for (UInt32 i = 0; i < str.length(); ++i) { + if ((*this)[i] != str[i]) { + return false; + } + } + return true; + } + + bool ends_with(const String &str) const { + if (length() < str.length()) { + return false; + } + UInt32 offset = length() - str.length(); + for (UInt32 i = 0; i < str.length(); ++i) { + if ((*this)[offset + i] != str[i]) { + return false; + } + } + return true; + } + + void swap(String *rhs) { + const UInt8 * const ptr_temp = ptr_; + ptr_ = rhs->ptr_; + rhs->ptr_ = ptr_temp; + + const UInt32 length_temp = length_; + length_ = rhs->length_; + rhs->length_ = length_temp; + } + + private: + const UInt8 *ptr_; + UInt32 length_; +}; + +inline bool operator==(const String &lhs, const String &rhs) { + if (lhs.length() != rhs.length()) { + return false; + } else if (lhs.ptr() == rhs.ptr()) { + return true; + } + for (UInt32 i = 0; i < lhs.length(); ++i) { + if (lhs[i] != rhs[i]) { + return false; + } + } + return true; +} + +inline bool operator!=(const String &lhs, const String &rhs) { + return !(lhs == rhs); +} + +inline bool operator<(const String &lhs, const String &rhs) { + return lhs.compare(rhs) < 0; +} + +inline bool operator>(const String &lhs, const String &rhs) { + return rhs < lhs; +} + +inline bool operator<=(const String &lhs, const String &rhs) { + return !(lhs > rhs); +} + +inline bool operator>=(const String &lhs, const String &rhs) { + return !(lhs < rhs); +} + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/trie.cpp b/storage/mroonga/vendor/groonga/lib/dat/trie.cpp new file mode 100644 index 00000000..b2c6a84f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/trie.cpp @@ -0,0 +1,1225 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2011-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "trie.hpp" + +#include +#include + +#include "vector.hpp" + +namespace grn { +namespace dat { +namespace { + +class StatusFlagManager { + public: + StatusFlagManager(Header *header, UInt32 status_flag) + : header_(header), status_flag_(status_flag) { + header_->set_status_flags(header_->status_flags() | status_flag_); + } + ~StatusFlagManager() { + header_->set_status_flags(header_->status_flags() & ~status_flag_); + } + + private: + Header *header_; + UInt32 status_flag_; + + // Disallows copy and assignment. + StatusFlagManager(const StatusFlagManager &); + StatusFlagManager &operator=(const StatusFlagManager &); +}; + +} // namespace + +Trie::Trie() + : file_(), + header_(NULL), + nodes_(), + blocks_(), + entries_(), + key_buf_() {} + +Trie::~Trie() {} + +void Trie::create(const char *file_name, + UInt64 file_size, + UInt32 max_num_keys, + double num_nodes_per_key, + double average_key_length) { + GRN_DAT_THROW_IF(PARAM_ERROR, (file_size != 0) && (max_num_keys != 0)); + + if (num_nodes_per_key < 1.0) { + num_nodes_per_key = DEFAULT_NUM_NODES_PER_KEY; + } + if (num_nodes_per_key > MAX_NUM_NODES_PER_KEY) { + num_nodes_per_key = MAX_NUM_NODES_PER_KEY; + } + GRN_DAT_THROW_IF(PARAM_ERROR, num_nodes_per_key < 1.0); + GRN_DAT_THROW_IF(PARAM_ERROR, num_nodes_per_key > MAX_NUM_NODES_PER_KEY); + + if (average_key_length < 1.0) { + average_key_length = DEFAULT_AVERAGE_KEY_LENGTH; + } + GRN_DAT_THROW_IF(PARAM_ERROR, average_key_length < 1.0); + GRN_DAT_THROW_IF(PARAM_ERROR, average_key_length > MAX_KEY_LENGTH); + + if (max_num_keys == 0) { + if (file_size == 0) { + file_size = DEFAULT_FILE_SIZE; + } else { + GRN_DAT_THROW_IF(PARAM_ERROR, file_size < MIN_FILE_SIZE); + GRN_DAT_THROW_IF(PARAM_ERROR, file_size > MAX_FILE_SIZE); + } + } else { + GRN_DAT_THROW_IF(PARAM_ERROR, max_num_keys > MAX_NUM_KEYS); + } + + Trie new_trie; + new_trie.create_file(file_name, file_size, max_num_keys, + num_nodes_per_key, average_key_length); + new_trie.swap(this); +} + +void Trie::create(const Trie &trie, + const char *file_name, + UInt64 file_size, + UInt32 max_num_keys, + double num_nodes_per_key, + double average_key_length) { + GRN_DAT_THROW_IF(PARAM_ERROR, (file_size != 0) && (max_num_keys != 0)); + + if (num_nodes_per_key < 1.0) { + if (trie.num_keys() == 0) { + num_nodes_per_key = DEFAULT_NUM_NODES_PER_KEY; + } else { + num_nodes_per_key = 1.0 * trie.num_nodes() / trie.num_keys(); + if (num_nodes_per_key > MAX_NUM_NODES_PER_KEY) { + num_nodes_per_key = MAX_NUM_NODES_PER_KEY; + } + } + } + GRN_DAT_THROW_IF(PARAM_ERROR, num_nodes_per_key < 1.0); + GRN_DAT_THROW_IF(PARAM_ERROR, num_nodes_per_key > MAX_NUM_NODES_PER_KEY); + + if (average_key_length < 1.0) { + if (trie.num_keys() == 0) { + average_key_length = DEFAULT_AVERAGE_KEY_LENGTH; + } else { + average_key_length = 1.0 * trie.total_key_length() / trie.num_keys(); + } + } + GRN_DAT_THROW_IF(PARAM_ERROR, average_key_length < 1.0); + GRN_DAT_THROW_IF(PARAM_ERROR, average_key_length > MAX_KEY_LENGTH); + + if (max_num_keys == 0) { + if (file_size == 0) { + file_size = trie.file_size(); + } + GRN_DAT_THROW_IF(PARAM_ERROR, file_size < MIN_FILE_SIZE); + GRN_DAT_THROW_IF(PARAM_ERROR, file_size > MAX_FILE_SIZE); + GRN_DAT_THROW_IF(PARAM_ERROR, file_size < trie.virtual_size()); + } else { + GRN_DAT_THROW_IF(PARAM_ERROR, max_num_keys < trie.num_keys()); + GRN_DAT_THROW_IF(PARAM_ERROR, max_num_keys < trie.max_key_id()); + GRN_DAT_THROW_IF(PARAM_ERROR, max_num_keys > MAX_NUM_KEYS); + } + + Trie new_trie; + new_trie.create_file(file_name, file_size, max_num_keys, + num_nodes_per_key, average_key_length); + new_trie.build_from_trie(trie); + new_trie.swap(this); +} + +void Trie::repair(const Trie &trie, const char *file_name) { + Trie new_trie; + new_trie.create_file(file_name, trie.file_size(), trie.max_num_keys(), + trie.max_num_blocks(), trie.key_buf_size()); + new_trie.repair_trie(trie); + new_trie.swap(this); +} + +void Trie::open(const char *file_name) { + GRN_DAT_THROW_IF(PARAM_ERROR, file_name == NULL); + + Trie new_trie; + new_trie.open_file(file_name); + new_trie.swap(this); +} + +void Trie::close() { + Trie().swap(this); +} + +void Trie::swap(Trie *trie) { + file_.swap(&trie->file_); + std::swap(header_, trie->header_); + nodes_.swap(&trie->nodes_); + blocks_.swap(&trie->blocks_); + entries_.swap(&trie->entries_); + key_buf_.swap(&trie->key_buf_); +} + +void Trie::flush() { + file_.flush(); +} + +void Trie::create_file(const char *file_name, + UInt64 file_size, + UInt32 max_num_keys, + double num_nodes_per_key, + double average_key_length) { + GRN_DAT_THROW_IF(PARAM_ERROR, (file_size == 0) && (max_num_keys == 0)); + GRN_DAT_THROW_IF(PARAM_ERROR, (file_size != 0) && (max_num_keys != 0)); + if (max_num_keys == 0) { + const UInt64 avail = file_size - sizeof(Header); + const double num_bytes_per_key = (sizeof(Node) * num_nodes_per_key) + + (1.0 * sizeof(Block) / BLOCK_SIZE * num_nodes_per_key) + + sizeof(Entry) + + sizeof(UInt32) + sizeof(UInt8) + average_key_length + 1.5; + if ((avail / num_bytes_per_key) > MAX_NUM_KEYS) { + max_num_keys = MAX_NUM_KEYS; + } else { + max_num_keys = (UInt32)(avail / num_bytes_per_key); + } + GRN_DAT_THROW_IF(PARAM_ERROR, max_num_keys == 0); + } + + UInt32 max_num_blocks; + { + const double max_num_nodes = num_nodes_per_key * max_num_keys; + GRN_DAT_THROW_IF(PARAM_ERROR, (max_num_nodes - 1.0) >= MAX_NUM_NODES); + max_num_blocks = ((UInt32)max_num_nodes + BLOCK_SIZE - 1) / BLOCK_SIZE; + GRN_DAT_THROW_IF(PARAM_ERROR, max_num_blocks == 0); + GRN_DAT_THROW_IF(PARAM_ERROR, max_num_blocks > MAX_NUM_BLOCKS); + } + + UInt32 key_buf_size; + if (file_size == 0) { + const double total_key_length = average_key_length * max_num_keys; + GRN_DAT_THROW_IF(PARAM_ERROR, + (total_key_length - 1.0) >= MAX_TOTAL_KEY_LENGTH); + + // The last term is the estimated number of bytes that will be used for + // 32-bit alignment. + const UInt64 total_num_bytes = (UInt64)(total_key_length) + + (UInt64)(sizeof(UInt32) + sizeof(UInt8)) * max_num_keys + + (UInt32)(max_num_keys * 1.5); + GRN_DAT_THROW_IF(PARAM_ERROR, + (total_num_bytes / sizeof(UInt32)) >= MAX_KEY_BUF_SIZE); + key_buf_size = (UInt32)(total_num_bytes / sizeof(UInt32)); + + file_size = sizeof(Header) + + (sizeof(Block) * max_num_blocks) + + (sizeof(Node) * BLOCK_SIZE * max_num_blocks) + + (sizeof(Entry) * max_num_keys) + + (sizeof(UInt32) * key_buf_size); + } else { + const UInt64 avail = file_size - sizeof(Header) + - (sizeof(Block) * max_num_blocks) + - (sizeof(Node) * BLOCK_SIZE * max_num_blocks) + - (sizeof(Entry) * max_num_keys); + GRN_DAT_THROW_IF(PARAM_ERROR, (avail / sizeof(UInt32)) > MAX_KEY_BUF_SIZE); + key_buf_size = (UInt32)(avail / sizeof(UInt32)); + } + + create_file(file_name, file_size, max_num_keys, + max_num_blocks, key_buf_size); +} + +void Trie::create_file(const char *file_name, + UInt64 file_size, + UInt32 max_num_keys, + UInt32 max_num_blocks, + UInt32 key_buf_size) { + GRN_DAT_THROW_IF(PARAM_ERROR, file_size < (sizeof(Header) + + (sizeof(Block) * max_num_blocks) + + (sizeof(Node) * BLOCK_SIZE * max_num_blocks) + + (sizeof(Entry) * max_num_keys) + + (sizeof(UInt32) * key_buf_size))); + + file_.create(file_name, file_size); + + Header * const header = static_cast
(file_.ptr()); + *header = Header(); + header->set_file_size(file_size); + header->set_max_num_keys(max_num_keys); + header->set_max_num_blocks(max_num_blocks); + header->set_key_buf_size(key_buf_size); + + map_address(file_.ptr()); + + reserve_node(ROOT_NODE_ID); + ith_node(INVALID_OFFSET).set_is_offset(true); +} + +void Trie::open_file(const char *file_name) { + GRN_DAT_THROW_IF(PARAM_ERROR, file_name == NULL); + + file_.open(file_name); + map_address(file_.ptr()); + GRN_DAT_THROW_IF(FORMAT_ERROR, file_size() != file_.size()); +} + +void Trie::map_address(void *address) { + GRN_DAT_THROW_IF(PARAM_ERROR, address == NULL); + + header_ = static_cast
(address); + nodes_.assign(header_ + 1, max_num_nodes()); + blocks_.assign(nodes_.end(), max_num_blocks()); + entries_.assign(reinterpret_cast(blocks_.end()) - 1, + max_num_keys() + 1); + key_buf_.assign(entries_.end(), key_buf_size()); + + GRN_DAT_THROW_IF(UNEXPECTED_ERROR, static_cast(key_buf_.end()) + > static_cast(static_cast(address) + file_size())); +} + +void Trie::build_from_trie(const Trie &trie) { + GRN_DAT_THROW_IF(SIZE_ERROR, max_num_keys() < trie.num_keys()); + GRN_DAT_THROW_IF(SIZE_ERROR, max_num_keys() < trie.max_key_id()); + + header_->set_total_key_length(trie.total_key_length()); + header_->set_num_keys(trie.num_keys()); + header_->set_max_key_id(trie.max_key_id()); + header_->set_next_key_id(trie.next_key_id()); + for (UInt32 i = min_key_id(); i <= max_key_id(); ++i) { + ith_entry(i) = trie.ith_entry(i); + } + build_from_trie(trie, ROOT_NODE_ID, ROOT_NODE_ID); +} + +void Trie::build_from_trie(const Trie &trie, UInt32 src, UInt32 dest) { + // Keys are sorted in lexicographic order. + if (trie.ith_node(src).is_linker()) { + const Key &key = trie.get_key(trie.ith_node(src).key_pos()); + Key::create(key_buf_.ptr() + next_key_pos(), + key.id(), key.ptr(), key.length()); + ith_node(dest).set_key_pos(next_key_pos()); + ith_entry(key.id()).set_key_pos(next_key_pos()); + header_->set_next_key_pos( + next_key_pos() + Key::estimate_size(key.length())); + return; + } + + const UInt32 src_offset = trie.ith_node(src).offset(); + UInt32 dest_offset; + { + UInt16 labels[MAX_LABEL + 1]; + UInt32 num_labels = 0; + + UInt32 label = trie.ith_node(src).child(); + while (label != INVALID_LABEL) { + GRN_DAT_DEBUG_THROW_IF(label > MAX_LABEL); + const UInt32 child = src_offset ^ label; + if (trie.ith_node(child).is_linker() || + (trie.ith_node(child).child() != INVALID_LABEL)) { + labels[num_labels++] = label; + } + label = trie.ith_node(child).sibling(); + } + if (num_labels == 0) { + return; + } + + dest_offset = find_offset(labels, num_labels); + for (UInt32 i = 0; i < num_labels; ++i) { + const UInt32 child = dest_offset ^ labels[i]; + reserve_node(child); + ith_node(child).set_label(labels[i]); + if ((i + 1) < num_labels) { + ith_node(child).set_sibling(labels[i + 1]); + } + } + + GRN_DAT_DEBUG_THROW_IF(ith_node(dest_offset).is_offset()); + ith_node(dest_offset).set_is_offset(true); + ith_node(dest).set_offset(dest_offset); + ith_node(dest).set_child(labels[0]); + } + + UInt32 label = ith_node(dest).child(); + while (label != INVALID_LABEL) { + build_from_trie(trie, src_offset ^ label, dest_offset ^ label); + label = ith_node(dest_offset ^ label).sibling(); + } +} + +void Trie::repair_trie(const Trie &trie) { + Vector valid_ids; + header_->set_max_key_id(trie.max_key_id()); + header_->set_next_key_id(trie.max_key_id() + 1); + UInt32 prev_invalid_key_id = INVALID_KEY_ID; + for (UInt32 i = min_key_id(); i <= max_key_id(); ++i) { + const Entry &entry = trie.ith_entry(i); + if (entry.is_valid()) { + valid_ids.push_back(i); + ith_entry(i) = entry; + const Key &key = trie.get_key(entry.key_pos()); + Key::create(key_buf_.ptr() + next_key_pos(), + key.id(), key.ptr(), key.length()); + ith_entry(i).set_key_pos(next_key_pos()); + header_->set_next_key_pos( + next_key_pos() + Key::estimate_size(key.length())); + header_->set_total_key_length( + total_key_length() + key.length()); + header_->set_num_keys(num_keys() + 1); + } else { + if (prev_invalid_key_id == INVALID_KEY_ID) { + header_->set_next_key_id(i); + } else { + ith_entry(prev_invalid_key_id).set_next(i); + } + prev_invalid_key_id = i; + } + } + if (prev_invalid_key_id != INVALID_KEY_ID) { + ith_entry(prev_invalid_key_id).set_next(max_key_id() + 1); + } + mkq_sort(valid_ids.begin(), valid_ids.end(), 0); + build_from_keys(valid_ids.begin(), valid_ids.end(), 0, ROOT_NODE_ID); +} + +void Trie::build_from_keys(const UInt32 *begin, const UInt32 *end, + UInt32 depth, UInt32 node_id) { + if ((end - begin) == 1) { + ith_node(node_id).set_key_pos(ith_entry(*begin).key_pos()); + return; + } + + UInt32 offset; + { + UInt16 labels[MAX_LABEL + 2]; + UInt32 num_labels = 0; + + const UInt32 *it = begin; + if (ith_key(*it).length() == depth) { + labels[num_labels++] = TERMINAL_LABEL; + ++it; + } + + labels[num_labels++] = (UInt8)ith_key(*it)[depth]; + for (++it; it < end; ++it) { + const Key &key = ith_key(*it); + if ((UInt8)key[depth] != labels[num_labels - 1]) { + labels[num_labels++] = (UInt8)key[depth]; + } + } + labels[num_labels] = INVALID_LABEL; + + offset = find_offset(labels, num_labels); + ith_node(node_id).set_child(labels[0]); + for (UInt32 i = 0; i < num_labels; ++i) { + const UInt32 next = offset ^ labels[i]; + reserve_node(next); + ith_node(next).set_label(labels[i]); + ith_node(next).set_sibling(labels[i + 1]); + } + + if (offset >= num_nodes()) { + reserve_block(num_blocks()); + } + ith_node(offset).set_is_offset(true); + ith_node(node_id).set_offset(offset); + } + + if (ith_key(*begin).length() == depth) { + build_from_keys(begin, begin + 1, depth + 1, offset ^ TERMINAL_LABEL); + ++begin; + } + + UInt16 label = ith_key(*begin)[depth]; + for (const UInt32 *it = begin + 1; it < end; ++it) { + const Key &key = ith_key(*it); + if ((UInt8)key[depth] != label) { + build_from_keys(begin, it, depth + 1, offset ^ label); + label = (UInt8)key[depth]; + begin = it; + } + } + build_from_keys(begin, end, depth + 1, offset ^ label); +} + +void Trie::mkq_sort(UInt32 *l, UInt32 *r, UInt32 depth) { + while ((r - l) >= MKQ_SORT_THRESHOLD) { + UInt32 *pl = l; + UInt32 *pr = r; + UInt32 *pivot_l = l; + UInt32 *pivot_r = r; + + const int pivot = get_median(*l, *(l + (r - l) / 2), *(r - 1), depth); + for ( ; ; ) { + while (pl < pr) { + const int label = get_label(*pl, depth); + if (label > pivot) { + break; + } else if (label == pivot) { + swap_ids(pl, pivot_l); + ++pivot_l; + } + ++pl; + } + while (pl < pr) { + const int label = get_label(*--pr, depth); + if (label < pivot) { + break; + } else if (label == pivot) { + swap_ids(pr, --pivot_r); + } + } + if (pl >= pr) { + break; + } + swap_ids(pl, pr); + ++pl; + } + while (pivot_l > l) { + swap_ids(--pivot_l, --pl); + } + while (pivot_r < r) { + swap_ids(pivot_r, pr); + ++pivot_r; + ++pr; + } + + if (((pl - l) > (pr - pl)) || ((r - pr) > (pr - pl))) { + if ((pr - pl) > 1) { + mkq_sort(pl, pr, depth + 1); + } + + if ((pl - l) < (r - pr)) { + if ((pl - l) > 1) { + mkq_sort(l, pl, depth); + } + l = pr; + } else { + if ((r - pr) > 1) { + mkq_sort(pr, r, depth); + } + r = pl; + } + } else { + if ((pl - l) > 1) { + mkq_sort(l, pl, depth); + } + + if ((r - pr) > 1) { + mkq_sort(pr, r, depth); + } + + l = pl, r = pr; + if ((pr - pl) > 1) { + ++depth; + } + } + } + + if ((r - l) > 1) { + insertion_sort(l, r, depth); + } +} + +void Trie::insertion_sort(UInt32 *l, UInt32 *r, UInt32 depth) { + for (UInt32 *i = l + 1; i < r; ++i) { + for (UInt32 *j = i; j > l; --j) { + if (less_than(*(j - 1), *j, depth)) { + break; + } + swap_ids(j - 1, j); + } + } +} + +int Trie::get_median(UInt32 a, UInt32 b, UInt32 c, UInt32 depth) const { + const int x = get_label(a, depth); + const int y = get_label(b, depth); + const int z = get_label(c, depth); + if (x < y) { + if (y < z) { + return y; + } else if (x < z) { + return z; + } + return x; + } else if (x < z) { + return x; + } else if (y < z) { + return z; + } + return y; +} + +int Trie::get_label(UInt32 key_id, UInt32 depth) const { + const Key &key = ith_key(key_id); + if (depth == key.length()) { + return -1; + } else { + return (UInt8)key[depth]; + } +} + +bool Trie::less_than(UInt32 lhs, UInt32 rhs, UInt32 depth) const { + const Key &lhs_key = ith_key(lhs); + const Key &rhs_key = ith_key(rhs); + const UInt32 length = (lhs_key.length() < rhs_key.length()) ? + lhs_key.length() : rhs_key.length(); + for (UInt32 i = depth; i < length; ++i) { + if (lhs_key[i] != rhs_key[i]) { + return (UInt8)lhs_key[i] < (UInt8)rhs_key[i]; + } + } + return lhs_key.length() < rhs_key.length(); +} + +void Trie::swap_ids(UInt32 *lhs, UInt32 *rhs) { + UInt32 temp = *lhs; + *lhs = *rhs; + *rhs = temp; +} + +bool Trie::search_key(const UInt8 *ptr, UInt32 length, UInt32 *key_pos) const { + GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0)); + + UInt32 node_id = ROOT_NODE_ID; + UInt32 query_pos = 0; + if (!search_linker(ptr, length, node_id, query_pos)) { + return false; + } + + const Base base = ith_node(node_id).base(); + if (!base.is_linker()) { + return false; + } + + if (get_key(base.key_pos()).equals_to(ptr, length, query_pos)) { + if (key_pos != NULL) { + *key_pos = base.key_pos(); + } + return true; + } + return false; +} + +bool Trie::search_linker(const UInt8 *ptr, UInt32 length, + UInt32 &node_id, UInt32 &query_pos) const { + GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0)); + + for ( ; query_pos < length; ++query_pos) { + const Base base = ith_node(node_id).base(); + if (base.is_linker()) { + return true; + } + + const UInt32 next = base.offset() ^ ptr[query_pos]; + if (ith_node(next).label() != ptr[query_pos]) { + return false; + } + node_id = next; + } + + const Base base = ith_node(node_id).base(); + if (base.is_linker()) { + return true; + } + + const UInt32 next = base.offset() ^ TERMINAL_LABEL; + if (ith_node(next).label() != TERMINAL_LABEL) { + return false; + } + node_id = next; + return ith_node(next).is_linker(); +} + +bool Trie::lcp_search_key(const UInt8 *ptr, UInt32 length, + UInt32 *key_pos) const { + GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0)); + + bool found = false; + UInt32 node_id = ROOT_NODE_ID; + UInt32 query_pos = 0; + + for ( ; query_pos < length; ++query_pos) { + const Base base = ith_node(node_id).base(); + if (base.is_linker()) { + const Key &key = get_key(base.key_pos()); + if ((key.length() <= length) && + key.equals_to(ptr, key.length(), query_pos)) { + if (key_pos != NULL) { + *key_pos = base.key_pos(); + } + found = true; + } + return found; + } + + if (ith_node(node_id).child() == TERMINAL_LABEL) { + const Base linker_base = + ith_node(base.offset() ^ TERMINAL_LABEL).base(); + if (linker_base.is_linker()) { + if (key_pos != NULL) { + *key_pos = linker_base.key_pos(); + } + found = true; + } + } + + node_id = base.offset() ^ ptr[query_pos]; + if (ith_node(node_id).label() != ptr[query_pos]) { + return found; + } + } + + const Base base = ith_node(node_id).base(); + if (base.is_linker()) { + const Key &key = get_key(base.key_pos()); + if (key.length() <= length) { + if (key_pos != NULL) { + *key_pos = base.key_pos(); + } + found = true; + } + } else if (ith_node(node_id).child() == TERMINAL_LABEL) { + const Base linker_base = ith_node(base.offset() ^ TERMINAL_LABEL).base(); + if (linker_base.is_linker()) { + if (key_pos != NULL) { + *key_pos = linker_base.key_pos(); + } + found = true; + } + } + return found; +} + +bool Trie::remove_key(const UInt8 *ptr, UInt32 length) { + GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0); + StatusFlagManager status_flag_manager(header_, REMOVING_FLAG); + + GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0)); + + UInt32 node_id = ROOT_NODE_ID; + UInt32 query_pos = 0; + if (!search_linker(ptr, length, node_id, query_pos)) { + return false; + } + + const UInt32 key_pos = ith_node(node_id).key_pos(); + if (!get_key(key_pos).equals_to(ptr, length, query_pos)) { + return false; + } + + const UInt32 key_id = get_key(key_pos).id(); + ith_node(node_id).set_offset(INVALID_OFFSET); + ith_entry(key_id).set_next(next_key_id()); + + header_->set_next_key_id(key_id); + header_->set_total_key_length(total_key_length() - length); + header_->set_num_keys(num_keys() - 1); + return true; +} + +bool Trie::insert_key(const UInt8 *ptr, UInt32 length, UInt32 *key_pos) { + GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0); + StatusFlagManager status_flag_manager(header_, INSERTING_FLAG); + + GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0)); + + UInt32 node_id = ROOT_NODE_ID; + UInt32 query_pos = 0; + + search_linker(ptr, length, node_id, query_pos); + if (!insert_linker(ptr, length, node_id, query_pos)) { + if (key_pos != NULL) { + *key_pos = ith_node(node_id).key_pos(); + } + return false; + } + + const UInt32 new_key_id = next_key_id(); + const UInt32 new_key_pos = append_key(ptr, length, new_key_id); + + header_->set_total_key_length(total_key_length() + length); + header_->set_num_keys(num_keys() + 1); + if (new_key_id > max_key_id()) { + header_->set_max_key_id(new_key_id); + header_->set_next_key_id(new_key_id + 1); + } else { + header_->set_next_key_id(ith_entry(new_key_id).next()); + } + + ith_entry(new_key_id).set_key_pos(new_key_pos); + ith_node(node_id).set_key_pos(new_key_pos); + if (key_pos != NULL) { + *key_pos = new_key_pos; + } + return true; +} + +bool Trie::insert_linker(const UInt8 *ptr, UInt32 length, + UInt32 &node_id, UInt32 query_pos) { + if (ith_node(node_id).is_linker()) { + const Key &key = get_key(ith_node(node_id).key_pos()); + UInt32 i = query_pos; + while ((i < length) && (i < key.length())) { + if (ptr[i] != key[i]) { + break; + } + ++i; + } + if ((i == length) && (i == key.length())) { + return false; + } + GRN_DAT_THROW_IF(SIZE_ERROR, num_keys() >= max_num_keys()); + GRN_DAT_DEBUG_THROW_IF(next_key_id() > max_num_keys()); + + for (UInt32 j = query_pos; j < i; ++j) { + node_id = insert_node(node_id, ptr[j]); + } + node_id = separate(ptr, length, node_id, i); + return true; + } else if (ith_node(node_id).label() == TERMINAL_LABEL) { + return true; + } else { + GRN_DAT_THROW_IF(SIZE_ERROR, num_keys() >= max_num_keys()); + const UInt16 label = (query_pos < length) ? + (UInt16)ptr[query_pos] : (UInt16)TERMINAL_LABEL; + const Base base = ith_node(node_id).base(); + if ((base.offset() == INVALID_OFFSET) || + !ith_node(base.offset() ^ label).is_phantom()) { + resolve(node_id, label); + } + node_id = insert_node(node_id, label); + return true; + } +} + +bool Trie::update_key(const Key &key, const UInt8 *ptr, UInt32 length, + UInt32 *key_pos) { + GRN_DAT_THROW_IF(STATUS_ERROR, (status_flags() & CHANGING_MASK) != 0); + StatusFlagManager status_flag_manager(header_, UPDATING_FLAG); + + GRN_DAT_DEBUG_THROW_IF((ptr == NULL) && (length != 0)); + + if (!key.is_valid()) { + return false; + } + + UInt32 node_id = ROOT_NODE_ID; + UInt32 query_pos = 0; + + search_linker(ptr, length, node_id, query_pos); + if (!insert_linker(ptr, length, node_id, query_pos)) { + if (key_pos != NULL) { + *key_pos = ith_node(node_id).key_pos(); + } + return false; + } + + const UInt32 new_key_pos = append_key(ptr, length, key.id()); + header_->set_total_key_length(total_key_length() + length - key.length()); + ith_entry(key.id()).set_key_pos(new_key_pos); + ith_node(node_id).set_key_pos(new_key_pos); + if (key_pos != NULL) { + *key_pos = new_key_pos; + } + + node_id = ROOT_NODE_ID; + query_pos = 0; + GRN_DAT_THROW_IF(UNEXPECTED_ERROR, + !search_linker(static_cast(key.ptr()), key.length(), + node_id, query_pos)); + ith_node(node_id).set_offset(INVALID_OFFSET); + return true; +} + +UInt32 Trie::insert_node(UInt32 node_id, UInt16 label) { + GRN_DAT_DEBUG_THROW_IF(node_id >= num_nodes()); + GRN_DAT_DEBUG_THROW_IF(label > MAX_LABEL); + + const Base base = ith_node(node_id).base(); + UInt32 offset; + if (base.is_linker() || (base.offset() == INVALID_OFFSET)) { + offset = find_offset(&label, 1); + } else { + offset = base.offset(); + } + + const UInt32 next = offset ^ label; + reserve_node(next); + + ith_node(next).set_label(label); + if (base.is_linker()) { + GRN_DAT_DEBUG_THROW_IF(ith_node(offset).is_offset()); + ith_node(offset).set_is_offset(true); + ith_node(next).set_key_pos(base.key_pos()); + } else if (base.offset() == INVALID_OFFSET) { + GRN_DAT_DEBUG_THROW_IF(ith_node(offset).is_offset()); + ith_node(offset).set_is_offset(true); + } else { + GRN_DAT_DEBUG_THROW_IF(!ith_node(offset).is_offset()); + } + ith_node(node_id).set_offset(offset); + + const UInt32 child_label = ith_node(node_id).child(); + GRN_DAT_DEBUG_THROW_IF(child_label == label); + if (child_label == INVALID_LABEL) { + ith_node(node_id).set_child(label); + } else if ((label == TERMINAL_LABEL) || + ((child_label != TERMINAL_LABEL) && (label < child_label))) { + GRN_DAT_DEBUG_THROW_IF(ith_node(offset ^ child_label).is_phantom()); + GRN_DAT_DEBUG_THROW_IF(ith_node(offset ^ child_label).label() != child_label); + ith_node(next).set_sibling(child_label); + ith_node(node_id).set_child(label); + } else { + UInt32 prev = offset ^ child_label; + GRN_DAT_DEBUG_THROW_IF(ith_node(prev).label() != child_label); + UInt32 sibling_label = ith_node(prev).sibling(); + while (label > sibling_label) { + prev = offset ^ sibling_label; + GRN_DAT_DEBUG_THROW_IF(ith_node(prev).label() != sibling_label); + sibling_label = ith_node(prev).sibling(); + } + GRN_DAT_DEBUG_THROW_IF(label == sibling_label); + ith_node(next).set_sibling(ith_node(prev).sibling()); + ith_node(prev).set_sibling(label); + } + return next; +} + +UInt32 Trie::append_key(const UInt8 *ptr, UInt32 length, UInt32 key_id) { + GRN_DAT_THROW_IF(SIZE_ERROR, key_id > max_num_keys()); + + const UInt32 key_pos = next_key_pos(); + const UInt32 key_size = Key::estimate_size(length); + + GRN_DAT_THROW_IF(SIZE_ERROR, key_size > (key_buf_size() - key_pos)); + Key::create(key_buf_.ptr() + key_pos, key_id, ptr, length); + + header_->set_next_key_pos(key_pos + key_size); + return key_pos; +} + +UInt32 Trie::separate(const UInt8 *ptr, UInt32 length, + UInt32 node_id, UInt32 i) { + GRN_DAT_DEBUG_THROW_IF(node_id >= num_nodes()); + GRN_DAT_DEBUG_THROW_IF(!ith_node(node_id).is_linker()); + GRN_DAT_DEBUG_THROW_IF(i > length); + + const UInt32 key_pos = ith_node(node_id).key_pos(); + const Key &key = get_key(key_pos); + + UInt16 labels[2]; + labels[0] = (i < key.length()) ? (UInt16)key[i] : (UInt16)TERMINAL_LABEL; + labels[1] = (i < length) ? (UInt16)ptr[i] : (UInt16)TERMINAL_LABEL; + GRN_DAT_DEBUG_THROW_IF(labels[0] == labels[1]); + + const UInt32 offset = find_offset(labels, 2); + + UInt32 next = offset ^ labels[0]; + reserve_node(next); + GRN_DAT_DEBUG_THROW_IF(ith_node(offset).is_offset()); + + ith_node(next).set_label(labels[0]); + ith_node(next).set_key_pos(key_pos); + + next = offset ^ labels[1]; + reserve_node(next); + + ith_node(next).set_label(labels[1]); + + ith_node(offset).set_is_offset(true); + ith_node(node_id).set_offset(offset); + + if ((labels[0] == TERMINAL_LABEL) || + ((labels[1] != TERMINAL_LABEL) && (labels[0] < labels[1]))) { + ith_node(node_id).set_child(labels[0]); + ith_node(offset ^ labels[0]).set_sibling(labels[1]); + } else { + ith_node(node_id).set_child(labels[1]); + ith_node(offset ^ labels[1]).set_sibling(labels[0]); + } + return next; +} + +void Trie::resolve(UInt32 node_id, UInt16 label) { + GRN_DAT_DEBUG_THROW_IF(node_id >= num_nodes()); + GRN_DAT_DEBUG_THROW_IF(ith_node(node_id).is_linker()); + GRN_DAT_DEBUG_THROW_IF(label > MAX_LABEL); + + UInt32 offset = ith_node(node_id).offset(); + if (offset != INVALID_OFFSET) { + UInt16 labels[MAX_LABEL + 1]; + UInt32 num_labels = 0; + + UInt32 next_label = ith_node(node_id).child(); + GRN_DAT_DEBUG_THROW_IF(next_label == INVALID_LABEL); + while (next_label != INVALID_LABEL) { + GRN_DAT_DEBUG_THROW_IF(next_label > MAX_LABEL); + labels[num_labels++] = next_label; + next_label = ith_node(offset ^ next_label).sibling(); + } + GRN_DAT_DEBUG_THROW_IF(num_labels == 0); + + labels[num_labels] = label; + offset = find_offset(labels, num_labels + 1); + migrate_nodes(node_id, offset, labels, num_labels); + } else { + offset = find_offset(&label, 1); + if (offset >= num_nodes()) { + GRN_DAT_DEBUG_THROW_IF((offset / BLOCK_SIZE) != num_blocks()); + reserve_block(num_blocks()); + } + ith_node(offset).set_is_offset(true); + ith_node(node_id).set_offset(offset); + } +} + +void Trie::migrate_nodes(UInt32 node_id, UInt32 dest_offset, + const UInt16 *labels, UInt32 num_labels) { + GRN_DAT_DEBUG_THROW_IF(node_id >= num_nodes()); + GRN_DAT_DEBUG_THROW_IF(ith_node(node_id).is_linker()); + GRN_DAT_DEBUG_THROW_IF(labels == NULL); + GRN_DAT_DEBUG_THROW_IF(num_labels == 0); + GRN_DAT_DEBUG_THROW_IF(num_labels > (MAX_LABEL + 1)); + + const UInt32 src_offset = ith_node(node_id).offset(); + GRN_DAT_DEBUG_THROW_IF(src_offset == INVALID_OFFSET); + GRN_DAT_DEBUG_THROW_IF(!ith_node(src_offset).is_offset()); + + for (UInt32 i = 0; i < num_labels; ++i) { + const UInt32 src_node_id = src_offset ^ labels[i]; + const UInt32 dest_node_id = dest_offset ^ labels[i]; + GRN_DAT_DEBUG_THROW_IF(ith_node(src_node_id).is_phantom()); + GRN_DAT_DEBUG_THROW_IF(ith_node(src_node_id).label() != labels[i]); + + reserve_node(dest_node_id); + ith_node(dest_node_id).set_except_is_offset( + ith_node(src_node_id).except_is_offset()); + ith_node(dest_node_id).set_base(ith_node(src_node_id).base()); + } + header_->set_num_zombies(num_zombies() + num_labels); + + GRN_DAT_DEBUG_THROW_IF(ith_node(dest_offset).is_offset()); + ith_node(dest_offset).set_is_offset(true); + ith_node(node_id).set_offset(dest_offset); +} + +UInt32 Trie::find_offset(const UInt16 *labels, UInt32 num_labels) { + GRN_DAT_DEBUG_THROW_IF(labels == NULL); + GRN_DAT_DEBUG_THROW_IF(num_labels == 0); + GRN_DAT_DEBUG_THROW_IF(num_labels > (MAX_LABEL + 1)); + + // Blocks are tested in descending order of level. Basically, a lower level + // block contains more phantom nodes. + UInt32 level = 1; + while (num_labels >= (1U << level)) { + ++level; + } + level = (level < MAX_BLOCK_LEVEL) ? (MAX_BLOCK_LEVEL - level) : 0; + + UInt32 block_count = 0; + do { + UInt32 leader = header_->ith_leader(level); + if (leader == INVALID_LEADER) { + // This level has no blocks and it is thus skipped. + continue; + } + + UInt32 block_id = leader; + do { + const Block &block = ith_block(block_id); + GRN_DAT_DEBUG_THROW_IF(block.level() != level); + + const UInt32 first = (block_id * BLOCK_SIZE) | block.first_phantom(); + UInt32 node_id = first; + do { + GRN_DAT_DEBUG_THROW_IF(!ith_node(node_id).is_phantom()); + const UInt32 offset = node_id ^ labels[0]; + if (!ith_node(offset).is_offset()) { + UInt32 i = 1; + for ( ; i < num_labels; ++i) { + if (!ith_node(offset ^ labels[i]).is_phantom()) { + break; + } + } + if (i >= num_labels) { + return offset; + } + } + node_id = (block_id * BLOCK_SIZE) | ith_node(node_id).next(); + } while (node_id != first); + + const UInt32 prev = block_id; + const UInt32 next = block.next(); + block_id = next; + ith_block(prev).set_failure_count(ith_block(prev).failure_count() + 1); + + // The level of a block is updated when this function fails many times, + // actually MAX_FAILURE_COUNT times, in that block. + if (ith_block(prev).failure_count() == MAX_FAILURE_COUNT) { + update_block_level(prev, level + 1); + if (next == leader) { + break; + } else { + // Note that the leader might be updated in the level update. + leader = header_->ith_leader(level); + continue; + } + } + } while ((++block_count < MAX_BLOCK_COUNT) && (block_id != leader)); + } while ((block_count < MAX_BLOCK_COUNT) && (level-- != 0)); + + return num_nodes() ^ labels[0]; +} + +void Trie::reserve_node(UInt32 node_id) { + GRN_DAT_DEBUG_THROW_IF(node_id > num_nodes()); + if (node_id >= num_nodes()) { + reserve_block(node_id / BLOCK_SIZE); + } + + Node &node = ith_node(node_id); + GRN_DAT_DEBUG_THROW_IF(!node.is_phantom()); + + const UInt32 block_id = node_id / BLOCK_SIZE; + Block &block = ith_block(block_id); + GRN_DAT_DEBUG_THROW_IF(block.num_phantoms() == 0); + + const UInt32 next = (block_id * BLOCK_SIZE) | node.next(); + const UInt32 prev = (block_id * BLOCK_SIZE) | node.prev(); + GRN_DAT_DEBUG_THROW_IF(next >= num_nodes()); + GRN_DAT_DEBUG_THROW_IF(prev >= num_nodes()); + + if ((node_id & BLOCK_MASK) == block.first_phantom()) { + // The first phantom node is removed from the block and the second phantom + // node comes first. + block.set_first_phantom(next & BLOCK_MASK); + } + + ith_node(next).set_prev(prev & BLOCK_MASK); + ith_node(prev).set_next(next & BLOCK_MASK); + + if (block.level() != MAX_BLOCK_LEVEL) { + const UInt32 threshold = 1U << ((MAX_BLOCK_LEVEL - block.level() - 1) * 2); + if (block.num_phantoms() == threshold) { + update_block_level(block_id, block.level() + 1); + } + } + block.set_num_phantoms(block.num_phantoms() - 1); + + node.set_is_phantom(false); + + GRN_DAT_DEBUG_THROW_IF(node.offset() != INVALID_OFFSET); + GRN_DAT_DEBUG_THROW_IF(node.label() != INVALID_LABEL); + + header_->set_num_phantoms(num_phantoms() - 1); +} + +void Trie::reserve_block(UInt32 block_id) { + GRN_DAT_DEBUG_THROW_IF(block_id != num_blocks()); + GRN_DAT_THROW_IF(SIZE_ERROR, block_id >= max_num_blocks()); + + header_->set_num_blocks(block_id + 1); + ith_block(block_id).set_failure_count(0); + ith_block(block_id).set_first_phantom(0); + ith_block(block_id).set_num_phantoms(BLOCK_SIZE); + + const UInt32 begin = block_id * BLOCK_SIZE; + const UInt32 end = begin + BLOCK_SIZE; + GRN_DAT_DEBUG_THROW_IF(end != num_nodes()); + + Base base; + base.set_offset(INVALID_OFFSET); + + Check check; + check.set_is_phantom(true); + + for (UInt32 i = begin; i < end; ++i) { + check.set_prev((i - 1) & BLOCK_MASK); + check.set_next((i + 1) & BLOCK_MASK); + ith_node(i).set_base(base); + ith_node(i).set_check(check); + } + + // The level of the new block is 0. + set_block_level(block_id, 0); + header_->set_num_phantoms(num_phantoms() + BLOCK_SIZE); +} + +void Trie::update_block_level(UInt32 block_id, UInt32 level) { + GRN_DAT_DEBUG_THROW_IF(block_id >= num_blocks()); + GRN_DAT_DEBUG_THROW_IF(level > MAX_BLOCK_LEVEL); + + unset_block_level(block_id); + set_block_level(block_id, level); +} + +void Trie::set_block_level(UInt32 block_id, UInt32 level) { + GRN_DAT_DEBUG_THROW_IF(block_id >= num_blocks()); + GRN_DAT_DEBUG_THROW_IF(level > MAX_BLOCK_LEVEL); + + const UInt32 leader = header_->ith_leader(level); + if (leader == INVALID_LEADER) { + // The new block becomes the only one block of the linked list. + ith_block(block_id).set_next(block_id); + ith_block(block_id).set_prev(block_id); + header_->set_ith_leader(level, block_id); + } else { + // The new block is added to the end of the list. + const UInt32 next = leader; + const UInt32 prev = ith_block(leader).prev(); + GRN_DAT_DEBUG_THROW_IF(next >= num_blocks()); + GRN_DAT_DEBUG_THROW_IF(prev >= num_blocks()); + ith_block(block_id).set_next(next); + ith_block(block_id).set_prev(prev); + ith_block(next).set_prev(block_id); + ith_block(prev).set_next(block_id); + } + ith_block(block_id).set_level(level); + ith_block(block_id).set_failure_count(0); +} + +void Trie::unset_block_level(UInt32 block_id) { + GRN_DAT_DEBUG_THROW_IF(block_id >= num_blocks()); + + const UInt32 level = ith_block(block_id).level(); + GRN_DAT_DEBUG_THROW_IF(level > MAX_BLOCK_LEVEL); + + const UInt32 leader = header_->ith_leader(level); + GRN_DAT_DEBUG_THROW_IF(leader == INVALID_LEADER); + + const UInt32 next = ith_block(block_id).next(); + const UInt32 prev = ith_block(block_id).prev(); + GRN_DAT_DEBUG_THROW_IF(next >= num_blocks()); + GRN_DAT_DEBUG_THROW_IF(prev >= num_blocks()); + + if (next == block_id) { + // The linked list becomes empty. + header_->set_ith_leader(level, INVALID_LEADER); + } else { + ith_block(next).set_prev(prev); + ith_block(prev).set_next(next); + if (block_id == leader) { + // The second block becomes the leader of the linked list. + header_->set_ith_leader(level, next); + } + } +} + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/trie.hpp b/storage/mroonga/vendor/groonga/lib/dat/trie.hpp new file mode 100644 index 00000000..bf7d0b98 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/trie.hpp @@ -0,0 +1,285 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "array.hpp" +#include "header.hpp" +#include "node.hpp" +#include "block.hpp" +#include "entry.hpp" +#include "key.hpp" +#include "file.hpp" + +namespace grn { +namespace dat { + +class GRN_DAT_API Trie { + public: + Trie(); + ~Trie(); + + void create(const char *file_name = NULL, + UInt64 file_size = 0, + UInt32 max_num_keys = 0, + double num_nodes_per_key = 0.0, + double average_key_length = 0.0); + + void create(const Trie &trie, + const char *file_name = NULL, + UInt64 file_size = 0, + UInt32 max_num_keys = 0, + double num_nodes_per_key = 0.0, + double average_key_length = 0.0); + + void repair(const Trie &trie, const char *file_name = NULL); + + void open(const char *file_name); + void close(); + + void swap(Trie *trie); + + // Users can access a key by its position or ID. + const Key &get_key(UInt32 key_pos) const { + GRN_DAT_DEBUG_THROW_IF(key_pos >= next_key_pos()); + return *reinterpret_cast(key_buf_.ptr() + key_pos); + } + // If a specified ID is invalid, e.g. the key is already deleted, this + // function returns a reference to an invalid key object whose id() returns + // INVALID_KEY_ID. + const Key &ith_key(UInt32 key_id) const { + if ((key_id >= min_key_id()) && (key_id <= max_key_id()) && + ith_entry(key_id).is_valid()) { + return get_key(ith_entry(key_id).key_pos()); + } + return Key::invalid_key(); + } + + bool search(const void *ptr, UInt32 length, UInt32 *key_pos = NULL) const { + return search_key(static_cast(ptr), length, key_pos); + } + // Longest prefix match search. + bool lcp_search(const void *ptr, UInt32 length, + UInt32 *key_pos = NULL) const { + return lcp_search_key(static_cast(ptr), length, key_pos); + } + + bool remove(UInt32 key_id) { + const Key &key = ith_key(key_id); + if (key.is_valid()) { + return remove(key.ptr(), key.length()); + } + return false; + } + bool remove(const void *ptr, UInt32 length) { + return remove_key(static_cast(ptr), length); + } + + bool insert(const void *ptr, UInt32 length, UInt32 *key_pos = NULL) { + return insert_key(static_cast(ptr), length, key_pos); + } + + bool update(UInt32 key_id, const void *ptr, UInt32 length, + UInt32 *key_pos = NULL) { + return update_key(ith_key(key_id), static_cast(ptr), + length, key_pos); + } + bool update(const void *src_ptr, UInt32 src_length, + const void *dest_ptr, UInt32 dest_length, + UInt32 *key_pos = NULL) { + UInt32 src_key_pos; + if (!search(src_ptr, src_length, &src_key_pos)) { + return false; + } + const Key &src_key = get_key(src_key_pos); + return update_key(src_key, static_cast(dest_ptr), + dest_length, key_pos); + } + + const Node &ith_node(UInt32 i) const { + GRN_DAT_DEBUG_THROW_IF(i >= num_nodes()); + return nodes_[i]; + } + const Block &ith_block(UInt32 i) const { + GRN_DAT_DEBUG_THROW_IF(i >= num_blocks()); + return blocks_[i]; + } + const Entry &ith_entry(UInt32 i) const { + GRN_DAT_DEBUG_THROW_IF(i < min_key_id()); + GRN_DAT_DEBUG_THROW_IF(i > max_key_id()); + return entries_[i]; + } + + const Header &header() const { + return *header_; + } + + UInt64 file_size() const { + return header_->file_size(); + } + UInt64 virtual_size() const { + return sizeof(Header) + + (sizeof(Entry) * num_keys()) + + (sizeof(Block) * num_blocks()) + + (sizeof(Node) * num_nodes()) + + total_key_length(); + } + UInt32 total_key_length() const { + return header_->total_key_length(); + } + UInt32 num_keys() const { + return header_->num_keys(); + } + UInt32 min_key_id() const { + return header_->min_key_id(); + } + UInt32 next_key_id() const { + return header_->next_key_id(); + } + UInt32 max_key_id() const { + return header_->max_key_id(); + } + UInt32 max_num_keys() const { + return header_->max_num_keys(); + } + UInt32 num_nodes() const { + return header_->num_nodes(); + } + UInt32 num_phantoms() const { + return header_->num_phantoms(); + } + UInt32 num_zombies() const { + return header_->num_zombies(); + } + UInt32 max_num_nodes() const { + return header_->max_num_nodes(); + } + UInt32 num_blocks() const { + return header_->num_blocks(); + } + UInt32 max_num_blocks() const { + return header_->max_num_blocks(); + } + UInt32 next_key_pos() const { + return header_->next_key_pos(); + } + UInt32 key_buf_size() const { + return header_->key_buf_size(); + } + UInt32 status_flags() const { + return header_->status_flags(); + } + + void clear_status_flags() { + header_->set_status_flags(status_flags() & ~CHANGING_MASK); + } + + void flush(); + + private: + File file_; + Header *header_; + Array nodes_; + Array blocks_; + Array entries_; + Array key_buf_; + + void create_file(const char *file_name, + UInt64 file_size, + UInt32 max_num_keys, + double num_nodes_per_key, + double average_key_length); + void create_file(const char *file_name, + UInt64 file_size, + UInt32 max_num_keys, + UInt32 max_num_blocks, + UInt32 key_buf_size); + + void open_file(const char *file_name); + + void map_address(void *address); + + void build_from_trie(const Trie &trie); + void build_from_trie(const Trie &trie, UInt32 src, UInt32 dest); + + void repair_trie(const Trie &trie); + void build_from_keys(const UInt32 *begin, const UInt32 *end, + UInt32 depth, UInt32 node_id); + + void mkq_sort(UInt32 *l, UInt32 *r, UInt32 depth); + void insertion_sort(UInt32 *l, UInt32 *r, UInt32 depth); + + inline int get_label(UInt32 key_id, UInt32 depth) const; + inline int get_median(UInt32 a, UInt32 b, UInt32 c, UInt32 depth) const; + inline bool less_than(UInt32 lhs, UInt32 rhs, UInt32 depth) const; + inline static void swap_ids(UInt32 *lhs, UInt32 *rhs); + + bool search_key(const UInt8 *ptr, UInt32 length, UInt32 *key_pos) const; + bool search_linker(const UInt8 *ptr, UInt32 length, + UInt32 &node_id, UInt32 &query_pos) const; + + bool lcp_search_key(const UInt8 *ptr, UInt32 length, UInt32 *key_pos) const; + + bool remove_key(const UInt8 *ptr, UInt32 length); + + bool insert_key(const UInt8 *ptr, UInt32 length, UInt32 *key_pos); + bool insert_linker(const UInt8 *ptr, UInt32 length, + UInt32 &node_id, UInt32 query_pos); + + bool update_key(const Key &key, const UInt8 *ptr, UInt32 length, + UInt32 *key_pos); + + UInt32 insert_node(UInt32 node_id, UInt16 label); + UInt32 append_key(const UInt8 *ptr, UInt32 length, UInt32 key_id); + + UInt32 separate(const UInt8 *ptr, UInt32 length, + UInt32 node_id, UInt32 i); + void resolve(UInt32 node_id, UInt16 label); + void migrate_nodes(UInt32 node_id, UInt32 dest_offset, + const UInt16 *labels, UInt32 num_labels); + + UInt32 find_offset(const UInt16 *labels, UInt32 num_labels); + + void reserve_node(UInt32 node_id); + void reserve_block(UInt32 block_id); + + void update_block_level(UInt32 block_id, UInt32 level); + void set_block_level(UInt32 block_id, UInt32 level); + void unset_block_level(UInt32 block_id); + + Node &ith_node(UInt32 i) { + GRN_DAT_DEBUG_THROW_IF(i >= num_nodes()); + return nodes_[i]; + } + Block &ith_block(UInt32 i) { + GRN_DAT_DEBUG_THROW_IF(i >= num_blocks()); + return blocks_[i]; + } + Entry &ith_entry(UInt32 i) { + GRN_DAT_DEBUG_THROW_IF(i < min_key_id()); + GRN_DAT_DEBUG_THROW_IF(i > (max_key_id() + 1)); + return entries_[i]; + } + + // Disallows copy and assignment. + Trie(const Trie &); + Trie &operator=(const Trie &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/dat/vector.hpp b/storage/mroonga/vendor/groonga/lib/dat/vector.hpp new file mode 100644 index 00000000..8a67b27b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dat/vector.hpp @@ -0,0 +1,191 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "dat.hpp" + +#include + +namespace grn { +namespace dat { + +template +class GRN_DAT_API Vector { + public: + Vector() : buf_(NULL), size_(0), capacity_(0) {} + ~Vector() { + for (UInt32 i = 0; i < size(); ++i) { + buf_[i].~T(); + } + delete [] reinterpret_cast(buf_); + } + + const T &operator[](UInt32 i) const { + GRN_DAT_DEBUG_THROW_IF(i >= size()); + return buf_[i]; + } + T &operator[](UInt32 i) { + GRN_DAT_DEBUG_THROW_IF(i >= size()); + return buf_[i]; + } + + const T &front() const { + GRN_DAT_DEBUG_THROW_IF(empty()); + return buf_[0]; + } + T &front() { + GRN_DAT_DEBUG_THROW_IF(empty()); + return buf_[0]; + } + + const T &back() const { + GRN_DAT_DEBUG_THROW_IF(empty()); + return buf_[size() - 1]; + } + T &back() { + GRN_DAT_DEBUG_THROW_IF(empty()); + return buf_[size() - 1]; + } + + const T *begin() const { + return buf_; + } + T *begin() { + return buf_; + } + + const T *end() const { + return buf_ + size_; + } + T *end() { + return buf_ + size_; + } + + void push_back() { + reserve(size() + 1); + new (&buf_[size()]) T; + ++size_; + } + void push_back(const T &x) { + reserve(size() + 1); + new (&buf_[size()]) T(x); + ++size_; + } + + void pop_back() { + GRN_DAT_DEBUG_THROW_IF(empty()); + back().~T(); + --size_; + } + + void clear() { + resize(0); + } + + void resize(UInt32 new_size) { + if (new_size > capacity()) { + reserve(new_size); + } + for (UInt32 i = size(); i < new_size; ++i) { + new (&buf_[i]) T; + } + for (UInt32 i = new_size; i < size(); ++i) { + buf_[i].~T(); + } + size_ = new_size; + } + template + void resize(UInt32 new_size, const U &value) { + if (new_size > capacity()) { + reserve(new_size); + } + for (UInt32 i = size(); i < new_size; ++i) { + new (&buf_[i]) T(value); + } + for (UInt32 i = new_size; i < size(); ++i) { + buf_[i].~T(); + } + size_ = new_size; + } + + void reserve(UInt32 new_capacity) { + if (new_capacity <= capacity()) { + return; + } else if ((new_capacity / 2) < capacity()) { + if (capacity() < (MAX_UINT32 / 2)) { + new_capacity = capacity() * 2; + } else { + new_capacity = MAX_UINT32; + } + } + + T *new_buf = reinterpret_cast( + new (std::nothrow) char[sizeof(new_capacity) * new_capacity]); + GRN_DAT_THROW_IF(MEMORY_ERROR, new_buf == NULL); + + for (UInt32 i = 0; i < size(); ++i) { + new (&new_buf[i]) T(buf_[i]); + } + for (UInt32 i = 0; i < size(); ++i) { + buf_[i].~T(); + } + + T *old_buf = buf_; + buf_ = new_buf; + delete [] reinterpret_cast(old_buf); + + capacity_ = new_capacity; + } + + void swap(Vector *rhs) { + T * const temp_buf = buf_; + buf_ = rhs->buf_; + rhs->buf_ = temp_buf; + + const UInt32 temp_size = size_; + size_ = rhs->size_; + rhs->size_ = temp_size; + + const UInt32 temp_capacity = capacity_; + capacity_ = rhs->capacity_; + rhs->capacity_ = temp_capacity; + } + + bool empty() const { + return size_ == 0; + } + UInt32 size() const { + return size_; + } + UInt32 capacity() const { + return capacity_; + } + + private: + T *buf_; + UInt32 size_; + UInt32 capacity_; + + // Disallows copy and assignment. + Vector(const Vector &); + Vector &operator=(const Vector &); +}; + +} // namespace dat +} // namespace grn diff --git a/storage/mroonga/vendor/groonga/lib/db.c b/storage/mroonga/vendor/groonga/lib/db.c new file mode 100644 index 00000000..7749d4c0 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/db.c @@ -0,0 +1,14054 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include "grn_config.h" +#include "grn_db.h" +#include "grn_obj.h" +#include "grn_hash.h" +#include "grn_pat.h" +#include "grn_dat.h" +#include "grn_ii.h" +#include "grn_index_column.h" +#include "grn_ctx_impl.h" +#include "grn_token_cursor.h" +#include "grn_tokenizers.h" +#include "grn_proc.h" +#include "grn_plugin.h" +#include "grn_geo.h" +#include "grn_scorers.h" +#include "grn_snip.h" +#include "grn_string.h" +#include "grn_normalizer.h" +#include "grn_report.h" +#include "grn_util.h" +#include "grn_cache.h" +#include "grn_window_functions.h" +#include +#include + +typedef struct { + grn_id id; + unsigned int weight; +} weight_uvector_entry; + +#define IS_WEIGHT_UVECTOR(obj) ((obj)->header.flags & GRN_OBJ_WITH_WEIGHT) + +#define GRN_TABLE_GROUPED (0x01<<0) +#define GRN_TABLE_IS_GROUPED(table)\ + ((table)->header.impl_flags & GRN_TABLE_GROUPED) +#define GRN_TABLE_GROUPED_ON(table)\ + ((table)->header.impl_flags |= GRN_TABLE_GROUPED) +#define GRN_TABLE_IS_MULTI_KEYS_GROUPED(table)\ + (GRN_TABLE_IS_GROUPED(table) &&\ + table->header.domain == GRN_ID_NIL) + +#define WITH_NORMALIZE(table,key,key_size,block) do {\ + if ((table)->normalizer && key && key_size > 0) {\ + grn_obj *nstr;\ + if ((nstr = grn_string_open(ctx, key, key_size,\ + (table)->normalizer, 0))) {\ + const char *key;\ + unsigned int key_size;\ + grn_string_get_normalized(ctx, nstr, &key, &key_size, NULL);\ + block\ + grn_obj_close(ctx, nstr);\ + }\ + } else {\ + block\ + }\ +} while (0) + +inline static grn_id +grn_table_add_v_inline(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, + void **value, int *added); +inline static void +grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, double score, + grn_rset_posinfo *pi, int dir); +inline static grn_id +grn_table_cursor_next_inline(grn_ctx *ctx, grn_table_cursor *tc); +inline static int +grn_table_cursor_get_value_inline(grn_ctx *ctx, grn_table_cursor *tc, void **value); + +static void grn_obj_ensure_bulk(grn_ctx *ctx, grn_obj *obj); +static void grn_obj_ensure_vector(grn_ctx *ctx, grn_obj *obj); + +inline static void +grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj, + grn_id *range_id, grn_obj_flags *range_flags); + +static char grn_db_key[GRN_ENV_BUFFER_SIZE]; + +void +grn_db_init_from_env(void) +{ + grn_getenv("GRN_DB_KEY", + grn_db_key, + GRN_ENV_BUFFER_SIZE); +} + +inline static void +gen_pathname(const char *path, char *buffer, int fno) +{ + size_t len = strlen(path); + grn_memcpy(buffer, path, len); + if (fno >= 0) { + buffer[len] = '.'; + grn_itoh(fno, buffer + len + 1, 7); + buffer[len + 8] = '\0'; + } else { + buffer[len] = '\0'; + } +} + +void +grn_db_generate_pathname(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer) +{ + gen_pathname(grn_obj_get_io(ctx, db)->path, buffer, id); +} + +typedef struct { + grn_obj *ptr; + uint32_t lock; + uint32_t done; +} db_value; + +static const char *GRN_DB_CONFIG_PATH_FORMAT = "%s.conf"; + +static grn_bool +grn_db_config_create(grn_ctx *ctx, grn_db *s, const char *path, + const char *context_tag) +{ + char *config_path; + char config_path_buffer[PATH_MAX]; + uint32_t flags = GRN_OBJ_KEY_VAR_SIZE; + + if (path) { + grn_snprintf(config_path_buffer, PATH_MAX, PATH_MAX, + GRN_DB_CONFIG_PATH_FORMAT, path); + config_path = config_path_buffer; + } else { + config_path = NULL; + } + s->config = grn_hash_create(ctx, config_path, + GRN_CONFIG_MAX_KEY_SIZE, + GRN_CONFIG_VALUE_SPACE_SIZE, + flags); + if (!s->config) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "%s failed to create data store for configuration: <%s>", + context_tag, + config_path ? config_path : "(temporary)"); + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static grn_bool +grn_db_config_open(grn_ctx *ctx, grn_db *s, const char *path) +{ + char config_path[PATH_MAX]; + + grn_snprintf(config_path, PATH_MAX, PATH_MAX, GRN_DB_CONFIG_PATH_FORMAT, path); + if (grn_path_exist(config_path)) { + s->config = grn_hash_open(ctx, config_path); + if (!s->config) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[db][open] failed to open data store for configuration: <%s>", + config_path); + return GRN_FALSE; + } + return GRN_TRUE; + } else { + return grn_db_config_create(ctx, s, path, "[db][open]"); + } +} + +static grn_rc +grn_db_config_remove(grn_ctx *ctx, const char *path) +{ + char config_path[PATH_MAX]; + + grn_snprintf(config_path, PATH_MAX, PATH_MAX, GRN_DB_CONFIG_PATH_FORMAT, path); + return grn_hash_remove(ctx, config_path); +} + +grn_obj * +grn_db_create(grn_ctx *ctx, const char *path, grn_db_create_optarg *optarg) +{ + grn_db *s = NULL; + + GRN_API_ENTER; + + if (path && strlen(path) > PATH_MAX - 14) { + ERR(GRN_INVALID_ARGUMENT, "too long path"); + goto exit; + } + + s = GRN_MALLOC(sizeof(grn_db)); + if (!s) { + ERR(GRN_NO_MEMORY_AVAILABLE, "grn_db alloc failed"); + goto exit; + } + + CRITICAL_SECTION_INIT(s->lock); + grn_tiny_array_init(ctx, &s->values, sizeof(db_value), + GRN_TINY_ARRAY_CLEAR| + GRN_TINY_ARRAY_THREADSAFE| + GRN_TINY_ARRAY_USE_MALLOC); + s->keys = NULL; + s->specs = NULL; + s->config = NULL; + + { + grn_bool use_default_db_key = GRN_TRUE; + grn_bool use_pat_as_db_keys = GRN_FALSE; + if (grn_db_key[0]) { + if (!strcmp(grn_db_key, "pat")) { + use_default_db_key = GRN_FALSE; + use_pat_as_db_keys = GRN_TRUE; + } else if (!strcmp(grn_db_key, "dat")) { + use_default_db_key = GRN_FALSE; + } + } + + if (use_default_db_key && !strcmp(GRN_DEFAULT_DB_KEY, "pat")) { + use_pat_as_db_keys = GRN_TRUE; + } + if (use_pat_as_db_keys) { + s->keys = (grn_obj *)grn_pat_create(ctx, path, GRN_TABLE_MAX_KEY_SIZE, + 0, GRN_OBJ_KEY_VAR_SIZE); + } else { + s->keys = (grn_obj *)grn_dat_create(ctx, path, GRN_TABLE_MAX_KEY_SIZE, + 0, GRN_OBJ_KEY_VAR_SIZE); + } + } + + if (!s->keys) { + goto exit; + } + + GRN_DB_OBJ_SET_TYPE(s, GRN_DB); + s->obj.db = (grn_obj *)s; + s->obj.header.domain = GRN_ID_NIL; + DB_OBJ(&s->obj)->range = GRN_ID_NIL; + /* prepare builtin classes and load builtin plugins. */ + if (path) { + { + char specs_path[PATH_MAX]; + gen_pathname(path, specs_path, 0); + s->specs = grn_ja_create(ctx, specs_path, 65536, 0); + if (!s->specs) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to create specs: <%s>", specs_path); + goto exit; + } + } + if (!grn_db_config_create(ctx, s, path, "[db][create]")) { + goto exit; + } + grn_ctx_use(ctx, (grn_obj *)s); + grn_db_init_builtin_types(ctx); + grn_obj_flush(ctx, (grn_obj *)s); + GRN_API_RETURN((grn_obj *)s); + } else { + if (!grn_db_config_create(ctx, s, NULL, "[db][create]")) { + goto exit; + } + grn_ctx_use(ctx, (grn_obj *)s); + grn_db_init_builtin_types(ctx); + GRN_API_RETURN((grn_obj *)s); + } + +exit: + if (s) { + if (s->keys) { + if (s->keys->header.type == GRN_TABLE_PAT_KEY) { + grn_pat_close(ctx, (grn_pat *)s->keys); + grn_pat_remove(ctx, path); + } else { + grn_dat_close(ctx, (grn_dat *)s->keys); + grn_dat_remove(ctx, path); + } + } + if (s->specs) { + const char *specs_path; + specs_path = grn_obj_path(ctx, (grn_obj *)(s->specs)); + grn_ja_close(ctx, s->specs); + grn_ja_remove(ctx, specs_path); + } + grn_tiny_array_fin(&s->values); + CRITICAL_SECTION_FIN(s->lock); + GRN_FREE(s); + } + + GRN_API_RETURN(NULL); +} + +grn_obj * +grn_db_open(grn_ctx *ctx, const char *path) +{ + grn_db *s = NULL; + + GRN_API_ENTER; + + if (!path) { + ERR(GRN_INVALID_ARGUMENT, "[db][open] path is missing"); + goto exit; + } + + if (strlen(path) > PATH_MAX - 14) { + ERR(GRN_INVALID_ARGUMENT, "inappropriate path"); + goto exit; + } + + s = GRN_MALLOC(sizeof(grn_db)); + if (!s) { + ERR(GRN_NO_MEMORY_AVAILABLE, "grn_db alloc failed"); + goto exit; + } + + CRITICAL_SECTION_INIT(s->lock); + grn_tiny_array_init(ctx, &s->values, sizeof(db_value), + GRN_TINY_ARRAY_CLEAR| + GRN_TINY_ARRAY_THREADSAFE| + GRN_TINY_ARRAY_USE_MALLOC); + s->keys = NULL; + s->specs = NULL; + s->config = NULL; + + { + uint32_t type = grn_io_detect_type(ctx, path); + switch (type) { + case GRN_TABLE_PAT_KEY : + s->keys = (grn_obj *)grn_pat_open(ctx, path); + break; + case GRN_TABLE_DAT_KEY : + s->keys = (grn_obj *)grn_dat_open(ctx, path); + break; + default : + s->keys = NULL; + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_INVALID_ARGUMENT, + "[db][open] invalid keys table's type: %#x", type); + goto exit; + } + break; + } + } + + if (!s->keys) { + goto exit; + } + + { + char specs_path[PATH_MAX]; + gen_pathname(path, specs_path, 0); + s->specs = grn_ja_open(ctx, specs_path); + if (!s->specs) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[db][open] failed to open specs: <%s>", specs_path); + goto exit; + } + } + if (!grn_db_config_open(ctx, s, path)) { + goto exit; + } + + GRN_DB_OBJ_SET_TYPE(s, GRN_DB); + s->obj.db = (grn_obj *)s; + s->obj.header.domain = GRN_ID_NIL; + DB_OBJ(&s->obj)->range = GRN_ID_NIL; + grn_ctx_use(ctx, (grn_obj *)s); + { + unsigned int n_records; + + n_records = grn_table_size(ctx, (grn_obj *)s); +#ifdef GRN_WITH_MECAB + if (grn_db_init_mecab_tokenizer(ctx)) { + ERRCLR(ctx); + } +#endif + grn_db_init_builtin_tokenizers(ctx); + grn_db_init_builtin_normalizers(ctx); + grn_db_init_builtin_scorers(ctx); + grn_db_init_builtin_commands(ctx); + grn_db_init_builtin_window_functions(ctx); + + if (grn_table_size(ctx, (grn_obj *)s) > n_records) { + grn_obj_flush(ctx, (grn_obj *)s); + } + } + GRN_API_RETURN((grn_obj *)s); + +exit: + if (s) { + if (s->specs) { + grn_ja_close(ctx, s->specs); + } + if (s->keys) { + if (s->keys->header.type == GRN_TABLE_PAT_KEY) { + grn_pat_close(ctx, (grn_pat *)s->keys); + } else { + grn_dat_close(ctx, (grn_dat *)s->keys); + } + } + grn_tiny_array_fin(&s->values); + CRITICAL_SECTION_FIN(s->lock); + GRN_FREE(s); + } + + GRN_API_RETURN(NULL); +} + +static grn_id +grn_db_curr_id(grn_ctx *ctx, grn_obj *db) +{ + grn_id curr_id = GRN_ID_NIL; + grn_db *s = (grn_db *)db; + switch (s->keys->header.type) { + case GRN_TABLE_PAT_KEY : + curr_id = grn_pat_curr_id(ctx, (grn_pat *)s->keys); + break; + case GRN_TABLE_DAT_KEY : + curr_id = grn_dat_curr_id(ctx, (grn_dat *)s->keys); + break; + } + return curr_id; +} + +/* s must be validated by caller */ +grn_rc +grn_db_close(grn_ctx *ctx, grn_obj *db) +{ + grn_id id; + db_value *vp; + grn_db *s = (grn_db *)db; + grn_bool ctx_used_db; + if (!s) { return GRN_INVALID_ARGUMENT; } + GRN_API_ENTER; + + ctx_used_db = ctx->impl && ctx->impl->db == db; + if (ctx_used_db) { +#ifdef GRN_WITH_MECAB + grn_db_fin_mecab_tokenizer(ctx); +#endif + grn_ctx_loader_clear(ctx); + if (ctx->impl->parser) { + grn_expr_parser_close(ctx); + } + } + + GRN_TINY_ARRAY_EACH(&s->values, 1, grn_db_curr_id(ctx, db), id, vp, { + if (vp->ptr) { grn_obj_close(ctx, vp->ptr); } + }); + + if (ctx_used_db) { + if (ctx->impl->values) { + grn_db_obj *o; + GRN_ARRAY_EACH(ctx, ctx->impl->values, 0, 0, id, &o, { + grn_obj_close(ctx, *((grn_obj **)o)); + }); + grn_array_truncate(ctx, ctx->impl->values); + } + } + +/* grn_tiny_array_fin should be refined.. */ +#ifdef WIN32 + { + grn_tiny_array *a = &s->values; + CRITICAL_SECTION_FIN(a->lock); + } +#endif + grn_tiny_array_fin(&s->values); + + switch (s->keys->header.type) { + case GRN_TABLE_PAT_KEY : + grn_pat_close(ctx, (grn_pat *)s->keys); + break; + case GRN_TABLE_DAT_KEY : + grn_dat_close(ctx, (grn_dat *)s->keys); + break; + } + CRITICAL_SECTION_FIN(s->lock); + if (s->specs) { grn_ja_close(ctx, s->specs); } + grn_hash_close(ctx, s->config); + GRN_FREE(s); + + if (ctx_used_db) { + grn_cache *cache; + cache = grn_cache_current_get(ctx); + if (cache) { + grn_cache_expire(cache, -1); + } + ctx->impl->db = NULL; + } + + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_obj * +grn_ctx_get(grn_ctx *ctx, const char *name, int name_size) +{ + grn_obj *obj = NULL; + grn_obj *db; + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + return NULL; + } + GRN_API_ENTER; + if (GRN_DB_P(db)) { + grn_db *s = (grn_db *)db; + grn_obj *alias_table = NULL; + grn_obj *alias_column = NULL; + grn_obj alias_name_buffer; + + if (name_size < 0) { + name_size = strlen(name); + } + GRN_TEXT_INIT(&alias_name_buffer, 0); + while (GRN_TRUE) { + grn_id id; + + id = grn_table_get(ctx, s->keys, name, name_size); + if (id) { + obj = grn_ctx_at(ctx, id); + break; + } + + if (!alias_column) { + grn_id alias_column_id; + const char *alias_column_name; + uint32_t alias_column_name_size; + + grn_config_get(ctx, + "alias.column", -1, + &alias_column_name, &alias_column_name_size); + if (!alias_column_name) { + break; + } + alias_column_id = grn_table_get(ctx, + s->keys, + alias_column_name, + alias_column_name_size); + if (!alias_column_id) { + break; + } + alias_column = grn_ctx_at(ctx, alias_column_id); + if (alias_column->header.type != GRN_COLUMN_VAR_SIZE) { + break; + } + if (alias_column->header.flags & GRN_OBJ_VECTOR) { + break; + } + if (DB_OBJ(alias_column)->range != GRN_DB_SHORT_TEXT) { + break; + } + alias_table = grn_ctx_at(ctx, alias_column->header.domain); + if (alias_table->header.type == GRN_TABLE_NO_KEY) { + break; + } + } + + { + grn_id alias_id; + alias_id = grn_table_get(ctx, alias_table, name, name_size); + if (!alias_id) { + break; + } + GRN_BULK_REWIND(&alias_name_buffer); + grn_obj_get_value(ctx, alias_column, alias_id, &alias_name_buffer); + name = GRN_TEXT_VALUE(&alias_name_buffer); + name_size = GRN_TEXT_LEN(&alias_name_buffer); + } + } + GRN_OBJ_FIN(ctx, &alias_name_buffer); + } + GRN_API_RETURN(obj); +} + +grn_obj * +grn_ctx_db(grn_ctx *ctx) +{ + return (ctx && ctx->impl) ? ctx->impl->db : NULL; +} + +grn_obj * +grn_db_keys(grn_obj *s) +{ + return (grn_obj *)(((grn_db *)s)->keys); +} + +uint32_t +grn_obj_get_last_modified(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return 0; + } + + return grn_obj_get_io(ctx, obj)->header->last_modified; +} + +grn_bool +grn_obj_is_dirty(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return GRN_FALSE; + } + + switch (obj->header.type) { + case GRN_DB : + return grn_db_is_dirty(ctx, obj); + case GRN_TABLE_PAT_KEY : + return grn_pat_is_dirty(ctx, (grn_pat *)obj); + case GRN_TABLE_DAT_KEY : + return grn_dat_is_dirty(ctx, (grn_dat *)obj); + default : + return GRN_FALSE; + } +} + +uint32_t +grn_db_get_last_modified(grn_ctx *ctx, grn_obj *db) +{ + return grn_obj_get_last_modified(ctx, db); +} + +grn_bool +grn_db_is_dirty(grn_ctx *ctx, grn_obj *db) +{ + grn_obj *keys; + + if (!db) { + return GRN_FALSE; + } + + keys = ((grn_db *)db)->keys; + return grn_obj_is_dirty(ctx, keys); +} + +static grn_rc +grn_db_dirty(grn_ctx *ctx, grn_obj *db) +{ + grn_obj *keys; + + if (!db) { + return GRN_SUCCESS; + } + + keys = ((grn_db *)db)->keys; + switch (keys->header.type) { + case GRN_TABLE_PAT_KEY : + return grn_pat_dirty(ctx, (grn_pat *)keys); + case GRN_TABLE_DAT_KEY : + return grn_dat_dirty(ctx, (grn_dat *)keys); + default : + return GRN_SUCCESS; + } +} + +static grn_rc +grn_db_clean(grn_ctx *ctx, grn_obj *db) +{ + grn_obj *keys; + + if (!db) { + return GRN_SUCCESS; + } + + keys = ((grn_db *)db)->keys; + switch (keys->header.type) { + case GRN_TABLE_PAT_KEY : + return grn_pat_clean(ctx, (grn_pat *)keys); + case GRN_TABLE_DAT_KEY : + return grn_dat_clean(ctx, (grn_dat *)keys); + default : + return GRN_SUCCESS; + } +} + +static grn_rc +grn_db_clear_dirty(grn_ctx *ctx, grn_obj *db) +{ + grn_obj *keys; + + if (!db) { + return GRN_SUCCESS; + } + + keys = ((grn_db *)db)->keys; + switch (keys->header.type) { + case GRN_TABLE_PAT_KEY : + return grn_pat_clear_dirty(ctx, (grn_pat *)keys); + case GRN_TABLE_DAT_KEY : + return grn_dat_clear_dirty(ctx, (grn_dat *)keys); + default : + return GRN_SUCCESS; + } +} + +void +grn_db_touch(grn_ctx *ctx, grn_obj *s) +{ + grn_obj_touch(ctx, s, NULL); +} + +grn_bool +grn_obj_is_corrupt(grn_ctx *ctx, grn_obj *obj) +{ + grn_bool is_corrupt = GRN_FALSE; + + GRN_API_ENTER; + + if (!obj) { + ERR(GRN_INVALID_ARGUMENT, "[object][corrupt] object must not be NULL"); + GRN_API_RETURN(GRN_FALSE); + } + + switch (obj->header.type) { + case GRN_DB : + is_corrupt = grn_io_is_corrupt(ctx, grn_obj_get_io(ctx, obj)); + if (!is_corrupt) { + is_corrupt = grn_io_is_corrupt(ctx, ((grn_db *)obj)->specs->io); + } + if (!is_corrupt) { + is_corrupt = grn_io_is_corrupt(ctx, ((grn_db *)obj)->config->io); + } + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + is_corrupt = grn_io_is_corrupt(ctx, grn_obj_get_io(ctx, obj)); + break; + case GRN_TABLE_DAT_KEY : + is_corrupt = grn_dat_is_corrupt(ctx, (grn_dat *)obj); + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + is_corrupt = grn_io_is_corrupt(ctx, grn_obj_get_io(ctx, obj)); + break; + case GRN_COLUMN_INDEX : + is_corrupt = grn_io_is_corrupt(ctx, ((grn_ii *)obj)->seg); + if (!is_corrupt) { + is_corrupt = grn_io_is_corrupt(ctx, ((grn_ii *)obj)->chunk); + } + break; + default : + break; + } + + GRN_API_RETURN(is_corrupt); +} + +#define IS_TEMP(obj) (DB_OBJ(obj)->id & GRN_OBJ_TMP_OBJECT) + +static inline void +grn_obj_touch_db(grn_ctx *ctx, grn_obj *obj, grn_timeval *tv) +{ + grn_obj_get_io(ctx, obj)->header->last_modified = tv->tv_sec; + grn_db_dirty(ctx, obj); +} + +void +grn_obj_touch(grn_ctx *ctx, grn_obj *obj, grn_timeval *tv) +{ + grn_timeval tv_; + if (!tv) { + grn_timeval_now(ctx, &tv_); + tv = &tv_; + } + if (obj) { + switch (obj->header.type) { + case GRN_DB : + grn_obj_touch_db(ctx, obj, tv); + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_INDEX : + if (!IS_TEMP(obj)) { + grn_obj_get_io(ctx, obj)->header->last_modified = tv->tv_sec; + grn_obj_touch(ctx, DB_OBJ(obj)->db, tv); + } + break; + } + } +} + +grn_rc +grn_db_check_name(grn_ctx *ctx, const char *name, unsigned int name_size) +{ + int len; + const char *name_end = name + name_size; + if (name_size > 0 && + *name == GRN_DB_PSEUDO_COLUMN_PREFIX) { + return GRN_INVALID_ARGUMENT; + } + while (name < name_end) { + char c = *name; + if ((unsigned int)((c | 0x20) - 'a') >= 26u && + (unsigned int)(c - '0') >= 10u && + c != '_' && + c != '-' && + c != '#' && + c != '@') { + return GRN_INVALID_ARGUMENT; + } + if (!(len = grn_charlen(ctx, name, name_end))) { break; } + name += len; + } + return GRN_SUCCESS; +} + +static grn_obj * +grn_type_open(grn_ctx *ctx, grn_obj_spec *spec) +{ + struct _grn_type *res; + res = GRN_MALLOC(sizeof(struct _grn_type)); + if (res) { + GRN_DB_OBJ_SET_TYPE(res, GRN_TYPE); + res->obj.header = spec->header; + GRN_TYPE_SIZE(&res->obj) = GRN_TYPE_SIZE(spec); + } + return (grn_obj *)res; +} + +grn_obj * +grn_proc_create(grn_ctx *ctx, const char *name, int name_size, grn_proc_type type, + grn_proc_func *init, grn_proc_func *next, grn_proc_func *fin, + unsigned int nvars, grn_expr_var *vars) +{ + grn_proc *res = NULL; + grn_id id = GRN_ID_NIL; + grn_id range = GRN_ID_NIL; + int added = 0; + grn_obj *db; + const char *path; + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "db not initialized"); + return NULL; + } + GRN_API_ENTER; + path = ctx->impl->plugin_path; + if (path) { + range = grn_plugin_reference(ctx, path); + } + if (name_size < 0) { + name_size = strlen(name); + } + if (grn_db_check_name(ctx, name, name_size)) { + GRN_DB_CHECK_NAME_ERR("[proc][create]", name, name_size); + GRN_API_RETURN(NULL); + } + if (!GRN_DB_P(db)) { + ERR(GRN_INVALID_ARGUMENT, "invalid db assigned"); + GRN_API_RETURN(NULL); + } + if (name && name_size) { + grn_db *s = (grn_db *)db; + if (!(id = grn_table_get(ctx, s->keys, name, name_size))) { + if (!(id = grn_table_add(ctx, s->keys, name, name_size, &added))) { + ERR(GRN_NO_MEMORY_AVAILABLE, "grn_table_add failed"); + GRN_API_RETURN(NULL); + } + } + if (!added) { + db_value *vp; + if ((vp = grn_tiny_array_at(&s->values, id)) && (res = (grn_proc *)vp->ptr)) { + /* TODO: Do more robust check. */ + if (res->funcs[PROC_INIT] || + res->funcs[PROC_NEXT] || + res->funcs[PROC_FIN]) { + ERR(GRN_INVALID_ARGUMENT, "already used name"); + GRN_API_RETURN(NULL); + } + if (range != GRN_ID_NIL) { + grn_plugin_close(ctx, range); + } + GRN_API_RETURN((grn_obj *)res); + } else { + added = 1; + } + } + } else if (ctx->impl && ctx->impl->values) { + id = grn_array_add(ctx, ctx->impl->values, NULL) | GRN_OBJ_TMP_OBJECT; + added = 1; + } + if (!res) { res = GRN_MALLOCN(grn_proc, 1); } + if (res) { + GRN_DB_OBJ_SET_TYPE(res, GRN_PROC); + res->obj.db = db; + res->obj.id = id; + res->obj.header.domain = GRN_ID_NIL; + res->obj.header.flags = path ? GRN_OBJ_CUSTOM_NAME : 0; + res->obj.range = range; + res->type = type; + res->funcs[PROC_INIT] = init; + res->funcs[PROC_NEXT] = next; + res->funcs[PROC_FIN] = fin; + memset(&(res->callbacks), 0, sizeof(res->callbacks)); + res->callbacks.function.selector_op = GRN_OP_NOP; + res->callbacks.function.is_stable = GRN_TRUE; + GRN_TEXT_INIT(&res->name_buf, 0); + res->vars = NULL; + res->nvars = 0; + if (added) { + if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) { + // grn_obj_delete(ctx, db, id); + GRN_FREE(res); + GRN_API_RETURN(NULL); + } + } + while (nvars--) { + grn_obj *v = grn_expr_add_var(ctx, (grn_obj *)res, vars->name, vars->name_size); + GRN_OBJ_INIT(v, vars->value.header.type, 0, vars->value.header.domain); + GRN_TEXT_PUT(ctx, v, GRN_TEXT_VALUE(&vars->value), GRN_TEXT_LEN(&vars->value)); + vars++; + } + } + GRN_API_RETURN((grn_obj *)res); +} + +/* grn_table */ + +static void +calc_rec_size(grn_table_flags flags, uint32_t max_n_subrecs, uint32_t range_size, + uint32_t additional_value_size, + uint8_t *subrec_size, uint8_t *subrec_offset, + uint32_t *key_size, uint32_t *value_size) +{ + *subrec_size = 0; + *subrec_offset = 0; + if (flags & GRN_OBJ_WITH_SUBREC) { + switch (flags & GRN_OBJ_UNIT_MASK) { + case GRN_OBJ_UNIT_DOCUMENT_NONE : + break; + case GRN_OBJ_UNIT_DOCUMENT_SECTION : + *subrec_offset = sizeof(grn_id); + *subrec_size = sizeof(uint32_t); + break; + case GRN_OBJ_UNIT_DOCUMENT_POSITION : + *subrec_offset = sizeof(grn_id); + *subrec_size = sizeof(uint32_t) + sizeof(uint32_t); + break; + case GRN_OBJ_UNIT_SECTION_NONE : + *key_size += sizeof(uint32_t); + break; + case GRN_OBJ_UNIT_SECTION_POSITION : + *key_size += sizeof(uint32_t); + *subrec_offset = sizeof(grn_id) + sizeof(uint32_t); + *subrec_size = sizeof(uint32_t); + break; + case GRN_OBJ_UNIT_POSITION_NONE : + *key_size += sizeof(uint32_t) + sizeof(uint32_t); + break; + case GRN_OBJ_UNIT_USERDEF_DOCUMENT : + *subrec_size = range_size; + break; + case GRN_OBJ_UNIT_USERDEF_SECTION : + *subrec_size = range_size + sizeof(uint32_t); + break; + case GRN_OBJ_UNIT_USERDEF_POSITION : + *subrec_size = range_size + sizeof(uint32_t) + sizeof(uint32_t); + break; + } + *value_size = (uintptr_t)GRN_RSET_SUBRECS_NTH((((grn_rset_recinfo *)0)->subrecs), + *subrec_size, max_n_subrecs); + } else { + *value_size = range_size; + } + *value_size += additional_value_size; +} + +static grn_rc _grn_obj_remove(grn_ctx *ctx, grn_obj *obj, grn_bool dependent); + +static grn_rc +grn_table_create_validate(grn_ctx *ctx, const char *name, unsigned int name_size, + const char *path, grn_table_flags flags, + grn_obj *key_type, grn_obj *value_type) +{ + grn_table_flags table_type; + const char *table_type_name = NULL; + + table_type = (flags & GRN_OBJ_TABLE_TYPE_MASK); + switch (table_type) { + case GRN_OBJ_TABLE_HASH_KEY : + table_type_name = "TABLE_HASH_KEY"; + break; + case GRN_OBJ_TABLE_PAT_KEY : + table_type_name = "TABLE_PAT_KEY"; + break; + case GRN_OBJ_TABLE_DAT_KEY : + table_type_name = "TABLE_DAT_KEY"; + break; + case GRN_OBJ_TABLE_NO_KEY : + table_type_name = "TABLE_NO_KEY"; + break; + default : + table_type_name = "unknown"; + break; + } + + if (!key_type && table_type != GRN_OBJ_TABLE_NO_KEY && + !(flags & GRN_OBJ_KEY_VAR_SIZE)) { + ERR(GRN_INVALID_ARGUMENT, + "[table][create] " + "key type is required for TABLE_HASH_KEY, TABLE_PAT_KEY or " + "TABLE_DAT_KEY: <%.*s>", name_size, name); + return ctx->rc; + } + + if (key_type && table_type == GRN_OBJ_TABLE_NO_KEY) { + int key_name_size; + char key_name[GRN_TABLE_MAX_KEY_SIZE]; + key_name_size = grn_obj_name(ctx, key_type, key_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[table][create] " + "key isn't available for TABLE_NO_KEY table: <%.*s> (%.*s)", + name_size, name, key_name_size, key_name); + return ctx->rc; + } + + if ((flags & GRN_OBJ_KEY_WITH_SIS) && + table_type != GRN_OBJ_TABLE_PAT_KEY) { + ERR(GRN_INVALID_ARGUMENT, + "[table][create] " + "key with SIS is available only for TABLE_PAT_KEY table: " + "<%.*s>(%s)", + name_size, name, + table_type_name); + return ctx->rc; + } + + if ((flags & GRN_OBJ_KEY_NORMALIZE) && + table_type == GRN_OBJ_TABLE_NO_KEY) { + ERR(GRN_INVALID_ARGUMENT, + "[table][create] " + "key normalization isn't available for TABLE_NO_KEY table: <%.*s>", + name_size, name); + return ctx->rc; + } + + if ((flags & GRN_OBJ_KEY_LARGE) && + table_type != GRN_OBJ_TABLE_HASH_KEY) { + ERR(GRN_INVALID_ARGUMENT, + "[table][create] " + "large key support is available only for TABLE_HASH_KEY key table: " + "<%.*s>(%s)", + name_size, name, + table_type_name); + return ctx->rc; + } + + return ctx->rc; +} + +static grn_obj * +grn_table_create_with_max_n_subrecs(grn_ctx *ctx, const char *name, + unsigned int name_size, const char *path, + grn_table_flags flags, grn_obj *key_type, + grn_obj *value_type, + uint32_t max_n_subrecs, + uint32_t additional_value_size) +{ + grn_id id; + grn_id domain = GRN_ID_NIL, range = GRN_ID_NIL; + uint32_t key_size, value_size = 0, range_size = 0; + uint8_t subrec_size, subrec_offset; + grn_obj *res = NULL; + grn_obj *db; + char buffer[PATH_MAX]; + if (!ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "[table][create] db not initialized"); + return NULL; + } + if (grn_db_check_name(ctx, name, name_size)) { + GRN_DB_CHECK_NAME_ERR("[table][create]", name, name_size); + return NULL; + } + if (!GRN_DB_P(db)) { + ERR(GRN_INVALID_ARGUMENT, "[table][create] invalid db assigned"); + return NULL; + } + if (grn_table_create_validate(ctx, name, name_size, path, flags, + key_type, value_type)) { + return NULL; + } + if (key_type) { + domain = DB_OBJ(key_type)->id; + switch (key_type->header.type) { + case GRN_TYPE : + { + grn_db_obj *t = (grn_db_obj *)key_type; + flags |= t->header.flags; + key_size = GRN_TYPE_SIZE(t); + if (key_size > GRN_TABLE_MAX_KEY_SIZE) { + int type_name_size; + char type_name[GRN_TABLE_MAX_KEY_SIZE]; + type_name_size = grn_obj_name(ctx, key_type, type_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[table][create] key size too big: <%.*s> <%.*s>(%u) (max:%u)", + name_size, name, + type_name_size, type_name, + key_size, GRN_TABLE_MAX_KEY_SIZE); + return NULL; + } + } + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + key_size = sizeof(grn_id); + break; + default : + { + int key_name_size; + char key_name[GRN_TABLE_MAX_KEY_SIZE]; + key_name_size = grn_obj_name(ctx, key_type, key_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[table][create] key type must be type or table: <%.*s> (%.*s)", + name_size, name, key_name_size, key_name); + return NULL; + } + break; + } + } else { + key_size = (flags & GRN_OBJ_KEY_VAR_SIZE) ? GRN_TABLE_MAX_KEY_SIZE : sizeof(grn_id); + } + if (value_type) { + range = DB_OBJ(value_type)->id; + switch (value_type->header.type) { + case GRN_TYPE : + { + grn_db_obj *t = (grn_db_obj *)value_type; + if (t->header.flags & GRN_OBJ_KEY_VAR_SIZE) { + int type_name_size; + char type_name[GRN_TABLE_MAX_KEY_SIZE]; + type_name_size = grn_obj_name(ctx, value_type, type_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[table][create] value type must be fixed size: <%.*s> (%.*s)", + name_size, name, type_name_size, type_name); + return NULL; + } + range_size = GRN_TYPE_SIZE(t); + } + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + range_size = sizeof(grn_id); + break; + default : + { + int value_name_size; + char value_name[GRN_TABLE_MAX_KEY_SIZE]; + value_name_size = grn_obj_name(ctx, value_type, value_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[table][create] value type must be type or table: <%.*s> (%.*s)", + name_size, name, value_name_size, value_name); + return NULL; + } + break; + } + } + + id = grn_obj_register(ctx, db, name, name_size); + if (ERRP(ctx, GRN_ERROR)) { return NULL; } + if (GRN_OBJ_PERSISTENT & flags) { + GRN_LOG(ctx, GRN_LOG_NOTICE, + "DDL:%u:table_create %.*s", id, name_size, name); + if (!path) { + if (GRN_DB_PERSISTENT_P(db)) { + grn_db_generate_pathname(ctx, db, id, buffer); + path = buffer; + } else { + ERR(GRN_INVALID_ARGUMENT, "path not assigned for persistent table"); + grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + return NULL; + } + } else { + flags |= GRN_OBJ_CUSTOM_NAME; + } + } else { + if (path) { + ERR(GRN_INVALID_ARGUMENT, "path assigned for temporary table"); + grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + return NULL; + } + if (GRN_DB_PERSISTENT_P(db) && name && name_size) { + ERR(GRN_INVALID_ARGUMENT, "name assigned for temporary table"); + grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + return NULL; + } + } + calc_rec_size(flags, max_n_subrecs, range_size, additional_value_size, + &subrec_size, &subrec_offset, &key_size, &value_size); + switch (flags & GRN_OBJ_TABLE_TYPE_MASK) { + case GRN_OBJ_TABLE_HASH_KEY : + res = (grn_obj *)grn_hash_create(ctx, path, key_size, value_size, flags); + break; + case GRN_OBJ_TABLE_PAT_KEY : + res = (grn_obj *)grn_pat_create(ctx, path, key_size, value_size, flags); + break; + case GRN_OBJ_TABLE_DAT_KEY : + res = (grn_obj *)grn_dat_create(ctx, path, key_size, value_size, flags); + break; + case GRN_OBJ_TABLE_NO_KEY : + domain = range; + res = (grn_obj *)grn_array_create(ctx, path, value_size, flags); + break; + } + if (res) { + DB_OBJ(res)->header.impl_flags = 0; + DB_OBJ(res)->header.domain = domain; + DB_OBJ(res)->range = range; + DB_OBJ(res)->max_n_subrecs = max_n_subrecs; + DB_OBJ(res)->subrec_size = subrec_size; + DB_OBJ(res)->subrec_offset = subrec_offset; + DB_OBJ(res)->flags.group = 0; + if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) { + _grn_obj_remove(ctx, res, GRN_FALSE); + res = NULL; + } + } else { + grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + } + return res; +} + +grn_obj * +grn_table_create(grn_ctx *ctx, const char *name, unsigned int name_size, + const char *path, grn_table_flags flags, + grn_obj *key_type, grn_obj *value_type) +{ + grn_obj *res; + GRN_API_ENTER; + res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path, + flags, key_type, value_type, + 0, 0); + GRN_API_RETURN(res); +} + +grn_obj * +grn_table_create_for_group(grn_ctx *ctx, const char *name, + unsigned int name_size, const char *path, + grn_obj *group_key, grn_obj *value_type, + unsigned int max_n_subrecs) +{ + grn_obj *res = NULL; + GRN_API_ENTER; + if (group_key) { + grn_obj *key_type; + key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, group_key)); + if (key_type) { + res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path, + GRN_TABLE_HASH_KEY| + GRN_OBJ_WITH_SUBREC| + GRN_OBJ_UNIT_USERDEF_DOCUMENT, + key_type, value_type, + max_n_subrecs, 0); + grn_obj_unlink(ctx, key_type); + } + } else { + res = grn_table_create_with_max_n_subrecs(ctx, name, name_size, path, + GRN_TABLE_HASH_KEY| + GRN_OBJ_KEY_VAR_SIZE| + GRN_OBJ_WITH_SUBREC| + GRN_OBJ_UNIT_USERDEF_DOCUMENT, + NULL, value_type, + max_n_subrecs, 0); + } + GRN_API_RETURN(res); +} + +unsigned int +grn_table_get_subrecs(grn_ctx *ctx, grn_obj *table, grn_id id, + grn_id *subrecbuf, int *scorebuf, int buf_size) +{ + unsigned int count = 0; + GRN_API_ENTER; + if (GRN_OBJ_TABLEP(table)) { + uint32_t value_size; + grn_rset_recinfo *ri; + uint32_t subrec_size = DB_OBJ(table)->subrec_size; + uint32_t max_n_subrecs = DB_OBJ(table)->max_n_subrecs; + if (subrec_size < sizeof(grn_id)) { goto exit; } + if (!max_n_subrecs) { goto exit; } + ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, table, id, &value_size); + if (ri) { + byte *psubrec = (byte *)ri->subrecs; + uint32_t n_subrecs = (uint32_t)GRN_RSET_N_SUBRECS(ri); + uint32_t limit = value_size / (GRN_RSET_SCORE_SIZE + subrec_size); + if ((int) limit > buf_size) { + limit = buf_size; + } + if (limit > n_subrecs) { + limit = n_subrecs; + } + if (limit > max_n_subrecs) { + limit = max_n_subrecs; + } + for (; count < limit; count++) { + if (scorebuf) { + scorebuf[count] = *((double *)psubrec); + } + psubrec += GRN_RSET_SCORE_SIZE; + if (subrecbuf) { + subrecbuf[count] = *((grn_id *)psubrec); + } + psubrec += subrec_size; + } + } + } +exit : + GRN_API_RETURN(count); +} + +grn_obj * +grn_table_open(grn_ctx *ctx, const char *name, unsigned int name_size, const char *path) +{ + grn_obj *db; + if (!ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "db not initialized"); + return NULL; + } + GRN_API_ENTER; + if (!GRN_DB_P(db)) { + ERR(GRN_INVALID_ARGUMENT, "invalid db assigned"); + GRN_API_RETURN(NULL); + } else { + grn_obj *res = grn_ctx_get(ctx, name, name_size); + if (res) { + const char *path2 = grn_obj_path(ctx, res); + if (path && (!path2 || strcmp(path, path2))) { + ERR(GRN_INVALID_ARGUMENT, "path unmatch"); + GRN_API_RETURN(NULL); + } + } else if (path) { + uint32_t type = grn_io_detect_type(ctx, path); + if (!type) { GRN_API_RETURN(NULL); } + switch (type) { + case GRN_TABLE_HASH_KEY : + res = (grn_obj *)grn_hash_open(ctx, path); + break; + case GRN_TABLE_PAT_KEY : + res = (grn_obj *)grn_pat_open(ctx, path); + break; + case GRN_TABLE_DAT_KEY : + res = (grn_obj *)grn_dat_open(ctx, path); + break; + case GRN_TABLE_NO_KEY : + res = (grn_obj *)grn_array_open(ctx, path); + break; + } + if (res) { + grn_id id = grn_obj_register(ctx, db, name, name_size); + res->header.flags |= GRN_OBJ_CUSTOM_NAME; + res->header.domain = GRN_ID_NIL; /* unknown */ + DB_OBJ(res)->range = GRN_ID_NIL; /* unknown */ + grn_db_obj_init(ctx, db, id, DB_OBJ(res)); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "path is missing"); + } + GRN_API_RETURN(res); + } +} + +grn_id +grn_table_lcp_search(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size) +{ + grn_id id = GRN_ID_NIL; + GRN_API_ENTER; + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + { + grn_pat *pat = (grn_pat *)table; + WITH_NORMALIZE(pat, key, key_size, { + id = grn_pat_lcp_search(ctx, pat, key, key_size); + }); + } + break; + case GRN_TABLE_DAT_KEY : + { + grn_dat *dat = (grn_dat *)table; + WITH_NORMALIZE(dat, key, key_size, { + id = grn_dat_lcp_search(ctx, dat, key, key_size); + }); + } + break; + case GRN_TABLE_HASH_KEY : + { + grn_hash *hash = (grn_hash *)table; + WITH_NORMALIZE(hash, key, key_size, { + id = grn_hash_get(ctx, hash, key, key_size, NULL); + }); + } + break; + } + GRN_API_RETURN(id); +} + +grn_obj * +grn_obj_default_set_value_hook(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; + if (!pctx) { + ERR(GRN_INVALID_ARGUMENT, "default_set_value_hook failed"); + } else { + grn_obj *flags = grn_ctx_pop(ctx); + grn_obj *newvalue = grn_ctx_pop(ctx); + grn_obj *oldvalue = grn_ctx_pop(ctx); + grn_obj *id = grn_ctx_pop(ctx); + grn_hook *h = pctx->currh; + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(h); + grn_obj *target = grn_ctx_at(ctx, data->target); + int section = data->section; + if (flags) { /* todo */ } + if (target) { + switch (target->header.type) { + case GRN_COLUMN_INDEX : + grn_ii_column_update(ctx, (grn_ii *)target, + GRN_UINT32_VALUE(id), + section, oldvalue, newvalue, NULL); + } + } + } + return NULL; +} + +grn_id +grn_table_add(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size, int *added) +{ + grn_id id = GRN_ID_NIL; + GRN_API_ENTER; + if (table) { + int added_ = 0; + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + { + grn_pat *pat = (grn_pat *)table; + WITH_NORMALIZE(pat, key, key_size, { + if (pat->io && !(pat->io->flags & GRN_IO_TEMPORARY)) { + if (grn_io_lock(ctx, pat->io, grn_lock_timeout)) { + id = GRN_ID_NIL; + } else { + id = grn_pat_add(ctx, pat, key, key_size, NULL, &added_); + grn_io_unlock(pat->io); + } + } else { + id = grn_pat_add(ctx, pat, key, key_size, NULL, &added_); + } + }); + if (added) { *added = added_; } + } + break; + case GRN_TABLE_DAT_KEY : + { + grn_dat *dat = (grn_dat *)table; + WITH_NORMALIZE(dat, key, key_size, { + if (dat->io && !(dat->io->flags & GRN_IO_TEMPORARY)) { + if (grn_io_lock(ctx, dat->io, grn_lock_timeout)) { + id = GRN_ID_NIL; + } else { + id = grn_dat_add(ctx, dat, key, key_size, NULL, &added_); + grn_io_unlock(dat->io); + } + } else { + id = grn_dat_add(ctx, dat, key, key_size, NULL, &added_); + } + }); + if (added) { *added = added_; } + } + break; + case GRN_TABLE_HASH_KEY : + { + grn_hash *hash = (grn_hash *)table; + WITH_NORMALIZE(hash, key, key_size, { + if (hash->io && !(hash->io->flags & GRN_IO_TEMPORARY)) { + if (grn_io_lock(ctx, hash->io, grn_lock_timeout)) { + id = GRN_ID_NIL; + } else { + id = grn_hash_add(ctx, hash, key, key_size, NULL, &added_); + grn_io_unlock(hash->io); + } + } else { + id = grn_hash_add(ctx, hash, key, key_size, NULL, &added_); + } + }); + if (added) { *added = added_; } + } + break; + case GRN_TABLE_NO_KEY : + { + grn_array *array = (grn_array *)table; + if (array->io && !(array->io->flags & GRN_IO_TEMPORARY)) { + if (grn_io_lock(ctx, array->io, grn_lock_timeout)) { + id = GRN_ID_NIL; + } else { + id = grn_array_add(ctx, array, NULL); + grn_io_unlock(array->io); + } + } else { + id = grn_array_add(ctx, array, NULL); + } + added_ = id ? 1 : 0; + if (added) { *added = added_; } + } + break; + } + if (added_) { + grn_hook *hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; + if (hooks) { + // todo : grn_proc_ctx_open() + grn_obj id_, flags_, oldvalue_, value_; + grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4, {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}}}; + GRN_UINT32_INIT(&id_, 0); + GRN_UINT32_INIT(&flags_, 0); + GRN_TEXT_INIT(&oldvalue_, 0); + GRN_TEXT_INIT(&value_, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET_REF(&value_, key, key_size); + GRN_UINT32_SET(ctx, &id_, id); + GRN_UINT32_SET(ctx, &flags_, GRN_OBJ_SET); + while (hooks) { + grn_ctx_push(ctx, &id_); + grn_ctx_push(ctx, &oldvalue_); + grn_ctx_push(ctx, &value_); + grn_ctx_push(ctx, &flags_); + pctx.caller = NULL; + pctx.currh = hooks; + if (hooks->proc) { + hooks->proc->funcs[PROC_INIT](ctx, 1, &table, &pctx.user_data); + } else { + grn_obj_default_set_value_hook(ctx, 1, &table, &pctx.user_data); + } + if (ctx->rc) { break; } + hooks = hooks->next; + pctx.offset++; + } + } + } + } + GRN_API_RETURN(id); +} + +grn_id +grn_table_get_by_key(grn_ctx *ctx, grn_obj *table, grn_obj *key) +{ + grn_id id = GRN_ID_NIL; + if (table->header.domain == key->header.domain) { + id = grn_table_get(ctx, table, GRN_TEXT_VALUE(key), GRN_TEXT_LEN(key)); + } else { + grn_rc rc; + grn_obj buf; + GRN_OBJ_INIT(&buf, GRN_BULK, 0, table->header.domain); + if ((rc = grn_obj_cast(ctx, key, &buf, GRN_TRUE))) { + grn_obj *domain = grn_ctx_at(ctx, table->header.domain); + ERR_CAST(table, domain, key); + } else { + id = grn_table_get(ctx, table, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); + } + GRN_OBJ_FIN(ctx, &buf); + } + return id; +} + +grn_id +grn_table_add_by_key(grn_ctx *ctx, grn_obj *table, grn_obj *key, int *added) +{ + grn_id id = GRN_ID_NIL; + if (table->header.domain == key->header.domain) { + id = grn_table_add(ctx, table, GRN_TEXT_VALUE(key), GRN_TEXT_LEN(key), added); + } else { + grn_rc rc; + grn_obj buf; + GRN_OBJ_INIT(&buf, GRN_BULK, 0, table->header.domain); + if ((rc = grn_obj_cast(ctx, key, &buf, GRN_TRUE))) { + grn_obj *domain = grn_ctx_at(ctx, table->header.domain); + ERR_CAST(table, domain, key); + } else { + id = grn_table_add(ctx, table, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf), added); + } + GRN_OBJ_FIN(ctx, &buf); + } + return id; +} + +grn_id +grn_table_get(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size) +{ + grn_id id = GRN_ID_NIL; + GRN_API_ENTER; + if (table) { + if (table->header.type == GRN_DB) { + grn_db *db = (grn_db *)table; + table = db->keys; + } + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + WITH_NORMALIZE((grn_pat *)table, key, key_size, { + id = grn_pat_get(ctx, (grn_pat *)table, key, key_size, NULL); + }); + break; + case GRN_TABLE_DAT_KEY : + WITH_NORMALIZE((grn_dat *)table, key, key_size, { + id = grn_dat_get(ctx, (grn_dat *)table, key, key_size, NULL); + }); + break; + case GRN_TABLE_HASH_KEY : + WITH_NORMALIZE((grn_hash *)table, key, key_size, { + id = grn_hash_get(ctx, (grn_hash *)table, key, key_size, NULL); + }); + break; + } + } + GRN_API_RETURN(id); +} + +grn_id +grn_table_at(grn_ctx *ctx, grn_obj *table, grn_id id) +{ + GRN_API_ENTER; + if (table) { + switch (table->header.type) { + case GRN_DB : + { + grn_db *db = (grn_db *)table; + id = grn_table_at(ctx, db->keys, id); + } + break; + case GRN_TABLE_PAT_KEY : + id = grn_pat_at(ctx, (grn_pat *)table, id); + break; + case GRN_TABLE_DAT_KEY : + id = grn_dat_at(ctx, (grn_dat *)table, id); + break; + case GRN_TABLE_HASH_KEY : + id = grn_hash_at(ctx, (grn_hash *)table, id); + break; + case GRN_TABLE_NO_KEY : + id = grn_array_at(ctx, (grn_array *)table, id); + break; + default : + id = GRN_ID_NIL; + } + } + GRN_API_RETURN(id); +} + +inline static grn_id +grn_table_add_v_inline(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, + void **value, int *added) +{ + grn_id id = GRN_ID_NIL; + if (!key || !key_size) { return GRN_ID_NIL; } + if (table) { + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + WITH_NORMALIZE((grn_pat *)table, key, key_size, { + id = grn_pat_add(ctx, (grn_pat *)table, key, key_size, value, added); + }); + break; + case GRN_TABLE_DAT_KEY : + WITH_NORMALIZE((grn_dat *)table, key, key_size, { + id = grn_dat_add(ctx, (grn_dat *)table, key, key_size, value, added); + }); + break; + case GRN_TABLE_HASH_KEY : + WITH_NORMALIZE((grn_hash *)table, key, key_size, { + id = grn_hash_add(ctx, (grn_hash *)table, key, key_size, value, added); + }); + break; + case GRN_TABLE_NO_KEY : + id = grn_array_add(ctx, (grn_array *)table, value); + if (added) { *added = id ? 1 : 0; } + break; + } + } + return id; +} + +grn_id +grn_table_add_v(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, + void **value, int *added) { + grn_id id; + GRN_API_ENTER; + id = grn_table_add_v_inline(ctx, table, key, key_size, value, added); + GRN_API_RETURN(id); +} + +grn_id +grn_table_get_v(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, + void **value) +{ + grn_id id = GRN_ID_NIL; + GRN_API_ENTER; + if (table) { + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + WITH_NORMALIZE((grn_pat *)table, key, key_size, { + id = grn_pat_get(ctx, (grn_pat *)table, key, key_size, value); + }); + break; + case GRN_TABLE_DAT_KEY : + WITH_NORMALIZE((grn_dat *)table, key, key_size, { + id = grn_dat_get(ctx, (grn_dat *)table, key, key_size, value); + }); + break; + case GRN_TABLE_HASH_KEY : + WITH_NORMALIZE((grn_hash *)table, key, key_size, { + id = grn_hash_get(ctx, (grn_hash *)table, key, key_size, value); + }); + break; + } + } + GRN_API_RETURN(id); +} + +int +grn_table_get_key(grn_ctx *ctx, grn_obj *table, grn_id id, void *keybuf, int buf_size) +{ + int r = 0; + GRN_API_ENTER; + if (table) { + if (table->header.type == GRN_DB) { + table = ((grn_db *)table)->keys; + } + switch (table->header.type) { + case GRN_TABLE_HASH_KEY : + r = grn_hash_get_key(ctx, (grn_hash *)table, id, keybuf, buf_size); + break; + case GRN_TABLE_PAT_KEY : + r = grn_pat_get_key(ctx, (grn_pat *)table, id, keybuf, buf_size); + break; + case GRN_TABLE_DAT_KEY : + r = grn_dat_get_key(ctx, (grn_dat *)table, id, keybuf, buf_size); + break; + case GRN_TABLE_NO_KEY : + { + grn_array *a = (grn_array *)table; + if (a->obj.header.domain) { + if ((unsigned int) buf_size >= a->value_size) { + r = grn_array_get_value(ctx, a, id, keybuf); + } else { + r = a->value_size; + } + } + } + break; + } + } + GRN_API_RETURN(r); +} + +int +grn_table_get_key2(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *bulk) +{ + int r = 0; + GRN_API_ENTER; + if (table) { + if (table->header.type == GRN_DB) { + table = ((grn_db *)table)->keys; + } + switch (table->header.type) { + case GRN_TABLE_HASH_KEY : + r = grn_hash_get_key2(ctx, (grn_hash *)table, id, bulk); + break; + case GRN_TABLE_PAT_KEY : + r = grn_pat_get_key2(ctx, (grn_pat *)table, id, bulk); + break; + case GRN_TABLE_DAT_KEY : + r = grn_dat_get_key2(ctx, (grn_dat *)table, id, bulk); + break; + case GRN_TABLE_NO_KEY : + { + grn_array *a = (grn_array *)table; + if (a->obj.header.domain) { + if (!grn_bulk_space(ctx, bulk, a->value_size)) { + char *curr = GRN_BULK_CURR(bulk); + r = grn_array_get_value(ctx, a, id, curr - a->value_size); + } + } + } + break; + } + } + GRN_API_RETURN(r); +} + +static grn_rc +grn_obj_clear_value(grn_ctx *ctx, grn_obj *obj, grn_id id) +{ + grn_rc rc = GRN_SUCCESS; + if (GRN_DB_OBJP(obj)) { + grn_obj buf; + grn_id range = DB_OBJ(obj)->range; + GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); + switch (obj->header.type) { + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_FIX_SIZE : + rc = grn_obj_set_value(ctx, obj, id, &buf, GRN_OBJ_SET); + break; + } + GRN_OBJ_FIN(ctx, &buf); + } + return rc; +} + +static void +call_delete_hook(grn_ctx *ctx, grn_obj *table, grn_id rid, const void *key, unsigned int key_size) +{ + if (rid) { + grn_hook *hooks = DB_OBJ(table)->hooks[GRN_HOOK_DELETE]; + if (hooks) { + // todo : grn_proc_ctx_open() + grn_obj id_, flags_, oldvalue_, value_; + grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4, {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}}}; + GRN_UINT32_INIT(&id_, 0); + GRN_UINT32_INIT(&flags_, 0); + GRN_TEXT_INIT(&oldvalue_, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_INIT(&value_, 0); + GRN_TEXT_SET_REF(&oldvalue_, key, key_size); + GRN_UINT32_SET(ctx, &id_, rid); + GRN_UINT32_SET(ctx, &flags_, GRN_OBJ_SET); + while (hooks) { + grn_ctx_push(ctx, &id_); + grn_ctx_push(ctx, &oldvalue_); + grn_ctx_push(ctx, &value_); + grn_ctx_push(ctx, &flags_); + pctx.caller = NULL; + pctx.currh = hooks; + if (hooks->proc) { + hooks->proc->funcs[PROC_INIT](ctx, 1, &table, &pctx.user_data); + } else { + grn_obj_default_set_value_hook(ctx, 1, &table, &pctx.user_data); + } + if (ctx->rc) { break; } + hooks = hooks->next; + pctx.offset++; + } + } + } +} + +static void +clear_column_values(grn_ctx *ctx, grn_obj *table, grn_id rid) +{ + if (rid) { + grn_hash *cols; + if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { + if (grn_table_columns(ctx, table, "", 0, (grn_obj *)cols)) { + grn_id *key; + GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { + grn_obj *col = grn_ctx_at(ctx, *key); + if (col) { grn_obj_clear_value(ctx, col, rid); } + }); + } + grn_hash_close(ctx, cols); + } + } +} + +static void +delete_reference_records_in_index(grn_ctx *ctx, grn_obj *table, grn_id id, + grn_obj *index) +{ + grn_ii *ii = (grn_ii *)index; + grn_ii_cursor *ii_cursor = NULL; + grn_posting *posting; + grn_obj source_ids; + unsigned int i, n_ids; + grn_obj sources; + grn_bool have_reference_source = GRN_FALSE; + + GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); + GRN_PTR_INIT(&sources, GRN_OBJ_VECTOR, 0); + + grn_obj_get_info(ctx, index, GRN_INFO_SOURCE, &source_ids); + n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); + if (n_ids == 0) { + goto exit; + } + + for (i = 0; i < n_ids; i++) { + grn_id source_id; + grn_obj *source; + + source_id = GRN_UINT32_VALUE_AT(&source_ids, i); + source = grn_ctx_at(ctx, source_id); + if (grn_obj_get_range(ctx, source) == index->header.domain) { + GRN_PTR_PUT(ctx, &sources, source); + have_reference_source = GRN_TRUE; + } else { + grn_obj_unlink(ctx, source); + GRN_PTR_PUT(ctx, &sources, NULL); + } + } + + if (!have_reference_source) { + goto exit; + } + + ii_cursor = grn_ii_cursor_open(ctx, ii, id, GRN_ID_NIL, GRN_ID_MAX, + ii->n_elements, 0); + if (!ii_cursor) { + goto exit; + } + + while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) { + grn_obj *source = GRN_PTR_VALUE_AT(&sources, posting->sid - 1); + if (!source) { + continue; + } + switch (source->header.type) { + case GRN_COLUMN_VAR_SIZE : + switch (source->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { + case GRN_OBJ_COLUMN_SCALAR : + grn_obj_clear_value(ctx, source, posting->rid); + break; + case GRN_OBJ_COLUMN_VECTOR : + { + grn_obj value; + grn_obj new_value; + GRN_TEXT_INIT(&value, 0); + grn_obj_get_value(ctx, source, posting->rid, &value); + if (value.header.type == GRN_UVECTOR) { + int i, n_ids; + GRN_RECORD_INIT(&new_value, GRN_OBJ_VECTOR, value.header.domain); + n_ids = GRN_BULK_VSIZE(&value) / sizeof(grn_id); + for (i = 0; i < n_ids; i++) { + grn_id reference_id = GRN_RECORD_VALUE_AT(&value, i); + if (reference_id == id) { + continue; + } + GRN_RECORD_PUT(ctx, &new_value, reference_id); + } + } else { + unsigned int i, n_elements; + GRN_TEXT_INIT(&new_value, GRN_OBJ_VECTOR); + n_elements = grn_vector_size(ctx, &value); + for (i = 0; i < n_elements; i++) { + const char *content; + unsigned int content_length; + unsigned int weight; + grn_id domain; + content_length = + grn_vector_get_element(ctx, &value, i, + &content, &weight, &domain); + if (grn_table_get(ctx, table, content, content_length) == id) { + continue; + } + grn_vector_add_element(ctx, &new_value, content, content_length, + weight, domain); + } + } + grn_obj_set_value(ctx, source, posting->rid, &new_value, + GRN_OBJ_SET); + GRN_OBJ_FIN(ctx, &new_value); + GRN_OBJ_FIN(ctx, &value); + } + break; + } + break; + case GRN_COLUMN_FIX_SIZE : + grn_obj_clear_value(ctx, source, posting->rid); + break; + } + } + +exit: + if (ii_cursor) { + grn_ii_cursor_close(ctx, ii_cursor); + } + grn_obj_unlink(ctx, &source_ids); + { + int i, n_sources; + n_sources = GRN_BULK_VSIZE(&sources) / sizeof(grn_obj *); + for (i = 0; i < n_sources; i++) { + grn_obj *source = GRN_PTR_VALUE_AT(&sources, i); + grn_obj_unlink(ctx, source); + } + grn_obj_unlink(ctx, &sources); + } +} + +static grn_rc +delete_reference_records(grn_ctx *ctx, grn_obj *table, grn_id id) +{ + grn_hash *cols; + grn_id *key; + + cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); + if (!cols) { + return ctx->rc; + } + + if (!grn_table_columns(ctx, table, "", 0, (grn_obj *)cols)) { + grn_hash_close(ctx, cols); + return ctx->rc; + } + + GRN_HASH_EACH(ctx, cols, tid, &key, NULL, NULL, { + grn_obj *col = grn_ctx_at(ctx, *key); + if (!col) { + continue; + } + if (col->header.type != GRN_COLUMN_INDEX) { + continue; + } + delete_reference_records_in_index(ctx, table, id, col); + if (ctx->rc != GRN_SUCCESS) { + break; + } + }); + + grn_hash_close(ctx, cols); + + return ctx->rc; +} + +static grn_rc +grn_table_delete_prepare(grn_ctx *ctx, grn_obj *table, + grn_id id, const void *key, unsigned int key_size) +{ + grn_rc rc; + + rc = delete_reference_records(ctx, table, id); + if (rc != GRN_SUCCESS) { + return rc; + } + call_delete_hook(ctx, table, id, key, key_size); + clear_column_values(ctx, table, id); + + return rc; +} + +grn_rc +grn_table_delete(grn_ctx *ctx, grn_obj *table, const void *key, unsigned int key_size) +{ + grn_id rid = GRN_ID_NIL; + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (table) { + if (key && key_size) { rid = grn_table_get(ctx, table, key, key_size); } + if (rid) { + rc = grn_table_delete_prepare(ctx, table, rid, key, key_size); + if (rc != GRN_SUCCESS) { + goto exit; + } + switch (table->header.type) { + case GRN_DB : + /* todo : delete tables and columns from db */ + break; + case GRN_TABLE_PAT_KEY : + WITH_NORMALIZE((grn_pat *)table, key, key_size, { + grn_pat *pat = (grn_pat *)table; + if (pat->io && !(pat->io->flags & GRN_IO_TEMPORARY)) { + if (!(rc = grn_io_lock(ctx, pat->io, grn_lock_timeout))) { + rc = grn_pat_delete(ctx, pat, key, key_size, NULL); + grn_io_unlock(pat->io); + } + } else { + rc = grn_pat_delete(ctx, pat, key, key_size, NULL); + } + }); + break; + case GRN_TABLE_DAT_KEY : + WITH_NORMALIZE((grn_dat *)table, key, key_size, { + grn_dat *dat = (grn_dat *)table; + if (dat->io && !(dat->io->flags & GRN_IO_TEMPORARY)) { + if (!(rc = grn_io_lock(ctx, dat->io, grn_lock_timeout))) { + rc = grn_dat_delete(ctx, dat, key, key_size, NULL); + grn_io_unlock(dat->io); + } + } else { + rc = grn_dat_delete(ctx, dat, key, key_size, NULL); + } + }); + break; + case GRN_TABLE_HASH_KEY : + WITH_NORMALIZE((grn_hash *)table, key, key_size, { + grn_hash *hash = (grn_hash *)table; + if (hash->io && !(hash->io->flags & GRN_IO_TEMPORARY)) { + if (!(rc = grn_io_lock(ctx, hash->io, grn_lock_timeout))) { + rc = grn_hash_delete(ctx, hash, key, key_size, NULL); + grn_io_unlock(hash->io); + } + } else { + rc = grn_hash_delete(ctx, hash, key, key_size, NULL); + } + }); + break; + } + if (rc == GRN_SUCCESS) { + grn_obj_touch(ctx, table, NULL); + } + } + } +exit : + GRN_API_RETURN(rc); +} + +grn_rc +_grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, + grn_table_delete_optarg *optarg) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + if (table) { + if (id) { + const void *key = NULL; + unsigned int key_size = 0; + + if (table->header.type != GRN_TABLE_NO_KEY) { + key = _grn_table_key(ctx, table, id, &key_size); + } + rc = grn_table_delete_prepare(ctx, table, id, key, key_size); + if (rc != GRN_SUCCESS) { + goto exit; + } + // todo : support optarg + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + rc = grn_pat_delete_by_id(ctx, (grn_pat *)table, id, optarg); + break; + case GRN_TABLE_DAT_KEY : + rc = grn_dat_delete_by_id(ctx, (grn_dat *)table, id, optarg); + break; + case GRN_TABLE_HASH_KEY : + rc = grn_hash_delete_by_id(ctx, (grn_hash *)table, id, optarg); + break; + case GRN_TABLE_NO_KEY : + rc = grn_array_delete_by_id(ctx, (grn_array *)table, id, optarg); + break; + } + } + } +exit : + return rc; +} + +grn_rc +grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id) +{ + grn_rc rc; + grn_io *io; + GRN_API_ENTER; + if ((io = grn_obj_get_io(ctx, table)) && !(io->flags & GRN_IO_TEMPORARY)) { + if (!(rc = grn_io_lock(ctx, io, grn_lock_timeout))) { + rc = _grn_table_delete_by_id(ctx, table, id, NULL); + grn_io_unlock(io); + } + } else { + rc = _grn_table_delete_by_id(ctx, table, id, NULL); + } + if (rc == GRN_SUCCESS) { + grn_obj_touch(ctx, table, NULL); + } + GRN_API_RETURN(rc); +} + +grn_rc grn_ja_truncate(grn_ctx *ctx, grn_ja *ja); +grn_rc grn_ra_truncate(grn_ctx *ctx, grn_ra *ra); + +grn_rc +grn_column_truncate(grn_ctx *ctx, grn_obj *column) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (column) { + grn_hook *hooks; + switch (column->header.type) { + case GRN_COLUMN_INDEX : + rc = grn_ii_truncate(ctx, (grn_ii *)column); + break; + case GRN_COLUMN_VAR_SIZE : + for (hooks = DB_OBJ(column)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } + } + rc = grn_ja_truncate(ctx, (grn_ja *)column); + break; + case GRN_COLUMN_FIX_SIZE : + for (hooks = DB_OBJ(column)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } + } + rc = grn_ra_truncate(ctx, (grn_ra *)column); + break; + } + if (rc == GRN_SUCCESS) { + grn_obj_touch(ctx, column, NULL); + } + } +exit : + GRN_API_RETURN(rc); +} + +grn_rc +grn_table_truncate(grn_ctx *ctx, grn_obj *table) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (table) { + grn_hook *hooks; + grn_hash *cols; + grn_obj *tokenizer; + grn_obj *normalizer; + grn_obj token_filters; + if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { + if (grn_table_columns(ctx, table, "", 0, (grn_obj *)cols)) { + grn_id *key; + GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { + grn_obj *col = grn_ctx_at(ctx, *key); + if (col) { grn_column_truncate(ctx, col); } + }); + } + grn_hash_close(ctx, cols); + } + if (table->header.type != GRN_TABLE_NO_KEY) { + grn_table_get_info(ctx, table, NULL, NULL, &tokenizer, &normalizer, NULL); + GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, GRN_ID_NIL); + grn_obj_get_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); + } + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + for (hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } + } + rc = grn_pat_truncate(ctx, (grn_pat *)table); + break; + case GRN_TABLE_DAT_KEY : + for (hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } + } + rc = grn_dat_truncate(ctx, (grn_dat *)table); + break; + case GRN_TABLE_HASH_KEY : + for (hooks = DB_OBJ(table)->hooks[GRN_HOOK_INSERT]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + if ((rc = grn_ii_truncate(ctx, (grn_ii *)target))) { goto exit; } + } + rc = grn_hash_truncate(ctx, (grn_hash *)table); + break; + case GRN_TABLE_NO_KEY : + rc = grn_array_truncate(ctx, (grn_array *)table); + break; + } + if (table->header.type != GRN_TABLE_NO_KEY) { + grn_obj_set_info(ctx, table, GRN_INFO_DEFAULT_TOKENIZER, tokenizer); + grn_obj_set_info(ctx, table, GRN_INFO_NORMALIZER, normalizer); + grn_obj_set_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); + GRN_OBJ_FIN(ctx, &token_filters); + } + if (rc == GRN_SUCCESS) { + grn_obj_touch(ctx, table, NULL); + } + } +exit : + GRN_API_RETURN(rc); +} + +grn_rc +grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_table_flags *flags, + grn_encoding *encoding, grn_obj **tokenizer, + grn_obj **normalizer, + grn_obj **token_filters) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (table) { + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + if (flags) { *flags = ((grn_pat *)table)->header->flags; } + if (encoding) { *encoding = ((grn_pat *)table)->encoding; } + if (tokenizer) { *tokenizer = ((grn_pat *)table)->tokenizer; } + if (normalizer) { *normalizer = ((grn_pat *)table)->normalizer; } + if (token_filters) { *token_filters = &(((grn_pat *)table)->token_filters); } + rc = GRN_SUCCESS; + break; + case GRN_TABLE_DAT_KEY : + if (flags) { *flags = ((grn_dat *)table)->header->flags; } + if (encoding) { *encoding = ((grn_dat *)table)->encoding; } + if (tokenizer) { *tokenizer = ((grn_dat *)table)->tokenizer; } + if (normalizer) { *normalizer = ((grn_dat *)table)->normalizer; } + if (token_filters) { *token_filters = &(((grn_dat *)table)->token_filters); } + rc = GRN_SUCCESS; + break; + case GRN_TABLE_HASH_KEY : + if (flags) { *flags = ((grn_hash *)table)->header.common->flags; } + if (encoding) { *encoding = ((grn_hash *)table)->encoding; } + if (tokenizer) { *tokenizer = ((grn_hash *)table)->tokenizer; } + if (normalizer) { *normalizer = ((grn_hash *)table)->normalizer; } + if (token_filters) { *token_filters = &(((grn_hash *)table)->token_filters); } + rc = GRN_SUCCESS; + break; + case GRN_TABLE_NO_KEY : + if (flags) { *flags = grn_array_get_flags(ctx, ((grn_array *)table)); } + if (encoding) { *encoding = GRN_ENC_NONE; } + if (tokenizer) { *tokenizer = NULL; } + if (normalizer) { *normalizer = NULL; } + if (token_filters) { *token_filters = NULL; } + rc = GRN_SUCCESS; + break; + } + } + GRN_API_RETURN(rc); +} + +unsigned int +grn_table_size(grn_ctx *ctx, grn_obj *table) +{ + unsigned int n = 0; + GRN_API_ENTER; + if (table) { + switch (table->header.type) { + case GRN_DB : + n = grn_table_size(ctx, ((grn_db *)table)->keys); + break; + case GRN_TABLE_PAT_KEY : + n = grn_pat_size(ctx, (grn_pat *)table); + break; + case GRN_TABLE_DAT_KEY : + n = grn_dat_size(ctx, (grn_dat *)table); + break; + case GRN_TABLE_HASH_KEY : + n = grn_hash_size(ctx, (grn_hash *)table); + break; + case GRN_TABLE_NO_KEY : + n = grn_array_size(ctx, (grn_array *)table); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "not supported"); + break; + } + } else { + ERR(GRN_INVALID_ARGUMENT, "invalid table assigned"); + } + GRN_API_RETURN(n); +} + +inline static void +subrecs_push(byte *subrecs, int size, int n_subrecs, double score, void *body, int dir) +{ + byte *v; + double *c2; + int n = n_subrecs - 1, n2; + while (n) { + n2 = (n - 1) >> 1; + c2 = GRN_RSET_SUBRECS_NTH(subrecs,size,n2); + if (GRN_RSET_SUBRECS_CMP(score, *c2, dir) >= 0) { break; } + GRN_RSET_SUBRECS_COPY(subrecs,size,n,c2); + n = n2; + } + v = subrecs + n * (GRN_RSET_SCORE_SIZE + size); + *((double *)v) = score; + grn_memcpy(v + GRN_RSET_SCORE_SIZE, body, size); +} + +inline static void +subrecs_replace_min(byte *subrecs, int size, int n_subrecs, double score, void *body, int dir) +{ + byte *v; + int n = 0, n1, n2; + double *c1, *c2; + for (;;) { + n1 = n * 2 + 1; + n2 = n1 + 1; + c1 = n1 < n_subrecs ? GRN_RSET_SUBRECS_NTH(subrecs,size,n1) : NULL; + c2 = n2 < n_subrecs ? GRN_RSET_SUBRECS_NTH(subrecs,size,n2) : NULL; + if (c1 && GRN_RSET_SUBRECS_CMP(score, *c1, dir) > 0) { + if (c2 && + GRN_RSET_SUBRECS_CMP(score, *c2, dir) > 0 && + GRN_RSET_SUBRECS_CMP(*c1, *c2, dir) > 0) { + GRN_RSET_SUBRECS_COPY(subrecs,size,n,c2); + n = n2; + } else { + GRN_RSET_SUBRECS_COPY(subrecs,size,n,c1); + n = n1; + } + } else { + if (c2 && GRN_RSET_SUBRECS_CMP(score, *c2, dir) > 0) { + GRN_RSET_SUBRECS_COPY(subrecs,size,n,c2); + n = n2; + } else { + break; + } + } + } + v = subrecs + n * (GRN_RSET_SCORE_SIZE + size); + grn_memcpy(v, &score, GRN_RSET_SCORE_SIZE); + grn_memcpy(v + GRN_RSET_SCORE_SIZE, body, size); +} + +inline static void +grn_table_add_subrec_inline(grn_obj *table, grn_rset_recinfo *ri, double score, + grn_rset_posinfo *pi, int dir) +{ + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + int limit = DB_OBJ(table)->max_n_subrecs; + ri->score += score; + ri->n_subrecs += 1; + if (limit) { + int subrec_size = DB_OBJ(table)->subrec_size; + int n_subrecs = GRN_RSET_N_SUBRECS(ri); + if (pi) { + byte *body = (byte *)pi + DB_OBJ(table)->subrec_offset; + if (limit < n_subrecs) { + if (GRN_RSET_SUBRECS_CMP(score, *((double *)(ri->subrecs)), dir) > 0) { + subrecs_replace_min((byte *)ri->subrecs, subrec_size, limit, score, body, dir); + } + } else { + subrecs_push((byte *)ri->subrecs, subrec_size, n_subrecs, score, body, dir); + } + } + } + } +} + +void +grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, double score, + grn_rset_posinfo *pi, int dir) +{ + grn_table_add_subrec_inline(table, ri, score, pi, dir); +} + +grn_table_cursor * +grn_table_cursor_open(grn_ctx *ctx, grn_obj *table, + const void *min, unsigned int min_size, + const void *max, unsigned int max_size, + int offset, int limit, int flags) +{ + grn_rc rc; + grn_table_cursor *tc = NULL; + unsigned int table_size; + if (!table) { return tc; } + GRN_API_ENTER; + table_size = grn_table_size(ctx, table); + if (flags & GRN_CURSOR_PREFIX) { + if (offset < 0) { + ERR(GRN_TOO_SMALL_OFFSET, + "can't use negative offset with GRN_CURSOR_PREFIX: %d", offset); + } else if (offset != 0 && offset >= (int) table_size) { + ERR(GRN_TOO_LARGE_OFFSET, + "offset is not less than table size: offset:%d, table_size:%d", + offset, table_size); + } else { + if (limit < -1) { + ERR(GRN_TOO_SMALL_LIMIT, + "can't use smaller limit than -1 with GRN_CURSOR_PREFIX: %d", + limit); + } else if (limit == -1) { + limit = table_size; + } + } + } else { + rc = grn_normalize_offset_and_limit(ctx, table_size, &offset, &limit); + if (rc) { + ERR(rc, "grn_normalize_offset_and_limit failed"); + } + } + if (!ctx->rc) { + if (table->header.type == GRN_DB) { table = ((grn_db *)table)->keys; } + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + { + grn_pat *pat = (grn_pat *)table; + WITH_NORMALIZE(pat, min, min_size, { + WITH_NORMALIZE(pat, max, max_size, { + grn_pat_cursor *pat_cursor; + pat_cursor = grn_pat_cursor_open(ctx, pat, + min, min_size, + max, max_size, + offset, limit, flags); + tc = (grn_table_cursor *)pat_cursor; + }); + }); + } + break; + case GRN_TABLE_DAT_KEY : + { + grn_dat *dat = (grn_dat *)table; + WITH_NORMALIZE(dat, min, min_size, { + WITH_NORMALIZE(dat, max, max_size, { + grn_dat_cursor *dat_cursor; + dat_cursor = grn_dat_cursor_open(ctx, dat, + min, min_size, + max, max_size, + offset, limit, flags); + tc = (grn_table_cursor *)dat_cursor; + }); + }); + } + break; + case GRN_TABLE_HASH_KEY : + { + grn_hash *hash = (grn_hash *)table; + WITH_NORMALIZE(hash, min, min_size, { + WITH_NORMALIZE(hash, max, max_size, { + grn_hash_cursor *hash_cursor; + hash_cursor = grn_hash_cursor_open(ctx, hash, + min, min_size, + max, max_size, + offset, limit, flags); + tc = (grn_table_cursor *)hash_cursor; + }); + }); + } + break; + case GRN_TABLE_NO_KEY : + tc = (grn_table_cursor *)grn_array_cursor_open(ctx, (grn_array *)table, + GRN_ID_NIL, GRN_ID_NIL, + offset, limit, flags); + break; + } + } + if (tc) { + grn_id id = grn_obj_register(ctx, ctx->impl->db, NULL, 0); + DB_OBJ(tc)->header.domain = GRN_ID_NIL; + DB_OBJ(tc)->range = GRN_ID_NIL; + grn_db_obj_init(ctx, ctx->impl->db, id, DB_OBJ(tc)); + } + GRN_API_RETURN(tc); +} + +grn_table_cursor * +grn_table_cursor_open_by_id(grn_ctx *ctx, grn_obj *table, + grn_id min, grn_id max, int flags) +{ + grn_table_cursor *tc = NULL; + GRN_API_ENTER; + if (table) { + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + tc = (grn_table_cursor *)grn_pat_cursor_open(ctx, (grn_pat *)table, + NULL, 0, NULL, 0, 0, -1, flags); + break; + case GRN_TABLE_DAT_KEY : + tc = (grn_table_cursor *)grn_dat_cursor_open(ctx, (grn_dat *)table, + NULL, 0, NULL, 0, 0, -1, flags); + break; + case GRN_TABLE_HASH_KEY : + tc = (grn_table_cursor *)grn_hash_cursor_open(ctx, (grn_hash *)table, + NULL, 0, NULL, 0, 0, -1, flags); + break; + case GRN_TABLE_NO_KEY : + tc = (grn_table_cursor *)grn_array_cursor_open(ctx, (grn_array *)table, + min, max, 0, -1, flags); + break; + } + } + GRN_API_RETURN(tc); +} + +grn_rc +grn_table_cursor_close(grn_ctx *ctx, grn_table_cursor *tc) +{ + const char *tag = "[table][cursor][close]"; + grn_rc rc = GRN_SUCCESS; + GRN_API_ENTER; + if (!tc) { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, "%s invalid cursor", tag); + } else { + { + if (DB_OBJ(tc)->finalizer) { + DB_OBJ(tc)->finalizer(ctx, 1, (grn_obj **)&tc, &DB_OBJ(tc)->user_data); + } + if (DB_OBJ(tc)->source) { + GRN_FREE(DB_OBJ(tc)->source); + } + /* + grn_hook_entry entry; + for (entry = 0; entry < N_HOOK_ENTRIES; entry++) { + grn_hook_free(ctx, DB_OBJ(tc)->hooks[entry]); + } + */ + grn_obj_delete_by_id(ctx, DB_OBJ(tc)->db, DB_OBJ(tc)->id, GRN_FALSE); + } + switch (tc->header.type) { + case GRN_CURSOR_TABLE_PAT_KEY : + grn_pat_cursor_close(ctx, (grn_pat_cursor *)tc); + break; + case GRN_CURSOR_TABLE_DAT_KEY : + grn_dat_cursor_close(ctx, (grn_dat_cursor *)tc); + break; + case GRN_CURSOR_TABLE_HASH_KEY : + grn_hash_cursor_close(ctx, (grn_hash_cursor *)tc); + break; + case GRN_CURSOR_TABLE_NO_KEY : + grn_array_cursor_close(ctx, (grn_array_cursor *)tc); + break; + default : + rc = GRN_INVALID_ARGUMENT; + ERR(rc, "%s invalid type %d", tag, tc->header.type); + break; + } + } + GRN_API_RETURN(rc); +} + +inline static grn_id +grn_table_cursor_next_inline(grn_ctx *ctx, grn_table_cursor *tc) +{ + const char *tag = "[table][cursor][next]"; + grn_id id = GRN_ID_NIL; + if (!tc) { + ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag); + } else { + switch (tc->header.type) { + case GRN_CURSOR_TABLE_PAT_KEY : + id = grn_pat_cursor_next(ctx, (grn_pat_cursor *)tc); + break; + case GRN_CURSOR_TABLE_DAT_KEY : + id = grn_dat_cursor_next(ctx, (grn_dat_cursor *)tc); + break; + case GRN_CURSOR_TABLE_HASH_KEY : + id = grn_hash_cursor_next(ctx, (grn_hash_cursor *)tc); + break; + case GRN_CURSOR_TABLE_NO_KEY : + id = grn_array_cursor_next(ctx, (grn_array_cursor *)tc); + break; + case GRN_CURSOR_COLUMN_INDEX : + { + grn_posting *ip = grn_index_cursor_next(ctx, (grn_obj *)tc, NULL); + if (ip) { id = ip->rid; } + } + break; + default : + ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type); + break; + } + } + return id; +} + +grn_id +grn_table_cursor_next(grn_ctx *ctx, grn_table_cursor *tc) +{ + grn_id id; + GRN_API_ENTER; + id = grn_table_cursor_next_inline(ctx, tc); + GRN_API_RETURN(id); +} + +int +grn_table_cursor_get_key(grn_ctx *ctx, grn_table_cursor *tc, void **key) +{ + const char *tag = "[table][cursor][get-key]"; + int len = 0; + GRN_API_ENTER; + if (!tc) { + ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag); + } else { + switch (tc->header.type) { + case GRN_CURSOR_TABLE_PAT_KEY : + len = grn_pat_cursor_get_key(ctx, (grn_pat_cursor *)tc, key); + break; + case GRN_CURSOR_TABLE_DAT_KEY : + len = grn_dat_cursor_get_key(ctx, (grn_dat_cursor *)tc, (const void **)key); + break; + case GRN_CURSOR_TABLE_HASH_KEY : + len = grn_hash_cursor_get_key(ctx, (grn_hash_cursor *)tc, key); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type); + break; + } + } + GRN_API_RETURN(len); +} + +inline static int +grn_table_cursor_get_value_inline(grn_ctx *ctx, grn_table_cursor *tc, void **value) +{ + const char *tag = "[table][cursor][get-value]"; + int len = 0; + if (!tc) { + ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag); + } else { + switch (tc->header.type) { + case GRN_CURSOR_TABLE_PAT_KEY : + len = grn_pat_cursor_get_value(ctx, (grn_pat_cursor *)tc, value); + break; + case GRN_CURSOR_TABLE_DAT_KEY : + *value = NULL; + len = 0; + break; + case GRN_CURSOR_TABLE_HASH_KEY : + len = grn_hash_cursor_get_value(ctx, (grn_hash_cursor *)tc, value); + break; + case GRN_CURSOR_TABLE_NO_KEY : + len = grn_array_cursor_get_value(ctx, (grn_array_cursor *)tc, value); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type); + break; + } + } + return len; +} + +int +grn_table_cursor_get_value(grn_ctx *ctx, grn_table_cursor *tc, void **value) +{ + int len; + GRN_API_ENTER; + len = grn_table_cursor_get_value_inline(ctx, tc, value); + GRN_API_RETURN(len); +} + +grn_rc +grn_table_cursor_set_value(grn_ctx *ctx, grn_table_cursor *tc, + const void *value, int flags) +{ + const char *tag = "[table][cursor][set-value]"; + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (!tc) { + ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag); + } else { + switch (tc->header.type) { + case GRN_CURSOR_TABLE_PAT_KEY : + rc = grn_pat_cursor_set_value(ctx, (grn_pat_cursor *)tc, value, flags); + break; + case GRN_CURSOR_TABLE_DAT_KEY : + rc = GRN_OPERATION_NOT_SUPPORTED; + break; + case GRN_CURSOR_TABLE_HASH_KEY : + rc = grn_hash_cursor_set_value(ctx, (grn_hash_cursor *)tc, value, flags); + break; + case GRN_CURSOR_TABLE_NO_KEY : + rc = grn_array_cursor_set_value(ctx, (grn_array_cursor *)tc, value, flags); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type); + break; + } + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_table_cursor_delete(grn_ctx *ctx, grn_table_cursor *tc) +{ + const char *tag = "[table][cursor][delete]"; + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (!tc) { + ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag); + } else { + grn_id id; + grn_obj *table; + const void *key = NULL; + unsigned int key_size = 0; + switch (tc->header.type) { + case GRN_CURSOR_TABLE_PAT_KEY : + { + grn_pat_cursor *pc = (grn_pat_cursor *)tc; + id = pc->curr_rec; + table = (grn_obj *)(pc->pat); + key = _grn_pat_key(ctx, pc->pat, id, &key_size); + rc = grn_table_delete_prepare(ctx, table, id, key, key_size); + if (rc != GRN_SUCCESS) { + goto exit; + } + rc = grn_pat_cursor_delete(ctx, pc, NULL); + } + break; + case GRN_CURSOR_TABLE_DAT_KEY : + rc = GRN_OPERATION_NOT_SUPPORTED; + break; + case GRN_CURSOR_TABLE_HASH_KEY : + { + grn_hash_cursor *hc = (grn_hash_cursor *)tc; + id = hc->curr_rec; + table = (grn_obj *)(hc->hash); + key = _grn_hash_key(ctx, hc->hash, id, &key_size); + rc = grn_table_delete_prepare(ctx, table, id, key, key_size); + if (rc != GRN_SUCCESS) { + goto exit; + } + rc = grn_hash_cursor_delete(ctx, hc, NULL); + } + break; + case GRN_CURSOR_TABLE_NO_KEY : + { + grn_array_cursor *ac = (grn_array_cursor *)tc; + id = ac->curr_rec; + table = (grn_obj *)(ac->array); + rc = grn_table_delete_prepare(ctx, table, id, key, key_size); + if (rc != GRN_SUCCESS) { + goto exit; + } + rc = grn_array_cursor_delete(ctx, ac, NULL); + } + break; + default : + ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type); + break; + } + } +exit : + GRN_API_RETURN(rc); +} + +grn_obj * +grn_table_cursor_table(grn_ctx *ctx, grn_table_cursor *tc) +{ + const char *tag = "[table][cursor][table]"; + grn_obj *obj = NULL; + GRN_API_ENTER; + if (!tc) { + ERR(GRN_INVALID_ARGUMENT, "%s invalid cursor", tag); + } else { + switch (tc->header.type) { + case GRN_CURSOR_TABLE_PAT_KEY : + obj = (grn_obj *)(((grn_pat_cursor *)tc)->pat); + break; + case GRN_CURSOR_TABLE_DAT_KEY : + obj = (grn_obj *)(((grn_dat_cursor *)tc)->dat); + break; + case GRN_CURSOR_TABLE_HASH_KEY : + obj = (grn_obj *)(((grn_hash_cursor *)tc)->hash); + break; + case GRN_CURSOR_TABLE_NO_KEY : + obj = (grn_obj *)(((grn_array_cursor *)tc)->array); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "%s invalid type %d", tag, tc->header.type); + break; + } + } + GRN_API_RETURN(obj); +} + +typedef struct { + grn_db_obj obj; + grn_obj *index; + grn_table_cursor *tc; + grn_ii_cursor *iic; + grn_id tid; + grn_id rid_min; + grn_id rid_max; + int flags; +} grn_index_cursor; + +grn_obj * +grn_index_cursor_open(grn_ctx *ctx, grn_table_cursor *tc, + grn_obj *index, grn_id rid_min, grn_id rid_max, int flags) +{ + grn_index_cursor *ic = NULL; + GRN_API_ENTER; + if (tc && (ic = GRN_MALLOCN(grn_index_cursor, 1))) { + ic->tc = tc; + ic->index = index; + ic->iic = NULL; + ic->tid = GRN_ID_NIL; + ic->rid_min = rid_min; + ic->rid_max = rid_max; + ic->flags = flags; + GRN_DB_OBJ_SET_TYPE(ic, GRN_CURSOR_COLUMN_INDEX); + { + grn_id id = grn_obj_register(ctx, ctx->impl->db, NULL, 0); + DB_OBJ(ic)->header.domain = GRN_ID_NIL; + DB_OBJ(ic)->range = GRN_ID_NIL; + grn_db_obj_init(ctx, ctx->impl->db, id, DB_OBJ(ic)); + } + } + GRN_API_RETURN((grn_obj *)ic); +} + +grn_posting * +grn_index_cursor_next(grn_ctx *ctx, grn_obj *c, grn_id *tid) +{ + grn_posting *ip = NULL; + grn_index_cursor *ic = (grn_index_cursor *)c; + GRN_API_ENTER; + if (ic->iic) { + if (ic->flags & GRN_OBJ_WITH_POSITION) { + ip = grn_ii_cursor_next_pos(ctx, ic->iic); + while (!ip && grn_ii_cursor_next(ctx, ic->iic)) { + ip = grn_ii_cursor_next_pos(ctx, ic->iic); + break; + } + } else { + ip = grn_ii_cursor_next(ctx, ic->iic); + } + } + if (!ip) { + while ((ic->tid = grn_table_cursor_next_inline(ctx, ic->tc))) { + grn_ii *ii = (grn_ii *)ic->index; + if (ic->iic) { grn_ii_cursor_close(ctx, ic->iic); } + if ((ic->iic = grn_ii_cursor_open(ctx, ii, ic->tid, + ic->rid_min, ic->rid_max, + ii->n_elements, ic->flags))) { + ip = grn_ii_cursor_next(ctx, ic->iic); + if (ip && ic->flags & GRN_OBJ_WITH_POSITION) { + ip = grn_ii_cursor_next_pos(ctx, ic->iic); + } + if (ip) { + break; + } + } + } + } + if (tid) { *tid = ic->tid; } + GRN_API_RETURN((grn_posting *)ip); +} + +grn_rc +grn_table_search(grn_ctx *ctx, grn_obj *table, const void *key, uint32_t key_size, + grn_operator mode, grn_obj *res, grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + GRN_API_ENTER; + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + { + grn_pat *pat = (grn_pat *)table; + WITH_NORMALIZE(pat, key, key_size, { + switch (mode) { + case GRN_OP_EXACT : + { + grn_id id = grn_pat_get(ctx, pat, key, key_size, NULL); + if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } + } + // todo : support op; + break; + case GRN_OP_LCP : + { + grn_id id = grn_pat_lcp_search(ctx, pat, key, key_size); + if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } + } + // todo : support op; + break; + case GRN_OP_SUFFIX : + rc = grn_pat_suffix_search(ctx, pat, key, key_size, (grn_hash *)res); + // todo : support op; + break; + case GRN_OP_PREFIX : + rc = grn_pat_prefix_search(ctx, pat, key, key_size, (grn_hash *)res); + // todo : support op; + break; + case GRN_OP_TERM_EXTRACT : + { + int len; + grn_id tid; + const char *sp = key; + const char *se = sp + key_size; + for (; sp < se; sp += len) { + if ((tid = grn_pat_lcp_search(ctx, pat, sp, se - sp))) { + grn_table_add(ctx, res, &tid, sizeof(grn_id), NULL); + /* todo : nsubrec++ if GRN_OBJ_TABLE_SUBSET assigned */ + } + if (!(len = grn_charlen(ctx, sp, se))) { break; } + } + } + // todo : support op; + break; + default : + rc = GRN_INVALID_ARGUMENT; + ERR(rc, "invalid mode %d", mode); + } + }); + } + break; + case GRN_TABLE_DAT_KEY : + { + grn_dat *dat = (grn_dat *)table; + WITH_NORMALIZE(dat, key, key_size, { + switch (mode) { + case GRN_OP_EXACT : + { + grn_id id = grn_dat_get(ctx, dat, key, key_size, NULL); + if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } + } + break; + case GRN_OP_PREFIX : + { + grn_dat_cursor *dc = grn_dat_cursor_open(ctx, dat, key, key_size, NULL, 0, + 0, -1, GRN_CURSOR_PREFIX); + if (dc) { + grn_id id; + while ((id = grn_dat_cursor_next(ctx, dc))) { + grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); + } + grn_dat_cursor_close(ctx, dc); + } + } + break; + case GRN_OP_LCP : + { + grn_id id = grn_dat_lcp_search(ctx, dat, key, key_size); + if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } + } + break; + case GRN_OP_TERM_EXTRACT : + { + int len; + grn_id tid; + const char *sp = key; + const char *se = sp + key_size; + for (; sp < se; sp += len) { + if ((tid = grn_dat_lcp_search(ctx, dat, sp, se - sp))) { + grn_table_add(ctx, res, &tid, sizeof(grn_id), NULL); + /* todo : nsubrec++ if GRN_OBJ_TABLE_SUBSET assigned */ + } + if (!(len = grn_charlen(ctx, sp, se))) { break; } + } + } + // todo : support op; + break; + default : + rc = GRN_INVALID_ARGUMENT; + ERR(rc, "invalid mode %d", mode); + } + }); + } + break; + case GRN_TABLE_HASH_KEY : + { + grn_hash *hash = (grn_hash *)table; + grn_id id = GRN_ID_NIL; + WITH_NORMALIZE(hash, key, key_size, { + id = grn_hash_get(ctx, hash, key, key_size, NULL); + }); + if (id) { grn_table_add(ctx, res, &id, sizeof(grn_id), NULL); } + } + break; + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_table_fuzzy_search(grn_ctx *ctx, grn_obj *table, const void *key, uint32_t key_size, + grn_fuzzy_search_optarg *args, grn_obj *res, grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + GRN_API_ENTER; + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + { + grn_pat *pat = (grn_pat *)table; + if (!grn_table_size(ctx, res) && op == GRN_OP_OR) { + WITH_NORMALIZE(pat, key, key_size, { + rc = grn_pat_fuzzy_search(ctx, pat, key, key_size, + args, (grn_hash *)res); + }); + } else { + grn_obj *hash; + hash = grn_table_create(ctx, NULL, 0, NULL, + GRN_OBJ_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + table, NULL); + WITH_NORMALIZE(pat, key, key_size, { + rc = grn_pat_fuzzy_search(ctx, pat, key, key_size, + args, (grn_hash *)hash); + }); + if (rc == GRN_SUCCESS) { + rc = grn_table_setoperation(ctx, res, hash, res, op); + } + grn_obj_unlink(ctx, hash); + } + } + break; + default : + rc = GRN_OPERATION_NOT_SUPPORTED; + break; + } + GRN_API_RETURN(rc); +} + +grn_id +grn_table_next(grn_ctx *ctx, grn_obj *table, grn_id id) +{ + grn_id r = GRN_ID_NIL; + GRN_API_ENTER; + if (table) { + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + r = grn_pat_next(ctx, (grn_pat *)table, id); + break; + case GRN_TABLE_DAT_KEY : + r = grn_dat_next(ctx, (grn_dat *)table, id); + break; + case GRN_TABLE_HASH_KEY : + r = grn_hash_next(ctx, (grn_hash *)table, id); + break; + case GRN_TABLE_NO_KEY : + r = grn_array_next(ctx, (grn_array *)table, id); + break; + } + } + GRN_API_RETURN(r); +} + +static grn_rc +grn_accessor_resolve_one_index_column(grn_ctx *ctx, grn_accessor *accessor, + grn_obj *current_res, grn_obj **next_res) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *column = NULL; + grn_id next_res_domain_id = GRN_ID_NIL; + + { + grn_obj *index; + grn_obj source_ids; + unsigned int i, n_ids; + + index = accessor->obj; + next_res_domain_id = index->header.domain; + + GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); + grn_obj_get_info(ctx, index, GRN_INFO_SOURCE, &source_ids); + n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); + for (i = 0; i < n_ids; i++) { + grn_id source_id; + grn_obj *source; + + source_id = GRN_UINT32_VALUE_AT(&source_ids, i); + source = grn_ctx_at(ctx, source_id); + if (DB_OBJ(source)->range == next_res_domain_id) { + column = source; + break; + } + grn_obj_unlink(ctx, source); + } + + if (!column) { + return GRN_INVALID_ARGUMENT; + } + } + + { + grn_rc rc; + grn_obj *next_res_domain = grn_ctx_at(ctx, next_res_domain_id); + *next_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + next_res_domain, NULL); + rc = ctx->rc; + grn_obj_unlink(ctx, next_res_domain); + if (!*next_res) { + return rc; + } + } + + { + grn_obj_flags column_value_flags = 0; + grn_obj column_value; + grn_posting add_posting; + grn_id *tid; + grn_rset_recinfo *recinfo; + + if (column->header.type == GRN_COLUMN_VAR_SIZE) { + column_value_flags |= GRN_OBJ_VECTOR; + } + GRN_VALUE_FIX_SIZE_INIT(&column_value, + column_value_flags, + next_res_domain_id); + + add_posting.sid = 0; + add_posting.pos = 0; + add_posting.weight = 0; + + GRN_HASH_EACH(ctx, (grn_hash *)current_res, id, &tid, NULL, &recinfo, { + int i; + int n_elements; + + add_posting.weight = recinfo->score - 1; + + GRN_BULK_REWIND(&column_value); + grn_obj_get_value(ctx, column, *tid, &column_value); + + n_elements = GRN_BULK_VSIZE(&column_value) / sizeof(grn_id); + for (i = 0; i < n_elements; i++) { + add_posting.rid = GRN_RECORD_VALUE_AT(&column_value, i); + rc = grn_ii_posting_add(ctx, + &add_posting, + (grn_hash *)*next_res, + GRN_OP_OR); + if (rc != GRN_SUCCESS) { + break; + } + } + if (rc != GRN_SUCCESS) { + break; + } + }); + + GRN_OBJ_FIN(ctx, &column_value); + } + + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, *next_res); + } + + return rc; +} + +static grn_rc +grn_accessor_resolve_one_table(grn_ctx *ctx, grn_accessor *accessor, + grn_obj *current_res, grn_obj **next_res) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *table; + + table = accessor->obj; + *next_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + table, NULL); + if (!*next_res) { + return ctx->rc; + } + + grn_report_table(ctx, + "[accessor][resolve]", + "", + table); + + { + grn_posting posting; + + memset(&posting, 0, sizeof(posting)); + GRN_HASH_EACH_BEGIN(ctx, (grn_hash *)current_res, cursor, id) { + void *key; + void *value; + grn_id *record_id; + grn_rset_recinfo *recinfo; + grn_id next_record_id; + + grn_hash_cursor_get_key_value(ctx, cursor, &key, NULL, &value); + record_id = key; + recinfo = value; + next_record_id = grn_table_get(ctx, + table, + record_id, + sizeof(grn_id)); + if (next_record_id == GRN_ID_NIL) { + continue; + } + + posting.rid = next_record_id; + posting.weight = recinfo->score; + rc = grn_ii_posting_add(ctx, + &posting, + (grn_hash *)*next_res, + GRN_OP_OR); + if (rc != GRN_SUCCESS) { + break; + } + } GRN_HASH_EACH_END(ctx, cursor); + } + + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, *next_res); + } + + return rc; +} + +static grn_rc +grn_accessor_resolve_one_data_column(grn_ctx *ctx, grn_accessor *accessor, + grn_obj *current_res, grn_obj **next_res) +{ + grn_rc rc = GRN_SUCCESS; + grn_index_datum index_datum; + unsigned int n_index_data; + grn_id next_res_domain_id = GRN_ID_NIL; + + n_index_data = grn_column_get_all_index_data(ctx, + accessor->obj, + &index_datum, + 1); + if (n_index_data == 0) { + return GRN_INVALID_ARGUMENT; + } + + { + grn_obj *lexicon; + lexicon = grn_ctx_at(ctx, index_datum.index->header.domain); + if (grn_obj_id(ctx, lexicon) != current_res->header.domain) { + char index_name[GRN_TABLE_MAX_KEY_SIZE]; + int index_name_size; + grn_obj *expected; + char expected_name[GRN_TABLE_MAX_KEY_SIZE]; + int expected_name_size; + + index_name_size = grn_obj_name(ctx, + index_datum.index, + index_name, + GRN_TABLE_MAX_KEY_SIZE); + expected = grn_ctx_at(ctx, current_res->header.domain); + expected_name_size = grn_obj_name(ctx, + expected, + expected_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[accessor][resolve][data-column] lexicon mismatch index: " + "<%.*s> " + "expected:<%.*s>", + index_name_size, + index_name, + expected_name_size, + expected_name); + return ctx->rc; + } + } + + next_res_domain_id = DB_OBJ(index_datum.index)->range; + + grn_report_index(ctx, + "[accessor][resolve][data-column]", + "", + index_datum.index); + { + grn_rc rc; + grn_obj *next_res_domain = grn_ctx_at(ctx, next_res_domain_id); + *next_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + next_res_domain, NULL); + rc = ctx->rc; + grn_obj_unlink(ctx, next_res_domain); + if (!*next_res) { + return rc; + } + } + + { + grn_id *tid; + grn_rset_recinfo *recinfo; + + GRN_HASH_EACH(ctx, (grn_hash *)current_res, id, &tid, NULL, &recinfo, { + grn_ii *ii = (grn_ii *)(index_datum.index); + grn_ii_cursor *ii_cursor; + grn_posting *posting; + + ii_cursor = grn_ii_cursor_open(ctx, ii, *tid, + GRN_ID_NIL, GRN_ID_MAX, + ii->n_elements, + 0); + if (!ii_cursor) { + continue; + } + + while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) { + grn_posting add_posting; + + if (index_datum.section > 0 && posting->sid != index_datum.section) { + continue; + } + + add_posting = *posting; + add_posting.weight += recinfo->score - 1; + rc = grn_ii_posting_add(ctx, + &add_posting, + (grn_hash *)*next_res, + GRN_OP_OR); + if (rc != GRN_SUCCESS) { + break; + } + } + grn_ii_cursor_close(ctx, ii_cursor); + + if (rc != GRN_SUCCESS) { + break; + } + }); + } + + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, *next_res); + } + + return rc; +} + +grn_rc +grn_accessor_resolve(grn_ctx *ctx, grn_obj *accessor, int deep, + grn_obj *base_res, grn_obj *res, + grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + grn_accessor *a; + grn_obj accessor_stack; + int i, n_accessors; + grn_obj *current_res = base_res; + + GRN_PTR_INIT(&accessor_stack, GRN_OBJ_VECTOR, GRN_ID_NIL); + n_accessors = 0; + for (a = (grn_accessor *)accessor; a; a = a->next) { + if (deep == n_accessors) { + break; + } + GRN_PTR_PUT(ctx, &accessor_stack, a); + n_accessors++; + } + + for (i = n_accessors; i > 0; i--) { + grn_obj *next_res = NULL; + + a = (grn_accessor *)GRN_PTR_VALUE_AT(&accessor_stack, i - 1); + if (a->obj->header.type == GRN_COLUMN_INDEX) { + rc = grn_accessor_resolve_one_index_column(ctx, a, + current_res, &next_res); + } else if (grn_obj_is_table(ctx, a->obj)) { + rc = grn_accessor_resolve_one_table(ctx, a, + current_res, &next_res); + } else { + rc = grn_accessor_resolve_one_data_column(ctx, a, + current_res, &next_res); + } + + if (current_res != base_res) { + grn_obj_unlink(ctx, current_res); + } + + if (rc != GRN_SUCCESS) { + break; + } + + current_res = next_res; + } + + if (rc == GRN_SUCCESS && current_res != base_res) { + grn_id *record_id; + grn_rset_recinfo *recinfo; + GRN_HASH_EACH(ctx, (grn_hash *)current_res, id, &record_id, NULL, &recinfo, { + grn_posting posting; + posting.rid = *record_id; + posting.sid = 1; + posting.pos = 0; + posting.weight = recinfo->score - 1; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + }); + grn_obj_unlink(ctx, current_res); + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + } else { + if (rc == GRN_SUCCESS) { + rc = GRN_INVALID_ARGUMENT; + } + } + + GRN_OBJ_FIN(ctx, &accessor_stack); + return rc; +} + +static inline void +grn_obj_search_index_report(grn_ctx *ctx, const char *tag, grn_obj *index) +{ + grn_report_index(ctx, "[object][search]", tag, index); +} + +static inline grn_rc +grn_obj_search_accessor(grn_ctx *ctx, grn_obj *obj, grn_obj *query, + grn_obj *res, grn_operator op, grn_search_optarg *optarg) +{ + grn_rc rc = GRN_SUCCESS; + grn_accessor *a; + grn_obj *last_obj = NULL; + int n_accessors; + + for (a = (grn_accessor *)obj; a; a = a->next) { + if (!a->next) { + last_obj = a->obj; + } + } + n_accessors = 0; + for (a = (grn_accessor *)obj; a; a = a->next) { + n_accessors++; + if (GRN_OBJ_INDEX_COLUMNP(a->obj)) { + break; + } + } + + { + grn_obj *index; + grn_operator index_op = GRN_OP_MATCH; + if (optarg && optarg->mode != GRN_OP_EXACT) { + index_op = optarg->mode; + } + if (grn_column_index(ctx, last_obj, index_op, &index, 1, NULL) == 0) { + rc = GRN_INVALID_ARGUMENT; + goto exit; + } + + if (n_accessors == 1) { + rc = grn_obj_search(ctx, index, query, res, op, optarg); + } else { + grn_obj *base_res; + grn_obj *range = grn_ctx_at(ctx, DB_OBJ(index)->range); + base_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + range, + NULL); + rc = ctx->rc; + grn_obj_unlink(ctx, range); + if (!base_res) { + goto exit; + } + if (optarg) { + optarg->match_info.min = GRN_ID_NIL; + } + rc = grn_obj_search(ctx, index, query, base_res, GRN_OP_OR, optarg); + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, base_res); + goto exit; + } + rc = grn_accessor_resolve(ctx, obj, n_accessors - 1, base_res, res, op); + grn_obj_unlink(ctx, base_res); + } + } + +exit : + return rc; +} + +static grn_rc +grn_obj_search_column_index_by_id(grn_ctx *ctx, grn_obj *obj, + grn_id tid, + grn_obj *res, grn_operator op, + grn_search_optarg *optarg) +{ + grn_ii_cursor *c; + + grn_obj_search_index_report(ctx, "[id]", obj); + + c = grn_ii_cursor_open(ctx, (grn_ii *)obj, tid, + GRN_ID_NIL, GRN_ID_MAX, 1, 0); + if (c) { + grn_posting *pos; + grn_hash *s = (grn_hash *)res; + while ((pos = grn_ii_cursor_next(ctx, c))) { + /* todo: support orgarg(op) + res_add(ctx, s, (grn_rset_posinfo *) pos, + get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg), op); + */ + grn_hash_add(ctx, s, pos, s->key_size, NULL, NULL); + } + grn_ii_cursor_close(ctx, c); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_obj_search_column_index_by_key(grn_ctx *ctx, grn_obj *obj, + grn_obj *query, + grn_obj *res, grn_operator op, + grn_search_optarg *optarg) +{ + grn_rc rc; + unsigned int key_type = GRN_ID_NIL; + const char *key; + unsigned int key_len; + grn_obj *table; + grn_obj casted_query; + grn_bool need_cast = GRN_FALSE; + + table = grn_ctx_at(ctx, obj->header.domain); + if (table) { + key_type = table->header.domain; + need_cast = (query->header.domain != key_type); + grn_obj_unlink(ctx, table); + } + if (need_cast) { + GRN_OBJ_INIT(&casted_query, GRN_BULK, 0, key_type); + rc = grn_obj_cast(ctx, query, &casted_query, GRN_FALSE); + if (rc == GRN_SUCCESS) { + key = GRN_BULK_HEAD(&casted_query); + key_len = GRN_BULK_VSIZE(&casted_query); + } + } else { + rc = GRN_SUCCESS; + key = GRN_BULK_HEAD(query); + key_len = GRN_BULK_VSIZE(query); + } + if (rc == GRN_SUCCESS) { + if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { + const char *tag; + if (optarg) { + switch (optarg->mode) { + case GRN_OP_MATCH : + tag = "[key][match]"; + break; + case GRN_OP_EXACT : + tag = "[key][exact]"; + break; + case GRN_OP_NEAR : + tag = "[key][near]"; + break; + case GRN_OP_NEAR2 : + tag = "[key][near2]"; + break; + case GRN_OP_SIMILAR : + tag = "[key][similar]"; + break; + case GRN_OP_REGEXP : + tag = "[key][regexp]"; + break; + case GRN_OP_FUZZY : + tag = "[key][fuzzy]"; + break; + default : + tag = "[key][unknown]"; + break; + } + } else { + tag = "[key][exact]"; + } + grn_obj_search_index_report(ctx, tag, obj); + } + rc = grn_ii_sel(ctx, (grn_ii *)obj, key, key_len, + (grn_hash *)res, op, optarg); + } + if (need_cast) { + GRN_OBJ_FIN(ctx, &casted_query); + } + + return rc; +} + +static grn_rc +grn_obj_search_column_index(grn_ctx *ctx, grn_obj *obj, grn_obj *query, + grn_obj *res, grn_operator op, + grn_search_optarg *optarg) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + + if (DB_OBJ(obj)->range == res->header.domain) { + switch (query->header.type) { + case GRN_BULK : + if (query->header.domain == obj->header.domain && + GRN_BULK_VSIZE(query) == sizeof(grn_id)) { + grn_id tid = GRN_RECORD_VALUE(query); + rc = grn_obj_search_column_index_by_id(ctx, obj, tid, res, op, optarg); + } else { + rc = grn_obj_search_column_index_by_key(ctx, obj, query, + res, op, optarg); + } + break; + case GRN_QUERY : + rc = GRN_FUNCTION_NOT_IMPLEMENTED; + break; + } + } + + return rc; +} + +grn_rc +grn_obj_search(grn_ctx *ctx, grn_obj *obj, grn_obj *query, + grn_obj *res, grn_operator op, grn_search_optarg *optarg) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (GRN_ACCESSORP(obj)) { + rc = grn_obj_search_accessor(ctx, obj, query, res, op, optarg); + } else if (GRN_DB_OBJP(obj)) { + switch (obj->header.type) { + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_HASH_KEY : + { + const void *key = GRN_BULK_HEAD(query); + uint32_t key_size = GRN_BULK_VSIZE(query); + grn_operator mode = optarg ? optarg->mode : GRN_OP_EXACT; + if (key && key_size) { + if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { + const char *tag; + if (optarg) { + switch (optarg->mode) { + case GRN_OP_EXACT : + tag = "[table][exact]"; + break; + case GRN_OP_LCP : + tag = "[table][lcp]"; + break; + case GRN_OP_SUFFIX : + tag = "[table][suffix]"; + break; + case GRN_OP_PREFIX : + tag = "[table][prefix]"; + break; + case GRN_OP_TERM_EXTRACT : + tag = "[table][term-extract]"; + break; + case GRN_OP_FUZZY : + tag = "[table][fuzzy]"; + break; + default : + tag = "[table][unknown]"; + break; + } + } else { + tag = "[table][exact]"; + } + grn_obj_search_index_report(ctx, tag, obj); + } + if (optarg && optarg->mode == GRN_OP_FUZZY) { + rc = grn_table_fuzzy_search(ctx, obj, key, key_size, + &(optarg->fuzzy), res, op); + } else { + rc = grn_table_search(ctx, obj, key, key_size, mode, res, op); + } + } + } + break; + case GRN_COLUMN_INDEX : + rc = grn_obj_search_column_index(ctx, obj, query, res, op, optarg); + break; + } + } + GRN_API_RETURN(rc); +} + +#define GRN_TABLE_GROUP_BY_KEY 0 +#define GRN_TABLE_GROUP_BY_VALUE 1 +#define GRN_TABLE_GROUP_BY_COLUMN_VALUE 2 + +#define GRN_TABLE_GROUP_FILTER_PREFIX 0 +#define GRN_TABLE_GROUP_FILTER_SUFFIX (1L<<2) + +inline static void +grn_table_group_add_subrec(grn_ctx *ctx, + grn_obj *table, + grn_rset_recinfo *ri, double score, + grn_rset_posinfo *pi, int dir, + grn_obj *calc_target, + grn_obj *value_buffer) +{ + grn_table_group_flags flags; + + if (!(DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC)) { + return; + } + + grn_table_add_subrec_inline(table, ri, score, pi, dir); + + flags = DB_OBJ(table)->flags.group; + + if (!(flags & (GRN_TABLE_GROUP_CALC_MAX | + GRN_TABLE_GROUP_CALC_MIN | + GRN_TABLE_GROUP_CALC_SUM | + GRN_TABLE_GROUP_CALC_AVG))) { + return; + } + + GRN_BULK_REWIND(value_buffer); + grn_obj_get_value(ctx, calc_target, pi->rid, value_buffer); + grn_rset_recinfo_update_calc_values(ctx, ri, table, value_buffer); +} + +static grn_bool +accelerated_table_group(grn_ctx *ctx, grn_obj *table, grn_obj *key, + grn_table_group_result *result) +{ + grn_obj *res = result->table; + grn_obj *calc_target = result->calc_target; + if (key->header.type == GRN_ACCESSOR) { + grn_accessor *a = (grn_accessor *)key; + if (a->action == GRN_ACCESSOR_GET_KEY && + a->next && a->next->action == GRN_ACCESSOR_GET_COLUMN_VALUE && + a->next->obj && !a->next->next) { + grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, key)); + int idp = GRN_OBJ_TABLEP(range); + grn_table_cursor *tc; + if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_bool processed = GRN_TRUE; + grn_obj value_buffer; + GRN_VOID_INIT(&value_buffer); + switch (a->next->obj->header.type) { + case GRN_COLUMN_FIX_SIZE : + { + grn_id id; + grn_ra *ra = (grn_ra *)a->next->obj; + unsigned int element_size = (ra)->header->element_size; + grn_ra_cache cache; + GRN_RA_CACHE_INIT(ra, &cache); + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + void *v, *value; + grn_id *id_; + uint32_t key_size; + grn_rset_recinfo *ri = NULL; + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + id_ = (grn_id *)_grn_table_key(ctx, table, id, &key_size); + v = grn_ra_ref_cache(ctx, ra, *id_, &cache); + if (idp && *((grn_id *)v) && + grn_table_at(ctx, range, *((grn_id *)v)) == GRN_ID_NIL) { + continue; + } + if ((!idp || *((grn_id *)v)) && + grn_table_add_v_inline(ctx, res, v, element_size, &value, NULL)) { + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); + } + } + GRN_RA_CACHE_FIN(ra, &cache); + } + break; + case GRN_COLUMN_VAR_SIZE : + if (idp) { /* todo : support other type */ + grn_id id; + grn_ja *ja = (grn_ja *)a->next->obj; + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + grn_io_win jw; + unsigned int len = 0; + void *value; + grn_id *v, *id_; + uint32_t key_size; + grn_rset_recinfo *ri = NULL; + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + id_ = (grn_id *)_grn_table_key(ctx, table, id, &key_size); + if ((v = grn_ja_ref(ctx, ja, *id_, &jw, &len))) { + while (len) { + if ((*v != GRN_ID_NIL) && + grn_table_add_v_inline(ctx, res, v, sizeof(grn_id), &value, NULL)) { + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); + } + v++; + len -= sizeof(grn_id); + } + grn_ja_unref(ctx, &jw); + } + } + } else { + processed = GRN_FALSE; + } + break; + default : + processed = GRN_FALSE; + break; + } + GRN_OBJ_FIN(ctx, &value_buffer); + grn_table_cursor_close(ctx, tc); + return processed; + } + } + } + return GRN_FALSE; +} + +static void +grn_table_group_single_key_records(grn_ctx *ctx, grn_obj *table, + grn_obj *key, grn_table_group_result *result) +{ + grn_obj bulk; + grn_obj value_buffer; + grn_table_cursor *tc; + grn_obj *res = result->table; + grn_obj *calc_target = result->calc_target; + + GRN_TEXT_INIT(&bulk, 0); + GRN_VOID_INIT(&value_buffer); + if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_id id; + grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, key)); + int idp = GRN_OBJ_TABLEP(range); + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + void *value; + grn_rset_recinfo *ri = NULL; + GRN_BULK_REWIND(&bulk); + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + grn_obj_get_value(ctx, key, id, &bulk); + switch (bulk.header.type) { + case GRN_UVECTOR : + { + grn_bool is_reference; + unsigned int element_size; + uint8_t *elements; + int i, n_elements; + + is_reference = !grn_type_id_is_builtin(ctx, bulk.header.type); + + element_size = grn_uvector_element_size(ctx, &bulk); + elements = GRN_BULK_HEAD(&bulk); + n_elements = GRN_BULK_VSIZE(&bulk) / element_size; + for (i = 0; i < n_elements; i++) { + uint8_t *element = elements + (element_size * i); + + if (is_reference) { + grn_id id = *((grn_id *)element); + if (id == GRN_ID_NIL) { + continue; + } + } + + if (!grn_table_add_v_inline(ctx, res, element, element_size, + &value, NULL)) { + continue; + } + + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); + } + } + break; + case GRN_VECTOR : + { + unsigned int i, n_elements; + n_elements = grn_vector_size(ctx, &bulk); + for (i = 0; i < n_elements; i++) { + const char *content; + unsigned int content_length; + content_length = grn_vector_get_element(ctx, &bulk, i, + &content, NULL, NULL); + if (grn_table_add_v_inline(ctx, res, + content, content_length, + &value, NULL)) { + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); + } + } + } + break; + case GRN_BULK : + { + if ((!idp || *((grn_id *)GRN_BULK_HEAD(&bulk))) && + grn_table_add_v_inline(ctx, res, + GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), + &value, NULL)) { + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); + } + } + break; + default : + ERR(GRN_INVALID_ARGUMENT, "invalid column"); + break; + } + } + grn_table_cursor_close(ctx, tc); + } + GRN_OBJ_FIN(ctx, &value_buffer); + GRN_OBJ_FIN(ctx, &bulk); +} + +#define GRN_TABLE_GROUP_ALL_NAME "_all" +#define GRN_TABLE_GROUP_ALL_NAME_LEN (sizeof(GRN_TABLE_GROUP_ALL_NAME) - 1) + +static void +grn_table_group_all_records(grn_ctx *ctx, grn_obj *table, + grn_table_group_result *result) +{ + grn_obj value_buffer; + grn_table_cursor *tc; + grn_obj *res = result->table; + grn_obj *calc_target = result->calc_target; + + GRN_VOID_INIT(&value_buffer); + if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_id id; + void *value; + if (grn_table_add_v_inline(ctx, res, + GRN_TABLE_GROUP_ALL_NAME, + GRN_TABLE_GROUP_ALL_NAME_LEN, + &value, NULL)) { + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + grn_rset_recinfo *ri = NULL; + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + grn_table_group_add_subrec(ctx, res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + calc_target, + &value_buffer); + } + } + grn_table_cursor_close(ctx, tc); + } + GRN_OBJ_FIN(ctx, &value_buffer); +} + +grn_rc +grn_table_group_with_range_gap(grn_ctx *ctx, grn_obj *table, + grn_table_sort_key *group_key, + grn_obj *res, uint32_t range_gap) +{ + grn_obj *key = group_key->key; + if (key->header.type == GRN_ACCESSOR) { + grn_accessor *a = (grn_accessor *)key; + if (a->action == GRN_ACCESSOR_GET_KEY && + a->next && a->next->action == GRN_ACCESSOR_GET_COLUMN_VALUE && + a->next->obj && !a->next->next) { + grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, key)); + int idp = GRN_OBJ_TABLEP(range); + grn_table_cursor *tc; + if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, + 0, 0, -1, 0))) { + switch (a->next->obj->header.type) { + case GRN_COLUMN_FIX_SIZE : + { + grn_id id; + grn_ra *ra = (grn_ra *)a->next->obj; + unsigned int element_size = (ra)->header->element_size; + grn_ra_cache cache; + GRN_RA_CACHE_INIT(ra, &cache); + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + void *v, *value; + grn_id *id_; + uint32_t key_size; + grn_rset_recinfo *ri = NULL; + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + id_ = (grn_id *)_grn_table_key(ctx, table, id, &key_size); + v = grn_ra_ref_cache(ctx, ra, *id_, &cache); + if (idp && *((grn_id *)v) && + grn_table_at(ctx, range, *((grn_id *)v)) == GRN_ID_NIL) { + continue; + } + if ((!idp || *((grn_id *)v))) { + grn_id id; + if (element_size == sizeof(uint32_t)) { + uint32_t quantized = (*(uint32_t *)v); + quantized -= quantized % range_gap; + id = grn_table_add_v_inline(ctx, res, &quantized, + element_size, &value, NULL); + } else { + id = grn_table_add_v_inline(ctx, res, v, + element_size, &value, NULL); + } + if (id) { + grn_table_add_subrec_inline(res, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0); + } + } + } + GRN_RA_CACHE_FIN(ra, &cache); + } + break; + case GRN_COLUMN_VAR_SIZE : + if (idp) { /* todo : support other type */ + grn_id id; + grn_ja *ja = (grn_ja *)a->next->obj; + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + grn_io_win jw; + unsigned int len = 0; + void *value; + grn_id *v, *id_; + uint32_t key_size; + grn_rset_recinfo *ri = NULL; + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + id_ = (grn_id *)_grn_table_key(ctx, table, id, &key_size); + if ((v = grn_ja_ref(ctx, ja, *id_, &jw, &len))) { + while (len) { + if ((*v != GRN_ID_NIL) && + grn_table_add_v_inline(ctx, res, v, sizeof(grn_id), &value, NULL)) { + grn_table_add_subrec_inline(res, value, ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0); + } + v++; + len -= sizeof(grn_id); + } + grn_ja_unref(ctx, &jw); + } + } + } else { + return 0; + } + break; + default : + return 0; + } + grn_table_cursor_close(ctx, tc); + GRN_TABLE_GROUPED_ON(res); + return 1; + } + } + } + return 0; +} + +static inline void +grn_table_group_multi_keys_add_record(grn_ctx *ctx, + grn_table_sort_key *keys, + int n_keys, + grn_table_group_result *results, + int n_results, + grn_id id, + grn_rset_recinfo *ri, + grn_obj *vector, + grn_obj *bulk) +{ + int r; + grn_table_group_result *rp; + + for (r = 0, rp = results; r < n_results; r++, rp++) { + void *value; + int i; + int end; + + if (rp->key_end > n_keys) { + end = n_keys; + } else { + end = rp->key_end + 1; + } + GRN_BULK_REWIND(bulk); + grn_text_benc(ctx, bulk, end - rp->key_begin); + for (i = rp->key_begin; i < end; i++) { + grn_section section = vector->u.v.sections[i]; + grn_text_benc(ctx, bulk, section.length); + } + { + grn_obj *body = vector->u.v.body; + if (body) { + GRN_TEXT_PUT(ctx, bulk, GRN_BULK_HEAD(body), GRN_BULK_VSIZE(body)); + } + } + for (i = rp->key_begin; i < end; i++) { + grn_section section = vector->u.v.sections[i]; + grn_text_benc(ctx, bulk, section.weight); + grn_text_benc(ctx, bulk, section.domain); + } + + // todo : cut off GRN_ID_NIL + if (grn_table_add_v_inline(ctx, rp->table, + GRN_BULK_HEAD(bulk), GRN_BULK_VSIZE(bulk), + &value, NULL)) { + grn_table_group_add_subrec(ctx, rp->table, value, + ri ? ri->score : 0, + (grn_rset_posinfo *)&id, 0, + rp->calc_target, + bulk); + } + } +} + +static void +grn_table_group_multi_keys_scalar_records(grn_ctx *ctx, + grn_obj *table, + grn_table_sort_key *keys, + int n_keys, + grn_table_group_result *results, + int n_results) +{ + grn_id id; + grn_table_cursor *tc; + grn_obj bulk; + grn_obj vector; + + tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); + if (!tc) { + return; + } + + GRN_TEXT_INIT(&bulk, 0); + GRN_OBJ_INIT(&vector, GRN_VECTOR, 0, GRN_DB_VOID); + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + int k; + grn_table_sort_key *kp; + grn_rset_recinfo *ri = NULL; + + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + + GRN_BULK_REWIND(&vector); + for (k = 0, kp = keys; k < n_keys; k++, kp++) { + GRN_BULK_REWIND(&bulk); + grn_obj_get_value(ctx, kp->key, id, &bulk); + grn_vector_add_element(ctx, &vector, + GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), + 0, + bulk.header.domain); + } + + grn_table_group_multi_keys_add_record(ctx, keys, n_keys, results, n_results, + id, ri, &vector, &bulk); + } + GRN_OBJ_FIN(ctx, &vector); + GRN_OBJ_FIN(ctx, &bulk); + grn_table_cursor_close(ctx, tc); +} + +static inline void +grn_table_group_multi_keys_vector_record(grn_ctx *ctx, + grn_table_sort_key *keys, + grn_obj *key_buffers, + int nth_key, + int n_keys, + grn_table_group_result *results, + int n_results, + grn_id id, + grn_rset_recinfo *ri, + grn_obj *vector, + grn_obj *bulk) +{ + int k; + grn_table_sort_key *kp; + + for (k = nth_key, kp = &(keys[nth_key]); k < n_keys; k++, kp++) { + grn_obj *key_buffer = &(key_buffers[k]); + switch (key_buffer->header.type) { + case GRN_UVECTOR : + { + unsigned int n_vector_elements; + grn_id domain; + grn_id *ids; + unsigned int i, n_ids; + + n_vector_elements = grn_vector_size(ctx, vector); + domain = key_buffer->header.domain; + ids = (grn_id *)GRN_BULK_HEAD(key_buffer); + n_ids = GRN_BULK_VSIZE(key_buffer) / sizeof(grn_id); + for (i = 0; i < n_ids; i++) { + grn_id element_id = ids[i]; + grn_vector_add_element(ctx, vector, + (const char *)(&element_id), sizeof(grn_id), + 0, + domain); + grn_table_group_multi_keys_vector_record(ctx, + keys, key_buffers, + k + 1, n_keys, + results, n_results, + id, ri, vector, bulk); + while (grn_vector_size(ctx, vector) != n_vector_elements) { + const char *content; + grn_vector_pop_element(ctx, vector, &content, NULL, NULL); + } + } + return; + } + break; + case GRN_VECTOR : + { + unsigned int n_vector_elements; + unsigned int i, n_key_elements; + + n_vector_elements = grn_vector_size(ctx, vector); + n_key_elements = grn_vector_size(ctx, key_buffer); + for (i = 0; i < n_key_elements; i++) { + const char *content; + unsigned int content_length; + grn_id domain; + content_length = grn_vector_get_element(ctx, key_buffer, i, + &content, NULL, &domain); + grn_vector_add_element(ctx, vector, + content, content_length, + 0, + domain); + grn_table_group_multi_keys_vector_record(ctx, + keys, key_buffers, + k + 1, n_keys, + results, n_results, + id, ri, vector, bulk); + while (grn_vector_size(ctx, vector) != n_vector_elements) { + grn_vector_pop_element(ctx, vector, &content, NULL, NULL); + } + } + return; + } + break; + default : + grn_vector_add_element(ctx, vector, + GRN_BULK_HEAD(key_buffer), + GRN_BULK_VSIZE(key_buffer), + 0, + key_buffer->header.domain); + } + } + + if (k == n_keys) { + grn_table_group_multi_keys_add_record(ctx, + keys, n_keys, + results, n_results, + id, ri, vector, bulk); + } +} + +static void +grn_table_group_multi_keys_vector_records(grn_ctx *ctx, + grn_obj *table, + grn_table_sort_key *keys, + int n_keys, + grn_table_group_result *results, + int n_results) +{ + grn_id id; + grn_table_cursor *tc; + grn_obj bulk; + grn_obj vector; + grn_obj *key_buffers; + int k; + + tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); + if (!tc) { + return; + } + + key_buffers = GRN_MALLOCN(grn_obj, n_keys); + if (!key_buffers) { + grn_table_cursor_close(ctx, tc); + return; + } + + GRN_TEXT_INIT(&bulk, 0); + GRN_OBJ_INIT(&vector, GRN_VECTOR, 0, GRN_DB_VOID); + for (k = 0; k < n_keys; k++) { + GRN_VOID_INIT(&(key_buffers[k])); + } + while ((id = grn_table_cursor_next_inline(ctx, tc))) { + grn_table_sort_key *kp; + grn_rset_recinfo *ri = NULL; + + if (DB_OBJ(table)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_cursor_get_value_inline(ctx, tc, (void **)&ri); + } + + for (k = 0, kp = keys; k < n_keys; k++, kp++) { + grn_obj *key_buffer = &(key_buffers[k]); + GRN_BULK_REWIND(key_buffer); + grn_obj_get_value(ctx, kp->key, id, key_buffer); + } + + GRN_BULK_REWIND(&vector); + grn_table_group_multi_keys_vector_record(ctx, + keys, key_buffers, 0, n_keys, + results, n_results, + id, ri, &vector, &bulk); + } + for (k = 0; k < n_keys; k++) { + GRN_OBJ_FIN(ctx, &(key_buffers[k])); + } + GRN_FREE(key_buffers); + GRN_OBJ_FIN(ctx, &vector); + GRN_OBJ_FIN(ctx, &bulk); + grn_table_cursor_close(ctx, tc); +} + +grn_rc +grn_table_group(grn_ctx *ctx, grn_obj *table, + grn_table_sort_key *keys, int n_keys, + grn_table_group_result *results, int n_results) +{ + grn_rc rc = GRN_SUCCESS; + grn_bool group_by_all_records = GRN_FALSE; + if (n_keys == 0 && n_results == 1) { + group_by_all_records = GRN_TRUE; + } else if (!table || !n_keys || !n_results) { + ERR(GRN_INVALID_ARGUMENT, "table or n_keys or n_results is void"); + return GRN_INVALID_ARGUMENT; + } + GRN_API_ENTER; + { + int k, r; + grn_table_sort_key *kp; + grn_table_group_result *rp; + for (k = 0, kp = keys; k < n_keys; k++, kp++) { + if ((kp->flags & GRN_TABLE_GROUP_BY_COLUMN_VALUE) && !kp->key) { + ERR(GRN_INVALID_ARGUMENT, "column missing in (%d)", k); + goto exit; + } + } + for (r = 0, rp = results; r < n_results; r++, rp++) { + if (!rp->table) { + grn_table_flags flags; + grn_obj *key_type = NULL; + uint32_t additional_value_size; + + flags = GRN_TABLE_HASH_KEY| + GRN_OBJ_WITH_SUBREC| + GRN_OBJ_UNIT_USERDEF_DOCUMENT; + if (group_by_all_records) { + key_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT); + } else if (n_keys == 1) { + key_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, keys[0].key)); + } else { + flags |= GRN_OBJ_KEY_VAR_SIZE; + } + additional_value_size = grn_rset_recinfo_calc_values_size(ctx, + rp->flags); + rp->table = grn_table_create_with_max_n_subrecs(ctx, NULL, 0, NULL, + flags, + key_type, table, + rp->max_n_subrecs, + additional_value_size); + if (key_type) { + grn_obj_unlink(ctx, key_type); + } + if (!rp->table) { + goto exit; + } + DB_OBJ(rp->table)->flags.group = rp->flags; + } + } + if (group_by_all_records) { + grn_table_group_all_records(ctx, table, results); + } else if (n_keys == 1 && n_results == 1) { + if (!accelerated_table_group(ctx, table, keys->key, results)) { + grn_table_group_single_key_records(ctx, table, keys->key, results); + } + } else { + grn_bool have_vector = GRN_FALSE; + for (k = 0, kp = keys; k < n_keys; k++, kp++) { + grn_id range_id; + grn_obj_flags range_flags = 0; + grn_obj_get_range_info(ctx, kp->key, &range_id, &range_flags); + if (range_flags == GRN_OBJ_VECTOR) { + have_vector = GRN_TRUE; + break; + } + } + if (have_vector) { + grn_table_group_multi_keys_vector_records(ctx, table, + keys, n_keys, + results, n_results); + } else { + grn_table_group_multi_keys_scalar_records(ctx, table, + keys, n_keys, + results, n_results); + } + } + for (r = 0, rp = results; r < n_results; r++, rp++) { + GRN_TABLE_GROUPED_ON(rp->table); + } + } +exit : + GRN_API_RETURN(rc); +} + +grn_rc +grn_table_setoperation(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, grn_obj *res, + grn_operator op) +{ + void *key = NULL, *value1 = NULL, *value2 = NULL; + uint32_t value_size = 0; + uint32_t key_size = 0; + grn_bool have_subrec; + + GRN_API_ENTER; + if (!table1) { + ERR(GRN_INVALID_ARGUMENT, "[table][setoperation] table1 is NULL"); + GRN_API_RETURN(ctx->rc); + } + if (!table2) { + ERR(GRN_INVALID_ARGUMENT, "[table][setoperation] table2 is NULL"); + GRN_API_RETURN(ctx->rc); + } + if (!res) { + ERR(GRN_INVALID_ARGUMENT, "[table][setoperation] result table is NULL"); + GRN_API_RETURN(ctx->rc); + } + + if (table1 != res) { + if (table2 == res) { + grn_obj *t = table1; + table1 = table2; + table2 = t; + } else { + ERR(GRN_INVALID_ARGUMENT, + "[table][setoperation] table1 or table2 must be result table"); + GRN_API_RETURN(ctx->rc); + } + } + have_subrec = ((DB_OBJ(table1)->header.flags & GRN_OBJ_WITH_SUBREC) && + (DB_OBJ(table2)->header.flags & GRN_OBJ_WITH_SUBREC)); + switch (table1->header.type) { + case GRN_TABLE_HASH_KEY : + value_size = ((grn_hash *)table1)->value_size; + break; + case GRN_TABLE_PAT_KEY : + value_size = ((grn_pat *)table1)->value_size; + break; + case GRN_TABLE_DAT_KEY : + value_size = 0; + break; + case GRN_TABLE_NO_KEY : + value_size = ((grn_array *)table1)->value_size; + break; + } + switch (table2->header.type) { + case GRN_TABLE_HASH_KEY : + if (value_size < ((grn_hash *)table2)->value_size) { + value_size = ((grn_hash *)table2)->value_size; + } + break; + case GRN_TABLE_PAT_KEY : + if (value_size < ((grn_pat *)table2)->value_size) { + value_size = ((grn_pat *)table2)->value_size; + } + break; + case GRN_TABLE_DAT_KEY : + value_size = 0; + break; + case GRN_TABLE_NO_KEY : + if (value_size < ((grn_array *)table2)->value_size) { + value_size = ((grn_array *)table2)->value_size; + } + break; + } + switch (op) { + case GRN_OP_OR : + if (have_subrec) { + int added; + GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { + if (grn_table_add_v_inline(ctx, table1, key, key_size, &value1, &added)) { + if (added) { + grn_memcpy(value1, value2, value_size); + } else { + grn_rset_recinfo *ri1 = value1; + grn_rset_recinfo *ri2 = value2; + grn_table_add_subrec_inline(table1, ri1, ri2->score, NULL, 0); + } + } + }); + } else { + GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { + if (grn_table_add_v_inline(ctx, table1, key, key_size, &value1, NULL)) { + grn_memcpy(value1, value2, value_size); + } + }); + } + break; + case GRN_OP_AND : + if (have_subrec) { + GRN_TABLE_EACH(ctx, table1, 0, 0, id, &key, &key_size, &value1, { + if (grn_table_get_v(ctx, table2, key, key_size, &value2)) { + grn_rset_recinfo *ri1 = value1; + grn_rset_recinfo *ri2 = value2; + ri1->score += ri2->score; + } else { + _grn_table_delete_by_id(ctx, table1, id, NULL); + } + }); + } else { + GRN_TABLE_EACH(ctx, table1, 0, 0, id, &key, &key_size, &value1, { + if (!grn_table_get_v(ctx, table2, key, key_size, &value2)) { + _grn_table_delete_by_id(ctx, table1, id, NULL); + } + }); + } + break; + case GRN_OP_AND_NOT : + GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { + grn_table_delete(ctx, table1, key, key_size); + }); + break; + case GRN_OP_ADJUST : + if (have_subrec) { + GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { + if (grn_table_get_v(ctx, table1, key, key_size, &value1)) { + grn_rset_recinfo *ri1 = value1; + grn_rset_recinfo *ri2 = value2; + ri1->score += ri2->score; + } + }); + } else { + GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, &value2, { + if (grn_table_get_v(ctx, table1, key, key_size, &value1)) { + grn_memcpy(value1, value2, value_size); + } + }); + } + break; + default : + break; + } + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_table_difference(grn_ctx *ctx, grn_obj *table1, grn_obj *table2, + grn_obj *res1, grn_obj *res2) +{ + void *key = NULL; + uint32_t key_size = 0; + if (table1 != res1 || table2 != res2) { return GRN_INVALID_ARGUMENT; } + if (grn_table_size(ctx, table1) > grn_table_size(ctx, table2)) { + GRN_TABLE_EACH(ctx, table2, 0, 0, id, &key, &key_size, NULL, { + grn_id id1; + if ((id1 = grn_table_get(ctx, table1, key, key_size))) { + _grn_table_delete_by_id(ctx, table1, id1, NULL); + _grn_table_delete_by_id(ctx, table2, id, NULL); + } + }); + } else { + GRN_TABLE_EACH(ctx, table1, 0, 0, id, &key, &key_size, NULL, { + grn_id id2; + if ((id2 = grn_table_get(ctx, table2, key, key_size))) { + _grn_table_delete_by_id(ctx, table1, id, NULL); + _grn_table_delete_by_id(ctx, table2, id2, NULL); + } + }); + } + return GRN_SUCCESS; +} + +static grn_obj *grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, + const char *name, unsigned int name_size); + +static grn_obj * +grn_obj_column_(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size) +{ + grn_id table_id = DB_OBJ(table)->id; + grn_obj *column = NULL; + + if (table_id & GRN_OBJ_TMP_OBJECT) { + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + void *value = NULL; + grn_snprintf(column_name, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, + "%u%c%.*s", table_id, GRN_DB_DELIMITER, name_size, name); + grn_pat_get(ctx, ctx->impl->temporary_columns, + column_name, strlen(column_name), + &value); + if (value) { + column = *((grn_obj **)value); + } + } else { + char buf[GRN_TABLE_MAX_KEY_SIZE]; + int len = grn_obj_name(ctx, table, buf, GRN_TABLE_MAX_KEY_SIZE); + if (len) { + buf[len++] = GRN_DB_DELIMITER; + if (len + name_size <= GRN_TABLE_MAX_KEY_SIZE) { + grn_memcpy(buf + len, name, name_size); + column = grn_ctx_get(ctx, buf, len + name_size); + } else { + ERR(GRN_INVALID_ARGUMENT, "name is too long"); + } + } + } + + return column; +} + +grn_obj * +grn_obj_column(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size) +{ + grn_obj *column = NULL; + GRN_API_ENTER; + if (GRN_OBJ_TABLEP(table)) { + if (grn_db_check_name(ctx, name, name_size) || + !(column = grn_obj_column_(ctx, table, name, name_size))) { + column = grn_obj_get_accessor(ctx, table, name, name_size); + } + } else if (GRN_ACCESSORP(table)) { + column = grn_obj_get_accessor(ctx, table, name, name_size); + } + GRN_API_RETURN(column); +} + +int +grn_table_columns(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size, + grn_obj *res) +{ + int n = 0; + grn_id id; + + GRN_API_ENTER; + + if (!GRN_OBJ_TABLEP(table)) { + GRN_API_RETURN(n); + } + + id = DB_OBJ(table)->id; + + if (id == GRN_ID_NIL) { + GRN_API_RETURN(n); + } + + if (id & GRN_OBJ_TMP_OBJECT) { + char search_key[GRN_TABLE_MAX_KEY_SIZE]; + grn_pat_cursor *cursor; + grn_snprintf(search_key, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, + "%u%c%.*s", id, GRN_DB_DELIMITER, name_size, name); + cursor = grn_pat_cursor_open(ctx, ctx->impl->temporary_columns, + search_key, strlen(search_key), + NULL, 0, + 0, -1, GRN_CURSOR_PREFIX); + if (cursor) { + grn_id column_id; + while ((column_id = grn_pat_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + column_id |= GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN; + grn_hash_add(ctx, (grn_hash *)res, + &column_id, sizeof(grn_id), + NULL, NULL); + n++; + } + grn_pat_cursor_close(ctx, cursor); + } + } else { + grn_db *s = (grn_db *)DB_OBJ(table)->db; + if (s->keys) { + grn_obj bulk; + GRN_TEXT_INIT(&bulk, 0); + grn_table_get_key2(ctx, s->keys, id, &bulk); + GRN_TEXT_PUTC(ctx, &bulk, GRN_DB_DELIMITER); + grn_bulk_write(ctx, &bulk, name, name_size); + grn_table_search(ctx, s->keys, GRN_BULK_HEAD(&bulk), GRN_BULK_VSIZE(&bulk), + GRN_OP_PREFIX, res, GRN_OP_OR); + grn_obj_close(ctx, &bulk); + n = grn_table_size(ctx, res); + } + } + + GRN_API_RETURN(n); +} + +const char * +_grn_table_key(grn_ctx *ctx, grn_obj *table, grn_id id, uint32_t *key_size) +{ + GRN_ASSERT(table); + if (table->header.type == GRN_DB) { table = ((grn_db *)table)->keys; } + switch (table->header.type) { + case GRN_TABLE_HASH_KEY : + return _grn_hash_key(ctx, (grn_hash *)table, id, key_size); + case GRN_TABLE_PAT_KEY : + return _grn_pat_key(ctx, (grn_pat *)table, id, key_size); + case GRN_TABLE_DAT_KEY : + return _grn_dat_key(ctx, (grn_dat *)table, id, key_size); + case GRN_TABLE_NO_KEY : + { + grn_array *a = (grn_array *)table; + const char *v; + if (a->obj.header.domain && a->value_size && + (v = _grn_array_get_value(ctx, a, id))) { + *key_size = a->value_size; + return v; + } else { + *key_size = 0; + } + } + break; + } + return NULL; +} + +/* column */ + +grn_obj * +grn_column_create(grn_ctx *ctx, grn_obj *table, + const char *name, unsigned int name_size, + const char *path, grn_column_flags flags, grn_obj *type) +{ + grn_db *s; + uint32_t value_size; + grn_obj *db= NULL, *res = NULL; + grn_id id = GRN_ID_NIL; + grn_id range = GRN_ID_NIL; + grn_id domain = GRN_ID_NIL; + grn_bool is_persistent_table; + char fullname[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int fullname_size; + char buffer[PATH_MAX]; + + GRN_API_ENTER; + if (!table) { + ERR(GRN_INVALID_ARGUMENT, "[column][create] table is missing"); + goto exit; + } + if (!type) { + ERR(GRN_INVALID_ARGUMENT, "[column][create] type is missing"); + goto exit; + } + if (!name || !name_size) { + ERR(GRN_INVALID_ARGUMENT, "[column][create] name is missing"); + goto exit; + } + db = DB_OBJ(table)->db; + s = (grn_db *)db; + if (!GRN_DB_P(s)) { + int table_name_len; + char table_name[GRN_TABLE_MAX_KEY_SIZE]; + table_name_len = grn_obj_name(ctx, table, table_name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[column][create] invalid db assigned: <%.*s>.<%.*s>", + table_name_len, table_name, name_size, name); + goto exit; + } + + if (grn_db_check_name(ctx, name, name_size)) { + GRN_DB_CHECK_NAME_ERR("[column][create]", name, name_size); + goto exit; + } + + domain = DB_OBJ(table)->id; + is_persistent_table = !(domain & GRN_OBJ_TMP_OBJECT); + + if (!domain) { + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "[column][create] [todo] table-less column isn't supported yet"); + goto exit; + } + + { + int table_name_len; + if (is_persistent_table) { + table_name_len = grn_table_get_key(ctx, s->keys, domain, + fullname, GRN_TABLE_MAX_KEY_SIZE); + } else { + grn_snprintf(fullname, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, + "%u", domain); + table_name_len = strlen(fullname); + } + if (name_size + 1 + table_name_len > GRN_TABLE_MAX_KEY_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[column][create] too long column name: required name_size(%d) < %d" + ": <%.*s>.<%.*s>", + name_size, GRN_TABLE_MAX_KEY_SIZE - 1 - table_name_len, + table_name_len, fullname, name_size, name); + goto exit; + } + fullname[table_name_len] = GRN_DB_DELIMITER; + grn_memcpy(fullname + table_name_len + 1, name, name_size); + fullname_size = table_name_len + 1 + name_size; + } + + range = DB_OBJ(type)->id; + switch (type->header.type) { + case GRN_TYPE : + { + grn_db_obj *t = (grn_db_obj *)type; + flags |= t->header.flags & ~GRN_OBJ_KEY_MASK; + value_size = GRN_TYPE_SIZE(t); + } + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + value_size = sizeof(grn_id); + break; + default : + /* + if (type == grn_type_any) { + value_size = sizeof(grn_id) + sizeof(grn_id); + } + */ + value_size = sizeof(grn_id); + } + + if (is_persistent_table) { + id = grn_obj_register(ctx, db, fullname, fullname_size); + if (ERRP(ctx, GRN_ERROR)) { goto exit; } + + { + uint32_t table_name_size = 0; + const char *table_name; + table_name = _grn_table_key(ctx, ctx->impl->db, domain, &table_name_size); + GRN_LOG(ctx, GRN_LOG_NOTICE, + "DDL:%u:column_create %.*s %.*s", + id, + table_name_size, table_name, + name_size, name); + } + } else { + int added; + id = grn_pat_add(ctx, ctx->impl->temporary_columns, + fullname, fullname_size, NULL, + &added); + if (!id) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[column][create][temporary] " + "failed to register temporary column name: <%.*s>", + fullname_size, fullname); + goto exit; + } else if (!added) { + id = GRN_ID_NIL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[column][create][temporary] already used name was assigned: <%.*s>", + fullname_size, fullname); + goto exit; + } + id |= GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN; + } + + if (is_persistent_table && flags & GRN_OBJ_PERSISTENT) { + if (!path) { + if (GRN_DB_PERSISTENT_P(db)) { + grn_db_generate_pathname(ctx, db, id, buffer); + path = buffer; + } else { + int table_name_len; + char table_name[GRN_TABLE_MAX_KEY_SIZE]; + table_name_len = grn_obj_name(ctx, table, table_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[column][create] path not assigned for persistent column" + ": <%.*s>.<%.*s>", + table_name_len, table_name, name_size, name); + goto exit; + } + } else { + flags |= GRN_OBJ_CUSTOM_NAME; + } + } else { + if (path) { + int table_name_len; + char table_name[GRN_TABLE_MAX_KEY_SIZE]; + table_name_len = grn_obj_name(ctx, table, table_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[column][create] path assigned for temporary column" + ": <%.*s>.<%.*s>", + table_name_len, table_name, name_size, name); + goto exit; + } + } + switch (flags & GRN_OBJ_COLUMN_TYPE_MASK) { + case GRN_OBJ_COLUMN_SCALAR : + if ((flags & GRN_OBJ_KEY_VAR_SIZE) || value_size > sizeof(int64_t)) { + res = (grn_obj *)grn_ja_create(ctx, path, value_size, flags); + } else { + res = (grn_obj *)grn_ra_create(ctx, path, value_size); + } + break; + case GRN_OBJ_COLUMN_VECTOR : + res = (grn_obj *)grn_ja_create(ctx, path, value_size * 30/*todo*/, flags); + //todo : zlib support + break; + case GRN_OBJ_COLUMN_INDEX : + res = (grn_obj *)grn_ii_create(ctx, path, table, flags); //todo : ii layout support + break; + } + if (res) { + DB_OBJ(res)->header.domain = domain; + DB_OBJ(res)->header.impl_flags = 0; + DB_OBJ(res)->range = range; + DB_OBJ(res)->header.flags = flags; + res->header.flags = flags; + if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) { + _grn_obj_remove(ctx, res, GRN_FALSE); + res = NULL; + } else { + grn_obj_touch(ctx, res, NULL); + } + } +exit : + if (!res && id) { grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); } + GRN_API_RETURN(res); +} + +grn_obj * +grn_column_open(grn_ctx *ctx, grn_obj *table, + const char *name, unsigned int name_size, + const char *path, grn_obj *type) +{ + grn_id domain; + grn_obj *res = NULL; + grn_db *s; + char fullname[GRN_TABLE_MAX_KEY_SIZE]; + GRN_API_ENTER; + if (!table || !type || !name || !name_size) { + ERR(GRN_INVALID_ARGUMENT, "missing type or name"); + goto exit; + } + s = (grn_db *)DB_OBJ(table)->db; + if (!GRN_DB_P(s)) { + ERR(GRN_INVALID_ARGUMENT, "invalid db assigned"); + goto exit; + } + if (grn_db_check_name(ctx, name, name_size)) { + GRN_DB_CHECK_NAME_ERR("[column][open]", name, name_size); + goto exit; + } + if ((domain = DB_OBJ(table)->id)) { + int len = grn_table_get_key(ctx, s->keys, domain, fullname, GRN_TABLE_MAX_KEY_SIZE); + if (name_size + 1 + len > GRN_TABLE_MAX_KEY_SIZE) { + ERR(GRN_INVALID_ARGUMENT, "too long column name"); + goto exit; + } + fullname[len] = GRN_DB_DELIMITER; + grn_memcpy(fullname + len + 1, name, name_size); + name_size += len + 1; + } else { + ERR(GRN_INVALID_ARGUMENT, "todo : not supported yet"); + goto exit; + } + res = grn_ctx_get(ctx, fullname, name_size); + if (res) { + const char *path2 = grn_obj_path(ctx, res); + if (path && (!path2 || strcmp(path, path2))) { goto exit; } + } else if (path) { + uint32_t dbtype = grn_io_detect_type(ctx, path); + if (!dbtype) { goto exit; } + switch (dbtype) { + case GRN_COLUMN_VAR_SIZE : + res = (grn_obj *)grn_ja_open(ctx, path); + break; + case GRN_COLUMN_FIX_SIZE : + res = (grn_obj *)grn_ra_open(ctx, path); + break; + case GRN_COLUMN_INDEX : + res = (grn_obj *)grn_ii_open(ctx, path, table); + break; + } + if (res) { + grn_id id = grn_obj_register(ctx, (grn_obj *)s, fullname, name_size); + DB_OBJ(res)->header.domain = domain; + DB_OBJ(res)->range = DB_OBJ(type)->id; + res->header.flags |= GRN_OBJ_CUSTOM_NAME; + grn_db_obj_init(ctx, (grn_obj *)s, id, DB_OBJ(res)); + } + } +exit : + GRN_API_RETURN(res); +} + +/* +typedef struct { + grn_id id; + int flags; +} grn_column_set_value_arg; + +static grn_rc +default_column_set_value(grn_ctx *ctx, grn_proc_ctx *pctx, grn_obj *in, grn_obj *out) +{ + grn_user_data *data = grn_proc_ctx_get_local_data(pctx); + if (data) { + grn_column_set_value_arg *arg = data->ptr; + unsigned int value_size = in->u.p.size; //todo + if (!pctx->obj) { return GRN_ID_NIL; } + switch (pctx->obj->header.type) { + case GRN_COLUMN_VAR_SIZE : + return grn_ja_put(ctx, (grn_ja *)pctx->obj, arg->id, + in->u.p.ptr, value_size, 0, NULL); // todo type->flag + case GRN_COLUMN_FIX_SIZE : + if (((grn_ra *)pctx->obj)->header->element_size < value_size) { + ERR(GRN_INVALID_ARGUMENT, "too long value (%d)", value_size); + return GRN_INVALID_ARGUMENT; + } else { + void *v = grn_ra_ref(ctx, (grn_ra *)pctx->obj, arg->id); + if (!v) { + ERR(GRN_NO_MEMORY_AVAILABLE, "ra get failed"); + return GRN_NO_MEMORY_AVAILABLE; + } + grn_memcpy(v, in->u.p.ptr, value_size); + grn_ra_unref(ctx, (grn_ra *)pctx->obj, arg->id); + } + break; + case GRN_COLUMN_INDEX : + // todo : how?? + break; + } + return GRN_SUCCESS; + } else { + ERR(GRN_OBJECT_CORRUPT, "grn_proc_ctx_get_local_data failed"); + return ctx->rc; + } +} +*/ + +/**** grn_vector ****/ + +//#define VECTOR(obj) ((grn_vector *)obj) + +/* +#define INITIAL_VECTOR_SIZE 256 + +int +grn_vector_delimit(grn_ctx *ctx, grn_obj *vector) +{ + grn_vector *v = VECTOR(vector); + uint32_t *offsets; + if (!(v->n_entries & (INITIAL_VECTOR_SIZE - 1))) { + offsets = GRN_REALLOC(v->offsets, sizeof(uint32_t) * + (v->n_entries + INITIAL_VECTOR_SIZE)); + if (!offsets) { return -1; } + v->offsets = offsets; + } + v->offsets[v->n_entries] = GRN_BULK_VSIZE(vector); + return ++(v->n_entries); +} +*/ + +static unsigned int +grn_uvector_element_size_internal(grn_ctx *ctx, grn_obj *uvector) +{ + unsigned int element_size; + + if (IS_WEIGHT_UVECTOR(uvector)) { + element_size = sizeof(weight_uvector_entry); + } else { + switch (uvector->header.domain) { + case GRN_DB_BOOL : + element_size = sizeof(grn_bool); + break; + case GRN_DB_INT8 : + element_size = sizeof(int8_t); + break; + case GRN_DB_UINT8 : + element_size = sizeof(uint8_t); + break; + case GRN_DB_INT16 : + element_size = sizeof(int16_t); + break; + case GRN_DB_UINT16 : + element_size = sizeof(uint16_t); + break; + case GRN_DB_INT32 : + element_size = sizeof(int32_t); + break; + case GRN_DB_UINT32 : + element_size = sizeof(uint32_t); + break; + case GRN_DB_INT64 : + element_size = sizeof(int64_t); + break; + case GRN_DB_UINT64 : + element_size = sizeof(uint64_t); + break; + case GRN_DB_FLOAT : + element_size = sizeof(double); + break; + case GRN_DB_TIME : + element_size = sizeof(int64_t); + break; + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + element_size = sizeof(grn_geo_point); + break; + default : + element_size = sizeof(grn_id); + break; + } + } + + return element_size; +} + +static unsigned int +grn_uvector_size_internal(grn_ctx *ctx, grn_obj *uvector) +{ + unsigned int element_size; + + element_size = grn_uvector_element_size_internal(ctx, uvector); + return GRN_BULK_VSIZE(uvector) / element_size; +} + +unsigned int +grn_vector_size(grn_ctx *ctx, grn_obj *vector) +{ + unsigned int size; + if (!vector) { + ERR(GRN_INVALID_ARGUMENT, "vector is null"); + return 0; + } + GRN_API_ENTER; + switch (vector->header.type) { + case GRN_BULK : + size = GRN_BULK_VSIZE(vector); + break; + case GRN_UVECTOR : + size = grn_uvector_size_internal(ctx, vector); + break; + case GRN_VECTOR : + size = vector->u.v.n_sections; + break; + default : + ERR(GRN_INVALID_ARGUMENT, "not vector"); + size = 0; + break; + } + GRN_API_RETURN(size); +} + +static grn_obj * +grn_vector_body(grn_ctx *ctx, grn_obj *v) +{ + if (!v) { + ERR(GRN_INVALID_ARGUMENT, "invalid argument"); + return NULL; + } + switch (v->header.type) { + case GRN_VECTOR : + if (!v->u.v.body) { + v->u.v.body = grn_obj_open(ctx, GRN_BULK, 0, v->header.domain); + } + return v->u.v.body; + case GRN_BULK : + case GRN_UVECTOR : + return v; + default : + return NULL; + } +} + +unsigned int +grn_vector_get_element(grn_ctx *ctx, grn_obj *vector, + unsigned int offset, const char **str, + unsigned int *weight, grn_id *domain) +{ + unsigned int length = 0; + GRN_API_ENTER; + if (!vector || vector->header.type != GRN_VECTOR) { + ERR(GRN_INVALID_ARGUMENT, "invalid vector"); + goto exit; + } + if ((unsigned int) vector->u.v.n_sections <= offset) { + ERR(GRN_RANGE_ERROR, "offset out of range"); + goto exit; + } + { + grn_section *vp = &vector->u.v.sections[offset]; + grn_obj *body = grn_vector_body(ctx, vector); + *str = GRN_BULK_HEAD(body) + vp->offset; + if (weight) { *weight = vp->weight; } + if (domain) { *domain = vp->domain; } + length = vp->length; + } +exit : + GRN_API_RETURN(length); +} + +unsigned int +grn_vector_pop_element(grn_ctx *ctx, grn_obj *vector, + const char **str, unsigned int *weight, grn_id *domain) +{ + unsigned int offset, length = 0; + GRN_API_ENTER; + if (!vector || vector->header.type != GRN_VECTOR) { + ERR(GRN_INVALID_ARGUMENT, "invalid vector"); + goto exit; + } + if (!vector->u.v.n_sections) { + ERR(GRN_RANGE_ERROR, "offset out of range"); + goto exit; + } + offset = --vector->u.v.n_sections; + { + grn_section *vp = &vector->u.v.sections[offset]; + grn_obj *body = grn_vector_body(ctx, vector); + *str = GRN_BULK_HEAD(body) + vp->offset; + if (weight) { *weight = vp->weight; } + if (domain) { *domain = vp->domain; } + length = vp->length; + grn_bulk_truncate(ctx, body, vp->offset); + } +exit : + GRN_API_RETURN(length); +} + +#define W_SECTIONS_UNIT 8 +#define S_SECTIONS_UNIT (1 << W_SECTIONS_UNIT) +#define M_SECTIONS_UNIT (S_SECTIONS_UNIT - 1) + +grn_rc +grn_vector_delimit(grn_ctx *ctx, grn_obj *v, unsigned int weight, grn_id domain) +{ + if (v->header.type != GRN_VECTOR) { return GRN_INVALID_ARGUMENT; } + if (!(v->u.v.n_sections & M_SECTIONS_UNIT)) { + grn_section *vp = GRN_REALLOC(v->u.v.sections, sizeof(grn_section) * + (v->u.v.n_sections + S_SECTIONS_UNIT)); + if (!vp) { return GRN_NO_MEMORY_AVAILABLE; } + v->u.v.sections = vp; + } + { + grn_obj *body = grn_vector_body(ctx, v); + grn_section *vp = &v->u.v.sections[v->u.v.n_sections]; + vp->offset = v->u.v.n_sections ? vp[-1].offset + vp[-1].length : 0; + vp->length = GRN_BULK_VSIZE(body) - vp->offset; + vp->weight = weight; + vp->domain = domain; + } + v->u.v.n_sections++; + return GRN_SUCCESS; +} + +grn_rc +grn_vector_decode(grn_ctx *ctx, grn_obj *v, const char *data, uint32_t data_size) +{ + uint8_t *p = (uint8_t *)data; + uint8_t *pe = p + data_size; + uint32_t n, n0 = v->u.v.n_sections; + GRN_B_DEC(n, p); + if (((n0 + M_SECTIONS_UNIT) >> W_SECTIONS_UNIT) != + ((n0 + n + M_SECTIONS_UNIT) >> W_SECTIONS_UNIT)) { + grn_section *vp = GRN_REALLOC(v->u.v.sections, sizeof(grn_section) * + ((n0 + n + M_SECTIONS_UNIT) & ~M_SECTIONS_UNIT)); + if (!vp) { return GRN_NO_MEMORY_AVAILABLE; } + v->u.v.sections = vp; + } + { + grn_section *vp; + grn_obj *body = grn_vector_body(ctx, v); + uint32_t offset = GRN_BULK_VSIZE(body); + uint32_t o = 0, l, i; + for (i = n, vp = v->u.v.sections + n0; i; i--, vp++) { + if (pe <= p) { return GRN_INVALID_ARGUMENT; } + GRN_B_DEC(l, p); + vp->length = l; + vp->offset = offset + o; + vp->weight = 0; + vp->domain = 0; + o += l; + } + if (pe < p + o) { return GRN_INVALID_ARGUMENT; } + grn_bulk_write(ctx, body, (char *)p, o); + p += o; + if (p < pe) { + for (i = n, vp = v->u.v.sections + n0; i; i--, vp++) { + if (pe <= p) { return GRN_INVALID_ARGUMENT; } + GRN_B_DEC(vp->weight, p); + GRN_B_DEC(vp->domain, p); + } + } + } + v->u.v.n_sections += n; + return GRN_SUCCESS; +} + +grn_rc +grn_vector_add_element(grn_ctx *ctx, grn_obj *vector, + const char *str, unsigned int str_len, + unsigned int weight, grn_id domain) +{ + grn_obj *body; + GRN_API_ENTER; + if (!vector) { + ERR(GRN_INVALID_ARGUMENT, "vector is null"); + goto exit; + } + if ((body = grn_vector_body(ctx, vector))) { + grn_bulk_write(ctx, body, str, str_len); + grn_vector_delimit(ctx, vector, weight, domain); + } +exit : + GRN_API_RETURN(ctx->rc); +} + +/* +grn_obj * +grn_sections_to_vector(grn_ctx *ctx, grn_obj *sections) +{ + grn_obj *vector = grn_vector_open(ctx, 0); + if (vector) { + grn_section *vp; + int i; + for (i = sections->u.v.n_sections, vp = sections->u.v.sections; i; i--, vp++) { + grn_text_benc(ctx, vector, vp->weight); + grn_text_benc(ctx, vector, vp->domain); + grn_bulk_write(ctx, vector, vp->str, vp->str_len); + grn_vector_delimit(ctx, vector); + } + } + return vector; +} + +grn_obj * +grn_vector_to_sections(grn_ctx *ctx, grn_obj *vector, grn_obj *sections) +{ + if (!sections) { + sections = grn_obj_open(ctx, GRN_VECTOR, GRN_OBJ_DO_SHALLOW_COPY, 0); + } + if (sections) { + int i, n = grn_vector_size(ctx, vector); + sections->u.v.src = vector; + for (i = 0; i < n; i++) { + unsigned int size; + const uint8_t *pe, *p = (uint8_t *)grn_vector_fetch(ctx, vector, i, &size); + if (p) { + grn_id domain; + unsigned int weight; + pe = p + size; + if (p < pe) { + GRN_B_DEC(weight, p); + if (p < pe) { + GRN_B_DEC(domain, p); + if (p <= pe) { + grn_vector_add(ctx, sections, (char *)p, pe - p, weight, domain); + } + } + } + } + } + } + return sections; +} +*/ + +/**** uvector ****/ + +unsigned int +grn_uvector_size(grn_ctx *ctx, grn_obj *uvector) +{ + unsigned int size; + + if (!uvector) { + ERR(GRN_INVALID_ARGUMENT, "uvector must not be NULL"); + return 0; + } + + if (uvector->header.type != GRN_UVECTOR) { + grn_obj type_name; + GRN_TEXT_INIT(&type_name, 0); + grn_inspect_type(ctx, &type_name, uvector->header.type); + ERR(GRN_INVALID_ARGUMENT, "must be GRN_UVECTOR: %.*s", + (int)GRN_TEXT_LEN(&type_name), GRN_TEXT_VALUE(&type_name)); + GRN_OBJ_FIN(ctx, &type_name); + return 0; + } + + GRN_API_ENTER; + size = grn_uvector_size_internal(ctx, uvector); + GRN_API_RETURN(size); +} + +unsigned int +grn_uvector_element_size(grn_ctx *ctx, grn_obj *uvector) +{ + unsigned int element_size; + + if (!uvector) { + ERR(GRN_INVALID_ARGUMENT, "uvector must not be NULL"); + return 0; + } + + if (uvector->header.type != GRN_UVECTOR) { + grn_obj type_name; + GRN_TEXT_INIT(&type_name, 0); + grn_inspect_type(ctx, &type_name, uvector->header.type); + ERR(GRN_INVALID_ARGUMENT, "must be GRN_UVECTOR: %.*s", + (int)GRN_TEXT_LEN(&type_name), GRN_TEXT_VALUE(&type_name)); + GRN_OBJ_FIN(ctx, &type_name); + return 0; + } + + GRN_API_ENTER; + element_size = grn_uvector_element_size_internal(ctx, uvector); + GRN_API_RETURN(element_size); +} + +grn_rc +grn_uvector_add_element(grn_ctx *ctx, grn_obj *uvector, + grn_id id, unsigned int weight) +{ + GRN_API_ENTER; + if (!uvector) { + ERR(GRN_INVALID_ARGUMENT, "uvector is null"); + goto exit; + } + if (IS_WEIGHT_UVECTOR(uvector)) { + weight_uvector_entry entry; + entry.id = id; + entry.weight = weight; + grn_bulk_write(ctx, uvector, + (const char *)&entry, sizeof(weight_uvector_entry)); + } else { + grn_bulk_write(ctx, uvector, + (const char *)&id, sizeof(grn_id)); + } +exit : + GRN_API_RETURN(ctx->rc); +} + +grn_id +grn_uvector_get_element(grn_ctx *ctx, grn_obj *uvector, + unsigned int offset, unsigned int *weight) +{ + grn_id id = GRN_ID_NIL; + + GRN_API_ENTER; + if (!uvector || uvector->header.type != GRN_UVECTOR) { + ERR(GRN_INVALID_ARGUMENT, "invalid uvector"); + goto exit; + } + + if (IS_WEIGHT_UVECTOR(uvector)) { + const weight_uvector_entry *entry; + const weight_uvector_entry *entries_start; + const weight_uvector_entry *entries_end; + + entries_start = (const weight_uvector_entry *)GRN_BULK_HEAD(uvector); + entries_end = (const weight_uvector_entry *)GRN_BULK_CURR(uvector); + if (offset > entries_end - entries_start) { + ERR(GRN_RANGE_ERROR, "offset out of range"); + goto exit; + } + + entry = entries_start + offset; + id = entry->id; + if (weight) { *weight = entry->weight; } + } else { + const grn_id *ids_start; + const grn_id *ids_end; + + ids_start = (const grn_id *)GRN_BULK_HEAD(uvector); + ids_end = (const grn_id *)GRN_BULK_CURR(uvector); + if (offset > ids_end - ids_start) { + ERR(GRN_RANGE_ERROR, "offset out of range"); + goto exit; + } + id = ids_start[offset]; + if (weight) { *weight = 0; } + } +exit : + GRN_API_RETURN(id); +} + +/**** accessor ****/ + +static grn_accessor * +accessor_new(grn_ctx *ctx) +{ + grn_accessor *res = GRN_MALLOCN(grn_accessor, 1); + if (res) { + res->header.type = GRN_ACCESSOR; + res->header.impl_flags = GRN_OBJ_ALLOCATED; + res->header.flags = 0; + res->header.domain = GRN_ID_NIL; + res->range = GRN_ID_NIL; + res->action = GRN_ACCESSOR_VOID; + res->offset = 0; + res->obj = NULL; + res->next = NULL; + } + return res; +} + +inline static grn_bool +grn_obj_get_accessor_rset_value(grn_ctx *ctx, grn_obj *obj, + grn_accessor **res, uint8_t action) +{ + grn_bool succeeded = GRN_FALSE; + grn_accessor **rp; + + for (rp = res; GRN_TRUE; rp = &(*rp)->next) { + *rp = accessor_new(ctx); + (*rp)->obj = obj; + +#define CHECK_GROUP_CALC_FLAG(flag) do { \ + if (GRN_TABLE_IS_GROUPED(obj)) { \ + grn_table_group_flags flags; \ + flags = DB_OBJ(obj)->flags.group; \ + if (flags & flag) { \ + succeeded = GRN_TRUE; \ + (*rp)->action = action; \ + goto exit; \ + } \ + } \ + } while(GRN_FALSE) + switch (action) { + case GRN_ACCESSOR_GET_SCORE : + if (DB_OBJ(obj)->header.flags & GRN_OBJ_WITH_SUBREC) { + (*rp)->action = action; + succeeded = GRN_TRUE; + goto exit; + } + break; + case GRN_ACCESSOR_GET_MAX : + CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_MAX); + break; + case GRN_ACCESSOR_GET_MIN : + CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_MIN); + break; + case GRN_ACCESSOR_GET_SUM : + CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_SUM); + break; + case GRN_ACCESSOR_GET_AVG : + CHECK_GROUP_CALC_FLAG(GRN_TABLE_GROUP_CALC_AVG); + break; + case GRN_ACCESSOR_GET_NSUBRECS : + if (GRN_TABLE_IS_GROUPED(obj)) { + (*rp)->action = action; + succeeded = GRN_TRUE; + goto exit; + } + break; + } +#undef CHECK_GROUP_CALC_FLAG + + switch (obj->header.type) { + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_HASH_KEY : + (*rp)->action = GRN_ACCESSOR_GET_KEY; + break; + case GRN_TABLE_NO_KEY : + if (!obj->header.domain) { + goto exit; + } + (*rp)->action = GRN_ACCESSOR_GET_VALUE; + break; + default : + /* lookup failed */ + goto exit; + } + if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { + goto exit; + } + } + +exit : + if (!succeeded) { + grn_obj_close(ctx, (grn_obj *)*res); + *res = NULL; + } + + return succeeded; +} + +static grn_obj * +grn_obj_get_accessor(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int name_size) +{ + grn_accessor *res = NULL, **rp = NULL, **rp0 = NULL; + grn_bool is_chained = GRN_FALSE; + if (!obj) { return NULL; } + GRN_API_ENTER; + if (obj->header.type == GRN_ACCESSOR) { + is_chained = GRN_TRUE; + for (rp0 = (grn_accessor **)&obj; *rp0; rp0 = &(*rp0)->next) { + res = *rp0; + } + switch (res->action) { + case GRN_ACCESSOR_GET_KEY : + obj = grn_ctx_at(ctx, res->obj->header.domain); + break; + case GRN_ACCESSOR_GET_VALUE : + case GRN_ACCESSOR_GET_SCORE : + case GRN_ACCESSOR_GET_NSUBRECS : + case GRN_ACCESSOR_GET_MAX : + case GRN_ACCESSOR_GET_MIN : + case GRN_ACCESSOR_GET_SUM : + case GRN_ACCESSOR_GET_AVG : + obj = grn_ctx_at(ctx, DB_OBJ(res->obj)->range); + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + obj = grn_ctx_at(ctx, DB_OBJ(res->obj)->range); + break; + case GRN_ACCESSOR_LOOKUP : + /* todo */ + break; + case GRN_ACCESSOR_FUNCALL : + /* todo */ + break; + } + } + if (!obj) { + res = NULL; + goto exit; + } + { + size_t len; + const char *sp, *se = name + name_size; + if (*name == GRN_DB_DELIMITER) { name++; } + for (sp = name; (len = grn_charlen(ctx, sp, se)); sp += len) { + if (*sp == GRN_DB_DELIMITER) { break; } + } + if (!(len = sp - name)) { goto exit; } + if (*name == GRN_DB_PSEUDO_COLUMN_PREFIX) { /* pseudo column */ + int done = 0; + if (len < 2) { goto exit; } + switch (name[1]) { + case 'k' : /* key */ + if (len != GRN_COLUMN_NAME_KEY_LEN || + memcmp(name, GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_KEY_LEN)) { + goto exit; + } + for (rp = &res; !done; rp = &(*rp)->next) { + *rp = accessor_new(ctx); + (*rp)->obj = obj; + if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(obj)) { + (*rp)->action = GRN_ACCESSOR_GET_KEY; + done++; + break; + } + if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + switch (obj->header.type) { + case GRN_DB : + (*rp)->action = GRN_ACCESSOR_GET_KEY; + rp = &(*rp)->next; + *rp = accessor_new(ctx); + (*rp)->obj = obj; + (*rp)->action = GRN_ACCESSOR_GET_DB_OBJ; + done++; + break; + case GRN_TYPE : + (*rp)->action = GRN_ACCESSOR_GET_KEY; + done++; + break; + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_HASH_KEY : + (*rp)->action = GRN_ACCESSOR_GET_KEY; + break; + case GRN_TABLE_NO_KEY : + if (obj->header.domain) { + (*rp)->action = GRN_ACCESSOR_GET_VALUE; + break; + } + /* fallthru */ + default : + /* lookup failed */ + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + } + break; + case 'i' : /* id */ + if (len != GRN_COLUMN_NAME_ID_LEN || + memcmp(name, GRN_COLUMN_NAME_ID, GRN_COLUMN_NAME_ID_LEN)) { + goto exit; + } + for (rp = &res; !done; rp = &(*rp)->next) { + *rp = accessor_new(ctx); + (*rp)->obj = obj; + if (!obj->header.domain) { + (*rp)->action = GRN_ACCESSOR_GET_ID; + done++; + } else { + if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + switch (obj->header.type) { + case GRN_DB : + case GRN_TYPE : + (*rp)->action = GRN_ACCESSOR_GET_ID; + done++; + break; + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_NO_KEY : + (*rp)->action = GRN_ACCESSOR_GET_KEY; + break; + default : + /* lookup failed */ + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + } + } + break; + case 'v' : /* value */ + if (len != GRN_COLUMN_NAME_VALUE_LEN || + memcmp(name, GRN_COLUMN_NAME_VALUE, GRN_COLUMN_NAME_VALUE_LEN)) { + goto exit; + } + for (rp = &res; !done; rp = &(*rp)->next) { + *rp = accessor_new(ctx); + (*rp)->obj = obj; + if (!obj->header.domain) { + if (DB_OBJ((*rp)->obj)->range) { + (*rp)->action = GRN_ACCESSOR_GET_VALUE; + done++; + } else { + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + done++; + } else { + if (!(obj = grn_ctx_at(ctx, obj->header.domain))) { + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + switch (obj->header.type) { + case GRN_DB : + case GRN_TYPE : + if (DB_OBJ((*rp)->obj)->range) { + (*rp)->action = GRN_ACCESSOR_GET_VALUE; + done++; + } else { + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + break; + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_NO_KEY : + (*rp)->action = GRN_ACCESSOR_GET_KEY; + break; + default : + /* lookup failed */ + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + } + } + break; + case 's' : /* score, sum */ + if (len == GRN_COLUMN_NAME_SCORE_LEN && + memcmp(name, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_SCORE)) { + goto exit; + } + } else if (len == GRN_COLUMN_NAME_SUM_LEN && + memcmp(name, + GRN_COLUMN_NAME_SUM, + GRN_COLUMN_NAME_SUM_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_SUM)) { + goto exit; + } + } else { + goto exit; + } + break; + case 'n' : /* nsubrecs */ + if (len != GRN_COLUMN_NAME_NSUBRECS_LEN || + memcmp(name, + GRN_COLUMN_NAME_NSUBRECS, + GRN_COLUMN_NAME_NSUBRECS_LEN)) { + goto exit; + } + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_NSUBRECS)) { + goto exit; + } + break; + case 'm' : /* max, min */ + if (len == GRN_COLUMN_NAME_MAX_LEN && + memcmp(name, + GRN_COLUMN_NAME_MAX, + GRN_COLUMN_NAME_MAX_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_MAX)) { + goto exit; + } + } else if (len == GRN_COLUMN_NAME_MIN_LEN && + memcmp(name, + GRN_COLUMN_NAME_MIN, + GRN_COLUMN_NAME_MIN_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_MIN)) { + goto exit; + } + } else { + goto exit; + } + break; + case 'a' : /* avg */ + if (len == GRN_COLUMN_NAME_AVG_LEN && + memcmp(name, + GRN_COLUMN_NAME_AVG, + GRN_COLUMN_NAME_AVG_LEN) == 0) { + if (!grn_obj_get_accessor_rset_value(ctx, obj, &res, + GRN_ACCESSOR_GET_AVG)) { + goto exit; + } + } else { + goto exit; + } + break; + default : + res = NULL; + goto exit; + } + } else { + /* if obj->header.type == GRN_TYPE ... lookup table */ + for (rp = &res; ; rp = &(*rp)->next) { + grn_obj *column = grn_obj_column_(ctx, obj, name, len); + if (column) { + *rp = accessor_new(ctx); + (*rp)->obj = column; + /* + switch (column->header.type) { + case GRN_COLUMN_VAR_SIZE : + break; + case GRN_COLUMN_FIX_SIZE : + break; + case GRN_COLUMN_INDEX : + break; + } + */ + (*rp)->action = GRN_ACCESSOR_GET_COLUMN_VALUE; + break; + } else { + grn_id next_obj_id; + next_obj_id = obj->header.domain; + if (!next_obj_id) { + // ERR(GRN_INVALID_ARGUMENT, "no such column: <%s>", name); + if (!is_chained) { + grn_obj_close(ctx, (grn_obj *)res); + } + res = NULL; + goto exit; + } + *rp = accessor_new(ctx); + (*rp)->obj = obj; + obj = grn_ctx_at(ctx, next_obj_id); + if (!obj) { + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + switch (obj->header.type) { + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_NO_KEY : + (*rp)->action = GRN_ACCESSOR_GET_KEY; + break; + default : + /* lookup failed */ + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + } + } + } + if (sp != se) { + if (!grn_obj_get_accessor(ctx, (grn_obj *)res, sp, se - sp)) { + if (!is_chained) { + grn_obj_close(ctx, (grn_obj *)res); + res = NULL; + goto exit; + } + } + } + } + if (rp0) { *rp0 = res; } + exit : + GRN_API_RETURN((grn_obj *)res); +} + +inline static grn_bool +grn_column_is_vector(grn_ctx *ctx, grn_obj *column) +{ + grn_obj_flags type; + + if (column->header.type != GRN_COLUMN_VAR_SIZE) { + return GRN_FALSE; + } + + type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK; + return type == GRN_OBJ_COLUMN_VECTOR; +} + +inline static grn_bool +grn_column_is_index(grn_ctx *ctx, grn_obj *column) +{ + grn_obj_flags type; + + if (column->header.type == GRN_ACCESSOR) { + grn_accessor *a; + for (a = (grn_accessor *)column; a; a = a->next) { + if (a->next) { + continue; + } + if (a->action != GRN_ACCESSOR_GET_COLUMN_VALUE) { + return GRN_FALSE; + } + + column = a->obj; + } + } + + if (column->header.type != GRN_COLUMN_INDEX) { + return GRN_FALSE; + } + + type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK; + return type == GRN_OBJ_COLUMN_INDEX; +} + +inline static void +grn_obj_get_range_info(grn_ctx *ctx, grn_obj *obj, + grn_id *range_id, grn_obj_flags *range_flags) +{ + if (!obj) { + *range_id = GRN_ID_NIL; + } else if (grn_obj_is_proc(ctx, obj)) { + /* TODO */ + *range_id = GRN_ID_NIL; + } else if (GRN_DB_OBJP(obj)) { + *range_id = DB_OBJ(obj)->range; + if (grn_column_is_vector(ctx, obj)) { + *range_flags = GRN_OBJ_VECTOR; + } + } else if (obj->header.type == GRN_ACCESSOR) { + grn_accessor *a; + for (a = (grn_accessor *)obj; a; a = a->next) { + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + *range_id = GRN_DB_UINT32; + break; + case GRN_ACCESSOR_GET_VALUE : + if (GRN_DB_OBJP(a->obj)) { + *range_id = DB_OBJ(a->obj)->range; + } + break; + case GRN_ACCESSOR_GET_SCORE : + *range_id = GRN_DB_FLOAT; + break; + case GRN_ACCESSOR_GET_NSUBRECS : + *range_id = GRN_DB_INT32; + break; + case GRN_ACCESSOR_GET_MAX : + case GRN_ACCESSOR_GET_MIN : + case GRN_ACCESSOR_GET_SUM : + *range_id = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_AVG : + *range_id = GRN_DB_FLOAT; + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + grn_obj_get_range_info(ctx, a->obj, range_id, range_flags); + break; + case GRN_ACCESSOR_GET_KEY : + if (GRN_DB_OBJP(a->obj)) { *range_id = DB_OBJ(a->obj)->header.domain; } + break; + default : + if (GRN_DB_OBJP(a->obj)) { *range_id = DB_OBJ(a->obj)->range; } + break; + } + } + } +} + +grn_id +grn_obj_get_range(grn_ctx *ctx, grn_obj *obj) +{ + grn_id range_id = GRN_ID_NIL; + grn_obj_flags range_flags = 0; + + grn_obj_get_range_info(ctx, obj, &range_id, &range_flags); + + return range_id; +} + +int +grn_obj_is_persistent(grn_ctx *ctx, grn_obj *obj) +{ + int res = 0; + if (GRN_DB_OBJP(obj)) { + res = IS_TEMP(obj) ? 0 : 1; + } else if (obj->header.type == GRN_ACCESSOR) { + grn_accessor *a; + for (a = (grn_accessor *)obj; a; a = a->next) { + switch (a->action) { + case GRN_ACCESSOR_GET_SCORE : + case GRN_ACCESSOR_GET_NSUBRECS : + case GRN_ACCESSOR_GET_MAX : + case GRN_ACCESSOR_GET_MIN : + case GRN_ACCESSOR_GET_SUM : + case GRN_ACCESSOR_GET_AVG : + res = 0; + break; + case GRN_ACCESSOR_GET_ID : + case GRN_ACCESSOR_GET_VALUE : + case GRN_ACCESSOR_GET_COLUMN_VALUE : + case GRN_ACCESSOR_GET_KEY : + if (GRN_DB_OBJP(a->obj)) { res = IS_TEMP(obj) ? 0 : 1; } + break; + default : + if (GRN_DB_OBJP(a->obj)) { res = IS_TEMP(obj) ? 0 : 1; } + break; + } + } + } + return res; +} + +#define SRC2RECORD() do {\ + grn_obj *table = grn_ctx_at(ctx, dest->header.domain);\ + if (GRN_OBJ_TABLEP(table)) {\ + grn_obj *p_key = src;\ + grn_id id;\ + if (table->header.type != GRN_TABLE_NO_KEY) {\ + grn_obj key;\ + GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain);\ + if (src->header.domain != table->header.domain) {\ + rc = grn_obj_cast(ctx, src, &key, GRN_TRUE);\ + p_key = &key;\ + }\ + if (!rc) {\ + if (GRN_BULK_VSIZE(p_key)) {\ + if (add_record_if_not_exist) {\ + id = grn_table_add_by_key(ctx, table, p_key, NULL);\ + } else {\ + id = grn_table_get_by_key(ctx, table, p_key);\ + }\ + if (id) {\ + GRN_RECORD_SET(ctx, dest, id);\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + } else {\ + GRN_RECORD_SET(ctx, dest, GRN_ID_NIL);\ + }\ + }\ + GRN_OBJ_FIN(ctx, &key);\ + } else {\ + grn_obj record_id;\ + GRN_UINT32_INIT(&record_id, 0);\ + rc = grn_obj_cast(ctx, src, &record_id, GRN_TRUE);\ + if (!rc) {\ + id = GRN_UINT32_VALUE(&record_id);\ + if (id) {\ + GRN_RECORD_SET(ctx, dest, id);\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + }\ + }\ + } else {\ + rc = GRN_FUNCTION_NOT_IMPLEMENTED;\ + }\ +} while (0) + +inline static grn_rc +grn_obj_cast_bool(grn_ctx *ctx, grn_obj *src, grn_obj *dest, + grn_bool add_record_if_not_exist) +{ + grn_rc rc = GRN_SUCCESS; + + switch (dest->header.domain) { + case GRN_DB_BOOL : + GRN_BOOL_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_INT8 : + GRN_INT8_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_UINT8 : + GRN_UINT8_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_INT16 : + GRN_INT16_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_UINT16 : + GRN_UINT16_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_INT32 : + GRN_INT32_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_UINT32 : + GRN_UINT32_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_INT64 : + GRN_INT64_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_UINT64 : + GRN_UINT64_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_FLOAT : + GRN_FLOAT_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_TIME : + GRN_TIME_SET(ctx, dest, GRN_BOOL_VALUE(src)); + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + { + const char *bool_text; + bool_text = GRN_BOOL_VALUE(src) ? "true" : "false"; + GRN_TEXT_PUTS(ctx, dest, bool_text); + } + break; + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + rc = GRN_INVALID_ARGUMENT; + break; + default : + SRC2RECORD(); + break; + } + return rc; +} + +#define NUM2DEST(getvalue,totext,tobool,totime,tofloat)\ + switch (dest->header.domain) {\ + case GRN_DB_BOOL :\ + tobool(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_INT8 :\ + GRN_INT8_SET(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_UINT8 :\ + GRN_UINT8_SET(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_INT16 :\ + GRN_INT16_SET(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_UINT16 :\ + GRN_UINT16_SET(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_INT32 :\ + GRN_INT32_SET(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_UINT32 :\ + GRN_UINT32_SET(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_TIME :\ + totime(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_INT64 :\ + GRN_INT64_SET(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_UINT64 :\ + GRN_UINT64_SET(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_FLOAT :\ + tofloat(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + totext(ctx, dest, getvalue(src));\ + break;\ + case GRN_DB_TOKYO_GEO_POINT :\ + case GRN_DB_WGS84_GEO_POINT :\ + rc = GRN_INVALID_ARGUMENT;\ + break;\ + default :\ + SRC2RECORD();\ + break;\ + } + +#define TEXT2DEST(type,tonum,setvalue) do {\ + const char *cur, *str = GRN_TEXT_VALUE(src);\ + const char *str_end = GRN_BULK_CURR(src);\ + type i = tonum(str, str_end, &cur);\ + if (cur == str_end) {\ + setvalue(ctx, dest, i);\ + } else if (cur != str) {\ + const char *rest;\ + grn_obj buf;\ + GRN_VOID_INIT(&buf);\ + rc = grn_aton(ctx, str, str_end, &rest, &buf);\ + if (!rc) {\ + rc = grn_obj_cast(ctx, &buf, dest, add_record_if_not_exist);\ + }\ + GRN_OBJ_FIN(ctx, &buf);\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ +} while (0) + +#define NUM2BOOL(ctx, dest, value) GRN_BOOL_SET(ctx, dest, value != 0) +#define FLOAT2BOOL(ctx, dest, value) do {\ + double value_ = value;\ + GRN_BOOL_SET(ctx, dest, value_ < -DBL_EPSILON || DBL_EPSILON < value_);\ +} while (0) + +#define NUM2TIME(ctx, dest, value)\ + GRN_TIME_SET(ctx, dest, (long long int)(value) * GRN_TIME_USEC_PER_SEC); +#define TIME2TIME(ctx, dest, value)\ + GRN_TIME_SET(ctx, dest, value); +#define FLOAT2TIME(ctx, dest, value) do {\ + int64_t usec = llround(value * GRN_TIME_USEC_PER_SEC);\ + GRN_TIME_SET(ctx, dest, usec);\ +} while (0) + +#define NUM2FLOAT(ctx, dest, value)\ + GRN_FLOAT_SET(ctx, dest, value); +#define TIME2FLOAT(ctx, dest, value)\ + GRN_FLOAT_SET(ctx, dest, (double)(value) / GRN_TIME_USEC_PER_SEC); +#define FLOAT2FLOAT(ctx, dest, value)\ + GRN_FLOAT_SET(ctx, dest, value); + +static grn_rc +grn_obj_cast_record(grn_ctx *ctx, + grn_obj *src, + grn_obj *dest, + grn_bool add_record_if_not_exist) +{ + grn_obj *src_table; + grn_obj *dest_table; + const char *key; + uint32_t key_size; + grn_id dest_id; + + if (src->header.domain == dest->header.domain) { + GRN_RECORD_SET(ctx, dest, GRN_RECORD_VALUE(src)); + return GRN_SUCCESS; + } + + src_table = grn_ctx_at(ctx, src->header.domain); + if (!src_table) { + return GRN_INVALID_ARGUMENT; + } + if (src_table->header.type == GRN_TABLE_NO_KEY) { + return GRN_INVALID_ARGUMENT; + } + + dest_table = grn_ctx_at(ctx, dest->header.domain); + if (!dest_table) { + return GRN_INVALID_ARGUMENT; + } + switch (dest_table->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + break; + default : + return GRN_INVALID_ARGUMENT; + } + + if (GRN_RECORD_VALUE(src) == GRN_ID_NIL) { + GRN_RECORD_SET(ctx, dest, GRN_RECORD_VALUE(src)); + return GRN_SUCCESS; + } + + key = _grn_table_key(ctx, src_table, GRN_RECORD_VALUE(src), &key_size); + if (add_record_if_not_exist) { + dest_id = grn_table_add(ctx, dest_table, key, key_size, NULL); + } else { + dest_id = grn_table_get(ctx, dest_table, key, key_size); + } + GRN_RECORD_SET(ctx, dest, dest_id); + return GRN_SUCCESS; +} + +grn_rc +grn_obj_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, + grn_bool add_record_if_not_exist) +{ + grn_rc rc = GRN_SUCCESS; + switch (src->header.domain) { + case GRN_DB_BOOL : + rc = grn_obj_cast_bool(ctx, src, dest, add_record_if_not_exist); + break; + case GRN_DB_INT8 : + NUM2DEST(GRN_INT8_VALUE, grn_text_itoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); + break; + case GRN_DB_UINT8 : + NUM2DEST(GRN_UINT8_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); + break; + case GRN_DB_INT16 : + NUM2DEST(GRN_INT16_VALUE, grn_text_itoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); + break; + case GRN_DB_UINT16 : + NUM2DEST(GRN_UINT16_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); + break; + case GRN_DB_INT32 : + NUM2DEST(GRN_INT32_VALUE, grn_text_itoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); + break; + case GRN_DB_UINT32 : + NUM2DEST(GRN_UINT32_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); + break; + case GRN_DB_INT64 : + NUM2DEST(GRN_INT64_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); + break; + case GRN_DB_TIME : + NUM2DEST(GRN_TIME_VALUE, grn_text_lltoa, NUM2BOOL, TIME2TIME, TIME2FLOAT); + break; + case GRN_DB_UINT64 : + NUM2DEST(GRN_UINT64_VALUE, grn_text_lltoa, NUM2BOOL, NUM2TIME, NUM2FLOAT); + break; + case GRN_DB_FLOAT : + NUM2DEST(GRN_FLOAT_VALUE, grn_text_ftoa, FLOAT2BOOL, FLOAT2TIME, + FLOAT2FLOAT); + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + switch (dest->header.domain) { + case GRN_DB_BOOL : + GRN_BOOL_SET(ctx, dest, GRN_TEXT_LEN(src) > 0); + break; + case GRN_DB_INT8 : + TEXT2DEST(int8_t, grn_atoi8, GRN_INT8_SET); + break; + case GRN_DB_UINT8 : + TEXT2DEST(uint8_t, grn_atoui8, GRN_UINT8_SET); + break; + case GRN_DB_INT16 : + TEXT2DEST(int16_t, grn_atoi16, GRN_INT16_SET); + break; + case GRN_DB_UINT16 : + TEXT2DEST(uint16_t, grn_atoui16, GRN_UINT16_SET); + break; + case GRN_DB_INT32 : + TEXT2DEST(int32_t, grn_atoi, GRN_INT32_SET); + break; + case GRN_DB_UINT32 : + TEXT2DEST(uint32_t, grn_atoui, GRN_UINT32_SET); + break; + case GRN_DB_TIME : + { + grn_timeval v; + int len = GRN_TEXT_LEN(src); + char *str = GRN_TEXT_VALUE(src); + if (grn_str2timeval(str, len, &v)) { + double d; + char *end; + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_PUT(ctx, &buf, str, len); + GRN_TEXT_PUTC(ctx, &buf, '\0'); + errno = 0; + d = strtod(GRN_TEXT_VALUE(&buf), &end); + if (!errno && end + 1 == GRN_BULK_CURR(&buf)) { + v.tv_sec = d; + v.tv_nsec = ((d - v.tv_sec) * GRN_TIME_NSEC_PER_SEC); + } else { + rc = GRN_INVALID_ARGUMENT; + } + GRN_OBJ_FIN(ctx, &buf); + } + GRN_TIME_SET(ctx, dest, + GRN_TIME_PACK((int64_t)v.tv_sec, + GRN_TIME_NSEC_TO_USEC(v.tv_nsec))); + } + break; + case GRN_DB_INT64 : + TEXT2DEST(int64_t, grn_atoll, GRN_INT64_SET); + break; + case GRN_DB_UINT64 : + TEXT2DEST(int64_t, grn_atoll, GRN_UINT64_SET); + break; + case GRN_DB_FLOAT : + { + double d; + char *end; + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_PUT(ctx, &buf, GRN_TEXT_VALUE(src), GRN_TEXT_LEN(src)); + GRN_TEXT_PUTC(ctx, &buf, '\0'); + errno = 0; + d = strtod(GRN_TEXT_VALUE(&buf), &end); + if (!errno && end + 1 == GRN_BULK_CURR(&buf)) { + GRN_FLOAT_SET(ctx, dest, d); + } else { + rc = GRN_INVALID_ARGUMENT; + } + GRN_OBJ_FIN(ctx, &buf); + } + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + GRN_TEXT_PUT(ctx, dest, GRN_TEXT_VALUE(src), GRN_TEXT_LEN(src)); + break; + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + { + int latitude, longitude; + double degree; + const char *cur, *str = GRN_TEXT_VALUE(src); + const char *str_end = GRN_BULK_CURR(src); + if (str == str_end) { + GRN_GEO_POINT_SET(ctx, dest, 0, 0); + } else { + char *end; + grn_obj buf, *buf_p = NULL; + latitude = grn_atoi(str, str_end, &cur); + if (cur < str_end && cur[0] == '.') { + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_PUT(ctx, &buf, str, GRN_TEXT_LEN(src)); + GRN_TEXT_PUTC(ctx, &buf, '\0'); + buf_p = &buf; + errno = 0; + degree = strtod(GRN_TEXT_VALUE(buf_p), &end); + if (errno) { + rc = GRN_INVALID_ARGUMENT; + } else { + latitude = GRN_GEO_DEGREE2MSEC(degree); + cur = str + (end - GRN_TEXT_VALUE(buf_p)); + } + } + if (!rc && (cur[0] == 'x' || cur[0] == ',') && cur + 1 < str_end) { + const char *c = cur + 1; + longitude = grn_atoi(c, str_end, &cur); + if (cur < str_end && cur[0] == '.') { + if (!buf_p) { + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_PUT(ctx, &buf, str, GRN_TEXT_LEN(src)); + GRN_TEXT_PUTC(ctx, &buf, '\0'); + buf_p = &buf; + } + errno = 0; + degree = strtod(GRN_TEXT_VALUE(buf_p) + (c - str), &end); + if (errno) { + rc = GRN_INVALID_ARGUMENT; + } else { + longitude = GRN_GEO_DEGREE2MSEC(degree); + cur = str + (end - GRN_TEXT_VALUE(buf_p)); + } + } + if (!rc && cur == str_end) { + if ((GRN_GEO_MIN_LATITUDE <= latitude && + latitude <= GRN_GEO_MAX_LATITUDE) && + (GRN_GEO_MIN_LONGITUDE <= longitude && + longitude <= GRN_GEO_MAX_LONGITUDE)) { + GRN_GEO_POINT_SET(ctx, dest, latitude, longitude); + } else { + rc = GRN_INVALID_ARGUMENT; + } + } else { + rc = GRN_INVALID_ARGUMENT; + } + } else { + rc = GRN_INVALID_ARGUMENT; + } + if (buf_p) { GRN_OBJ_FIN(ctx, buf_p); } + } + } + break; + default : + SRC2RECORD(); + break; + } + break; + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + if (src->header.domain == dest->header.domain) { + GRN_TEXT_PUT(ctx, dest, GRN_TEXT_VALUE(src), GRN_TEXT_LEN(src)); + } else { + int latitude, longitude; + double latitude_in_degree, longitude_in_degree; + GRN_GEO_POINT_VALUE(src, latitude, longitude); + latitude_in_degree = GRN_GEO_MSEC2DEGREE(latitude); + longitude_in_degree = GRN_GEO_MSEC2DEGREE(longitude); + /* TokyoGeoPoint <-> WGS84GeoPoint is based on + http://www.jalan.net/jw/jwp0200/jww0203.do + + jx: longitude in degree in Tokyo Geodetic System. + jy: latitude in degree in Tokyo Geodetic System. + wx: longitude in degree in WGS 84. + wy: latitude in degree in WGS 84. + + jy = wy * 1.000106961 - wx * 0.000017467 - 0.004602017 + jx = wx * 1.000083049 + wy * 0.000046047 - 0.010041046 + + wy = jy - jy * 0.00010695 + jx * 0.000017464 + 0.0046017 + wx = jx - jy * 0.000046038 - jx * 0.000083043 + 0.010040 + */ + if (dest->header.domain == GRN_DB_TOKYO_GEO_POINT) { + double wgs84_latitude_in_degree = latitude_in_degree; + double wgs84_longitude_in_degree = longitude_in_degree; + int tokyo_latitude, tokyo_longitude; + double tokyo_latitude_in_degree, tokyo_longitude_in_degree; + tokyo_latitude_in_degree = + wgs84_latitude_in_degree * 1.000106961 - + wgs84_longitude_in_degree * 0.000017467 - + 0.004602017; + tokyo_longitude_in_degree = + wgs84_longitude_in_degree * 1.000083049 + + wgs84_latitude_in_degree * 0.000046047 - + 0.010041046; + tokyo_latitude = GRN_GEO_DEGREE2MSEC(tokyo_latitude_in_degree); + tokyo_longitude = GRN_GEO_DEGREE2MSEC(tokyo_longitude_in_degree); + GRN_GEO_POINT_SET(ctx, dest, tokyo_latitude, tokyo_longitude); + } else { + double tokyo_latitude_in_degree = latitude_in_degree; + double tokyo_longitude_in_degree = longitude_in_degree; + int wgs84_latitude, wgs84_longitude; + double wgs84_latitude_in_degree, wgs84_longitude_in_degree; + wgs84_latitude_in_degree = + tokyo_latitude_in_degree - + tokyo_latitude_in_degree * 0.00010695 + + tokyo_longitude_in_degree * 0.000017464 + + 0.0046017; + wgs84_longitude_in_degree = + tokyo_longitude_in_degree - + tokyo_latitude_in_degree * 0.000046038 - + tokyo_longitude_in_degree * 0.000083043 + + 0.010040; + wgs84_latitude = GRN_GEO_DEGREE2MSEC(wgs84_latitude_in_degree); + wgs84_longitude = GRN_GEO_DEGREE2MSEC(wgs84_longitude_in_degree); + GRN_GEO_POINT_SET(ctx, dest, wgs84_latitude, wgs84_longitude); + } + } + break; + case GRN_VOID : + rc = grn_obj_reinit(ctx, dest, dest->header.domain, dest->header.flags); + break; + default : + if (src->header.domain >= GRN_N_RESERVED_TYPES) { + grn_obj *table; + table = grn_ctx_at(ctx, src->header.domain); + switch (table->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + rc = grn_obj_cast_record(ctx, src, dest, add_record_if_not_exist); + break; + default : + rc = GRN_FUNCTION_NOT_IMPLEMENTED; + break; + } + } else { + rc = GRN_FUNCTION_NOT_IMPLEMENTED; + } + break; + } + return rc; +} + +const char * +grn_accessor_get_value_(grn_ctx *ctx, grn_accessor *a, grn_id id, uint32_t *size) +{ + const char *value = NULL; + for (;;) { + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + value = (const char *)(uintptr_t)id; + *size = GRN_OBJ_GET_VALUE_IMD; + break; + case GRN_ACCESSOR_GET_KEY : + value = _grn_table_key(ctx, a->obj, id, size); + break; + case GRN_ACCESSOR_GET_VALUE : + value = grn_obj_get_value_(ctx, a->obj, id, size); + break; + case GRN_ACCESSOR_GET_SCORE : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = (const char *)&((grn_rset_recinfo *)value)->score; + *size = sizeof(double); + } + break; + case GRN_ACCESSOR_GET_NSUBRECS : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = (const char *)&((grn_rset_recinfo *)value)->n_subrecs; + *size = sizeof(int); + } + break; + case GRN_ACCESSOR_GET_MAX : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = + (const char *)grn_rset_recinfo_get_max_(ctx, + (grn_rset_recinfo *)value, + a->obj); + *size = GRN_RSET_MAX_SIZE; + } + break; + case GRN_ACCESSOR_GET_MIN : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = + (const char *)grn_rset_recinfo_get_min_(ctx, + (grn_rset_recinfo *)value, + a->obj); + *size = GRN_RSET_MIN_SIZE; + } + break; + case GRN_ACCESSOR_GET_SUM : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = + (const char *)grn_rset_recinfo_get_sum_(ctx, + (grn_rset_recinfo *)value, + a->obj); + *size = GRN_RSET_SUM_SIZE; + } + break; + case GRN_ACCESSOR_GET_AVG : + if ((value = grn_obj_get_value_(ctx, a->obj, id, size))) { + value = + (const char *)grn_rset_recinfo_get_avg_(ctx, + (grn_rset_recinfo *)value, + a->obj); + *size = GRN_RSET_AVG_SIZE; + } + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + /* todo : support vector */ + value = grn_obj_get_value_(ctx, a->obj, id, size); + break; + case GRN_ACCESSOR_GET_DB_OBJ : + value = _grn_table_key(ctx, ((grn_db *)ctx->impl->db)->keys, id, size); + break; + case GRN_ACCESSOR_LOOKUP : + /* todo */ + break; + case GRN_ACCESSOR_FUNCALL : + /* todo */ + break; + } + if (value && (a = a->next)) { + id = *((grn_id *)value); + } else { + break; + } + } + return value; +} + +static grn_obj * +grn_accessor_get_value(grn_ctx *ctx, grn_accessor *a, grn_id id, grn_obj *value) +{ + uint32_t vs = 0; + uint32_t size0; + void *vp = NULL; + if (!value) { + if (!(value = grn_obj_open(ctx, GRN_BULK, 0, 0))) { return NULL; } + } else { + value->header.type = GRN_BULK; + } + size0 = GRN_BULK_VSIZE(value); + for (;;) { + grn_bulk_truncate(ctx, value, size0); + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + GRN_UINT32_PUT(ctx, value, id); + value->header.domain = GRN_DB_UINT32; + vp = GRN_BULK_HEAD(value) + size0; + vs = GRN_BULK_VSIZE(value) - size0; + break; + case GRN_ACCESSOR_GET_KEY : + if (!a->next && GRN_TABLE_IS_MULTI_KEYS_GROUPED(a->obj)) { + grn_obj_ensure_vector(ctx, value); + if (id) { + grn_obj raw_vector; + GRN_TEXT_INIT(&raw_vector, 0); + grn_table_get_key2(ctx, a->obj, id, &raw_vector); + grn_vector_decode(ctx, value, + GRN_BULK_HEAD(&raw_vector), + GRN_BULK_VSIZE(&raw_vector)); + GRN_OBJ_FIN(ctx, &raw_vector); + } + vp = NULL; + vs = 0; + } else { + if (id) { + grn_table_get_key2(ctx, a->obj, id, value); + vp = GRN_BULK_HEAD(value) + size0; + vs = GRN_BULK_VSIZE(value) - size0; + } else { + vp = NULL; + vs = 0; + } + value->header.domain = a->obj->header.domain; + } + break; + case GRN_ACCESSOR_GET_VALUE : + grn_obj_get_value(ctx, a->obj, id, value); + vp = GRN_BULK_HEAD(value) + size0; + vs = GRN_BULK_VSIZE(value) - size0; + break; + case GRN_ACCESSOR_GET_SCORE : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + GRN_FLOAT_PUT(ctx, value, ri->score); + } else { + GRN_FLOAT_PUT(ctx, value, 0.0); + } + value->header.domain = GRN_DB_FLOAT; + break; + case GRN_ACCESSOR_GET_NSUBRECS : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + GRN_INT32_PUT(ctx, value, ri->n_subrecs); + } else { + GRN_INT32_PUT(ctx, value, 0); + } + value->header.domain = GRN_DB_INT32; + break; + case GRN_ACCESSOR_GET_MAX : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t max; + max = grn_rset_recinfo_get_max(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, value, max); + } else { + GRN_INT64_PUT(ctx, value, 0); + } + value->header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_MIN : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t min; + min = grn_rset_recinfo_get_min(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, value, min); + } else { + GRN_INT64_PUT(ctx, value, 0); + } + value->header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_SUM : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t sum; + sum = grn_rset_recinfo_get_sum(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, value, sum); + } else { + GRN_INT64_PUT(ctx, value, 0); + } + value->header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_AVG : + if (id) { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + double avg; + avg = grn_rset_recinfo_get_avg(ctx, ri, a->obj); + GRN_FLOAT_PUT(ctx, value, avg); + } else { + GRN_FLOAT_PUT(ctx, value, 0.0); + } + value->header.domain = GRN_DB_FLOAT; + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + /* todo : support vector */ + grn_obj_get_value(ctx, a->obj, id, value); + vp = GRN_BULK_HEAD(value) + size0; + vs = GRN_BULK_VSIZE(value) - size0; + break; + case GRN_ACCESSOR_GET_DB_OBJ : + value = grn_ctx_at(ctx, id); + grn_obj_close(ctx, value); + return value; + break; + case GRN_ACCESSOR_LOOKUP : + /* todo */ + break; + case GRN_ACCESSOR_FUNCALL : + /* todo */ + break; + } + if ((a = a->next)) { + if (vs > 0) { + id = *((grn_id *)vp); + } else { + id = GRN_ID_NIL; + } + } else { + break; + } + } + return value; +} + +static grn_rc +grn_accessor_set_value(grn_ctx *ctx, grn_accessor *a, grn_id id, + grn_obj *value, int flags) +{ + grn_rc rc = GRN_SUCCESS; + if (!value) { value = grn_obj_open(ctx, GRN_BULK, 0, 0); } + if (value) { + grn_obj buf; + void *vp = NULL; + GRN_TEXT_INIT(&buf, 0); + for (;;) { + GRN_BULK_REWIND(&buf); + switch (a->action) { + case GRN_ACCESSOR_GET_KEY : + grn_table_get_key2(ctx, a->obj, id, &buf); + vp = GRN_BULK_HEAD(&buf); + break; + case GRN_ACCESSOR_GET_VALUE : + if (a->next) { + grn_obj_get_value(ctx, a->obj, id, &buf); + vp = GRN_BULK_HEAD(&buf); + } else { + rc = grn_obj_set_value(ctx, a->obj, id, value, flags); + } + break; + case GRN_ACCESSOR_GET_SCORE : + { + grn_rset_recinfo *ri; + if (a->next) { + grn_obj_get_value(ctx, a->obj, id, &buf); + ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + vp = &ri->score; + } else { + uint32_t size; + if ((ri = (grn_rset_recinfo *) grn_obj_get_value_(ctx, a->obj, id, &size))) { + // todo : flags support + if (value->header.domain == GRN_DB_FLOAT) { + ri->score = GRN_FLOAT_VALUE(value); + } else { + grn_obj buf; + GRN_FLOAT_INIT(&buf, 0); + grn_obj_cast(ctx, value, &buf, GRN_FALSE); + ri->score = GRN_FLOAT_VALUE(&buf); + GRN_OBJ_FIN(ctx, &buf); + } + } + } + } + break; + case GRN_ACCESSOR_GET_NSUBRECS : + grn_obj_get_value(ctx, a->obj, id, &buf); + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + vp = &ri->n_subrecs; + } + break; + case GRN_ACCESSOR_GET_MAX : + grn_obj_get_value(ctx, a->obj, id, &buf); + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + if (value->header.type == GRN_DB_INT64) { + grn_rset_recinfo_set_max(ctx, ri, a->obj, GRN_INT64_VALUE(value)); + } else { + grn_obj value_int64; + GRN_INT64_INIT(&value_int64, 0); + if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) { + grn_rset_recinfo_set_max(ctx, ri, a->obj, + GRN_INT64_VALUE(&value_int64)); + } + GRN_OBJ_FIN(ctx, &value_int64); + } + } + break; + case GRN_ACCESSOR_GET_MIN : + grn_obj_get_value(ctx, a->obj, id, &buf); + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + if (value->header.type == GRN_DB_INT64) { + grn_rset_recinfo_set_min(ctx, ri, a->obj, GRN_INT64_VALUE(value)); + } else { + grn_obj value_int64; + GRN_INT64_INIT(&value_int64, 0); + if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) { + grn_rset_recinfo_set_min(ctx, ri, a->obj, + GRN_INT64_VALUE(&value_int64)); + } + GRN_OBJ_FIN(ctx, &value_int64); + } + } + break; + case GRN_ACCESSOR_GET_SUM : + grn_obj_get_value(ctx, a->obj, id, &buf); + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + if (value->header.type == GRN_DB_INT64) { + grn_rset_recinfo_set_sum(ctx, ri, a->obj, GRN_INT64_VALUE(value)); + } else { + grn_obj value_int64; + GRN_INT64_INIT(&value_int64, 0); + if (!grn_obj_cast(ctx, value, &value_int64, GRN_FALSE)) { + grn_rset_recinfo_set_sum(ctx, ri, a->obj, + GRN_INT64_VALUE(&value_int64)); + } + GRN_OBJ_FIN(ctx, &value_int64); + } + } + break; + case GRN_ACCESSOR_GET_AVG : + grn_obj_get_value(ctx, a->obj, id, &buf); + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)GRN_BULK_HEAD(&buf); + if (value->header.type == GRN_DB_FLOAT) { + grn_rset_recinfo_set_avg(ctx, ri, a->obj, GRN_FLOAT_VALUE(value)); + } else { + grn_obj value_float; + GRN_FLOAT_INIT(&value_float, 0); + if (!grn_obj_cast(ctx, value, &value_float, GRN_FALSE)) { + grn_rset_recinfo_set_avg(ctx, ri, a->obj, + GRN_FLOAT_VALUE(&value_float)); + } + GRN_OBJ_FIN(ctx, &value_float); + } + } + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + /* todo : support vector */ + if (a->next) { + grn_obj_get_value(ctx, a->obj, id, &buf); + vp = GRN_BULK_HEAD(&buf); + } else { + rc = grn_obj_set_value(ctx, a->obj, id, value, flags); + } + break; + case GRN_ACCESSOR_LOOKUP : + /* todo */ + break; + case GRN_ACCESSOR_FUNCALL : + /* todo */ + break; + } + if ((a = a->next)) { + id = *((grn_id *)vp); + } else { + break; + } + } + grn_obj_close(ctx, &buf); + } + return rc; +} + +#define INCRDECR(op) \ + switch (DB_OBJ(obj)->range) {\ + case GRN_DB_INT8 :\ + if (s == sizeof(int8_t)) {\ + int8_t *vp = (int8_t *)p;\ + *vp op *(int8_t *)v;\ + rc = GRN_SUCCESS;\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + break;\ + case GRN_DB_UINT8 :\ + if (s == sizeof(uint8_t)) {\ + uint8_t *vp = (uint8_t *)p;\ + *vp op *(int8_t *)v;\ + rc = GRN_SUCCESS;\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + break;\ + case GRN_DB_INT16 :\ + if (s == sizeof(int16_t)) {\ + int16_t *vp = (int16_t *)p;\ + *vp op *(int16_t *)v;\ + rc = GRN_SUCCESS;\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + break;\ + case GRN_DB_UINT16 :\ + if (s == sizeof(uint16_t)) {\ + uint16_t *vp = (uint16_t *)p;\ + *vp op *(int16_t *)v;\ + rc = GRN_SUCCESS;\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + break;\ + case GRN_DB_INT32 :\ + if (s == sizeof(int32_t)) {\ + int32_t *vp = (int32_t *)p;\ + *vp op *(int32_t *)v;\ + rc = GRN_SUCCESS;\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + break;\ + case GRN_DB_UINT32 :\ + if (s == sizeof(uint32_t)) {\ + uint32_t *vp = (uint32_t *)p;\ + *vp op *(int32_t *)v;\ + rc = GRN_SUCCESS;\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + break;\ + case GRN_DB_INT64 :\ + case GRN_DB_TIME :\ + if (s == sizeof(int64_t)) {\ + int64_t *vp = (int64_t *)p;\ + *vp op *(int64_t *)v;\ + rc = GRN_SUCCESS;\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + break;\ + case GRN_DB_FLOAT :\ + if (s == sizeof(double)) {\ + double *vp = (double *)p;\ + *vp op *(double *)v;\ + rc = GRN_SUCCESS;\ + } else {\ + rc = GRN_INVALID_ARGUMENT;\ + }\ + break;\ + default :\ + rc = GRN_OPERATION_NOT_SUPPORTED;\ + break;\ + } + +uint32_t +grn_obj_size(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { return 0; } + switch (obj->header.type) { + case GRN_VOID : + case GRN_BULK : + case GRN_PTR : + case GRN_UVECTOR : + case GRN_PVECTOR : + case GRN_MSG : + return GRN_BULK_VSIZE(obj); + case GRN_VECTOR : + return obj->u.v.body ? GRN_BULK_VSIZE(obj->u.v.body) : 0; + default : + return 0; + } +} + +inline static int +call_hook(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value, int flags) +{ + grn_hook *hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET]; + void *v = GRN_BULK_HEAD(value); + unsigned int s = grn_obj_size(ctx, value); + if (hooks || obj->header.type == GRN_COLUMN_VAR_SIZE) { + grn_obj oldbuf, *oldvalue; + GRN_TEXT_INIT(&oldbuf, 0); + oldvalue = grn_obj_get_value(ctx, obj, id, &oldbuf); + if (flags & GRN_OBJ_SET) { + void *ov; + unsigned int os; + ov = GRN_BULK_HEAD(oldvalue); + os = grn_obj_size(ctx, oldvalue); + if ((ov && v && os == s && !memcmp(ov, v, s)) && + !(obj->header.type == GRN_COLUMN_FIX_SIZE && + grn_bulk_is_zero(ctx, value))) { + grn_obj_close(ctx, oldvalue); + return 0; + } + } + if (hooks) { + // todo : grn_proc_ctx_open() + grn_obj id_, flags_; + grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4, {{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}}}; + GRN_UINT32_INIT(&id_, 0); + GRN_UINT32_INIT(&flags_, 0); + GRN_UINT32_SET(ctx, &id_, id); + GRN_UINT32_SET(ctx, &flags_, flags); + while (hooks) { + grn_ctx_push(ctx, &id_); + grn_ctx_push(ctx, oldvalue); + grn_ctx_push(ctx, value); + grn_ctx_push(ctx, &flags_); + pctx.caller = NULL; + pctx.currh = hooks; + if (hooks->proc) { + hooks->proc->funcs[PROC_INIT](ctx, 1, &obj, &pctx.user_data); + } else { + grn_obj_default_set_value_hook(ctx, 1, &obj, &pctx.user_data); + } + if (ctx->rc) { + grn_obj_close(ctx, oldvalue); + return 1; + } + hooks = hooks->next; + pctx.offset++; + } + } + grn_obj_close(ctx, oldvalue); + } + return 0; +} + +static grn_rc +grn_obj_set_value_table_pat_key(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_obj *value, int flags) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_id range = DB_OBJ(obj)->range; + void *v = GRN_BULK_HEAD(value); + grn_obj buf; + + if (call_hook(ctx, obj, id, value, flags)) { + if (ctx->rc) { + rc = ctx->rc; + } + return rc; + } + + if (range != value->header.domain) { + GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); + if (grn_obj_cast(ctx, value, &buf, GRN_TRUE) == GRN_SUCCESS) { + v = GRN_BULK_HEAD(&buf); + } + } + rc = grn_pat_set_value(ctx, (grn_pat *)obj, id, v, flags); + if (range != value->header.domain) { + grn_obj_close(ctx, &buf); + } + + return rc; +} + +static grn_rc +grn_obj_set_value_table_hash_key(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_obj *value, int flags) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_id range = DB_OBJ(obj)->range; + void *v = GRN_BULK_HEAD(value); + grn_obj buf; + + if (call_hook(ctx, obj, id, value, flags)) { + if (ctx->rc) { + rc = ctx->rc; + } + return rc; + } + + if (range != value->header.domain) { + GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); + if (grn_obj_cast(ctx, value, &buf, GRN_TRUE) == GRN_SUCCESS) { + v = GRN_BULK_HEAD(&buf); + } + } + rc = grn_hash_set_value(ctx, (grn_hash *)obj, id, v, flags); + if (range != value->header.domain) { + grn_obj_close(ctx, &buf); + } + + return rc; +} + +static grn_rc +grn_obj_set_value_table_no_key(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_obj *value, int flags) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_id range = DB_OBJ(obj)->range; + void *v = GRN_BULK_HEAD(value); + grn_obj buf; + + if (call_hook(ctx, obj, id, value, flags)) { + if (ctx->rc) { + rc = ctx->rc; + } + return rc; + } + + if (range != value->header.domain) { + GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); + if (grn_obj_cast(ctx, value, &buf, GRN_TRUE) == GRN_SUCCESS) { + v = GRN_BULK_HEAD(&buf); + } + } + rc = grn_array_set_value(ctx, (grn_array *)obj, id, v, flags); + if (range != value->header.domain) { + grn_obj_close(ctx, &buf); + } + + return rc; +} + +static grn_rc +grn_obj_set_value_column_var_size_scalar(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_obj *value, int flags) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_id range = DB_OBJ(obj)->range; + void *v = GRN_BULK_HEAD(value); + unsigned int s = grn_obj_size(ctx, value); + grn_obj buf; + grn_id buf_domain = GRN_DB_VOID; + + if (call_hook(ctx, obj, id, value, flags)) { + if (ctx->rc) { + rc = ctx->rc; + } + return rc; + } + + switch (flags & GRN_OBJ_SET_MASK) { + case GRN_OBJ_INCR : + case GRN_OBJ_DECR : + if (value->header.domain == GRN_DB_INT32 || + value->header.domain == GRN_DB_INT64) { + /* do nothing */ + } else if (GRN_DB_INT8 <= value->header.domain && + value->header.domain < GRN_DB_INT32) { + buf_domain = GRN_DB_INT32; + } else { + buf_domain = GRN_DB_INT64; + } + break; + default : + if (range != value->header.domain) { + buf_domain = range; + } + break; + } + + if (buf_domain != GRN_DB_VOID) { + GRN_OBJ_INIT(&buf, GRN_BULK, 0, buf_domain); + if (grn_obj_cast(ctx, value, &buf, GRN_TRUE) == GRN_SUCCESS) { + v = GRN_BULK_HEAD(&buf); + s = GRN_BULK_VSIZE(&buf); + } + } + + rc = grn_ja_put(ctx, (grn_ja *)obj, id, v, s, flags, NULL); + + if (buf_domain != GRN_DB_VOID) { + grn_obj_close(ctx, &buf); + } + + return rc; +} + +static grn_rc +grn_obj_set_value_column_var_size_vector_uvector(grn_ctx *ctx, grn_obj *column, + grn_id id, grn_obj *value, + int flags) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj uvector; + grn_obj_flags uvector_flags = 0; + grn_bool need_convert = GRN_FALSE; + grn_bool need_cast = GRN_FALSE; + grn_id column_range_id; + void *raw_value; + unsigned int size; + + if (column->header.flags & GRN_OBJ_WITH_WEIGHT) { + if (!IS_WEIGHT_UVECTOR(value)) { + need_convert = GRN_TRUE; + } + } else { + if (IS_WEIGHT_UVECTOR(value)) { + need_convert = GRN_TRUE; + uvector_flags = GRN_OBJ_WITH_WEIGHT; + } + } + column_range_id = DB_OBJ(column)->range; + if (column_range_id != value->header.domain) { + need_convert = GRN_TRUE; + need_cast = GRN_TRUE; + } + + if (need_convert) { + unsigned int i, n; + + GRN_VALUE_FIX_SIZE_INIT(&uvector, GRN_OBJ_VECTOR, column_range_id); + uvector.header.flags |= uvector_flags; + n = grn_uvector_size(ctx, value); + if (need_cast) { + grn_obj value_record; + grn_obj casted_record; + + GRN_VALUE_FIX_SIZE_INIT(&value_record, 0, value->header.domain); + GRN_VALUE_FIX_SIZE_INIT(&casted_record, 0, column_range_id); + for (i = 0; i < n; i++) { + grn_id id; + grn_id casted_id; + unsigned int weight = 0; + + GRN_BULK_REWIND(&value_record); + GRN_BULK_REWIND(&casted_record); + + id = grn_uvector_get_element(ctx, value, i, NULL); + GRN_RECORD_SET(ctx, &value_record, id); + rc = grn_obj_cast(ctx, &value_record, &casted_record, GRN_TRUE); + if (rc != GRN_SUCCESS) { + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + grn_obj inspected; + column_name_size = grn_obj_name(ctx, + column, + column_name, + GRN_TABLE_MAX_KEY_SIZE); + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, &value_record); + ERR(rc, + "[column][set-value] failed to cast: <%.*s>: <%.*s>", + column_name_size, + column_name, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + break; + } + casted_id = GRN_RECORD_VALUE(&casted_record); + grn_uvector_add_element(ctx, &uvector, casted_id, weight); + } + + GRN_OBJ_FIN(ctx, &value_record); + GRN_OBJ_FIN(ctx, &casted_record); + } else { + for (i = 0; i < n; i++) { + grn_id id; + unsigned int weight = 0; + id = grn_uvector_get_element(ctx, value, i, NULL); + grn_uvector_add_element(ctx, &uvector, id, weight); + } + } + raw_value = GRN_BULK_HEAD(&uvector); + size = GRN_BULK_VSIZE(&uvector); + } else { + raw_value = GRN_BULK_HEAD(value); + size = GRN_BULK_VSIZE(value); + } + + if (rc == GRN_SUCCESS) { + rc = grn_ja_put(ctx, (grn_ja *)column, id, raw_value, size, flags, NULL); + } + + if (need_convert) { + GRN_OBJ_FIN(ctx, &uvector); + } + + return rc; +} + +static grn_rc +grn_obj_set_value_column_var_size_vector(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_obj *value, int flags) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_id range = DB_OBJ(obj)->range; + void *v = GRN_BULK_HEAD(value); + unsigned int s = grn_obj_size(ctx, value); + grn_obj *lexicon = grn_ctx_at(ctx, range); + + if (call_hook(ctx, obj, id, value, flags)) { + if (ctx->rc) { + rc = ctx->rc; + } + return rc; + } + + if (value->header.type == GRN_UVECTOR) { + rc = grn_obj_set_value_column_var_size_vector_uvector(ctx, obj, + id, value, + flags); + return rc; + } + + if (GRN_OBJ_TABLEP(lexicon)) { + grn_obj uvector; + GRN_RECORD_INIT(&uvector, GRN_OBJ_VECTOR, range); + if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) { + uvector.header.flags |= GRN_OBJ_WITH_WEIGHT; + } + switch (value->header.type) { + case GRN_BULK : + { + unsigned int token_flags = 0; + grn_token_cursor *token_cursor; + if (v && s && + (token_cursor = grn_token_cursor_open(ctx, lexicon, v, s, + GRN_TOKEN_ADD, token_flags))) { + while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) { + grn_id tid = grn_token_cursor_next(ctx, token_cursor); + grn_uvector_add_element(ctx, &uvector, tid, 0); + } + grn_token_cursor_close(ctx, token_cursor); + } + rc = grn_ja_put(ctx, (grn_ja *)obj, id, + GRN_BULK_HEAD(&uvector), GRN_BULK_VSIZE(&uvector), + flags, NULL); + } + break; + case GRN_VECTOR : + { + unsigned int n; + n = grn_vector_size(ctx, value); + if (n > 0) { + unsigned int i; + grn_obj value_buf, cast_buf; + GRN_OBJ_INIT(&value_buf, GRN_BULK, 0, GRN_DB_VOID); + GRN_OBJ_INIT(&cast_buf, GRN_BULK, 0, lexicon->header.domain); + for (i = 0; i < n; i++) { + grn_id tid; + const char *element; + unsigned int element_length; + unsigned int weight; + grn_id element_domain; + + element_length = grn_vector_get_element(ctx, value, i, + &element, &weight, + &element_domain); + if (element_domain != lexicon->header.domain) { + GRN_BULK_REWIND(&cast_buf); + GRN_BULK_REWIND(&value_buf); + grn_bulk_write(ctx, &value_buf, element, element_length); + value_buf.header.domain = element_domain; + rc = grn_obj_cast(ctx, &value_buf, &cast_buf, GRN_TRUE); + if (rc) { + grn_obj *range_obj; + range_obj = grn_ctx_at(ctx, range); + ERR_CAST(obj, range_obj, &value_buf); + grn_obj_unlink(ctx, range_obj); + } else { + element = GRN_BULK_HEAD(&cast_buf); + element_length = GRN_BULK_VSIZE(&cast_buf); + } + } else { + rc = GRN_SUCCESS; + } + if (rc) { + continue; + } + tid = grn_table_add(ctx, lexicon, element, element_length, NULL); + grn_uvector_add_element(ctx, &uvector, tid, weight); + } + GRN_OBJ_FIN(ctx, &value_buf); + GRN_OBJ_FIN(ctx, &cast_buf); + } + } + rc = grn_ja_put(ctx, (grn_ja *)obj, id, + GRN_BULK_HEAD(&uvector), GRN_BULK_VSIZE(&uvector), + flags, NULL); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "vector, uvector or bulk required"); + break; + } + grn_obj_close(ctx, &uvector); + } else { + switch (value->header.type) { + case GRN_BULK : + if (!GRN_BULK_VSIZE(value)) { + rc = grn_ja_put(ctx, (grn_ja *)obj, id, NULL, 0, flags, NULL); + } else { + grn_obj v; + GRN_OBJ_INIT(&v, GRN_VECTOR, GRN_OBJ_DO_SHALLOW_COPY, GRN_DB_TEXT); + v.u.v.body = value; + grn_vector_delimit(ctx, &v, 0, GRN_ID_NIL); + rc = grn_ja_putv(ctx, (grn_ja *)obj, id, &v, 0); + grn_obj_close(ctx, &v); + } + break; + case GRN_VECTOR : + rc = grn_ja_putv(ctx, (grn_ja *)obj, id, value, 0); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "vector or bulk required"); + break; + } + } + return rc; +} + +static grn_rc +grn_obj_set_value_column_fix_size(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_obj *value, int flags) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_id range = DB_OBJ(obj)->range; + void *v = GRN_BULK_HEAD(value); + unsigned int s = grn_obj_size(ctx, value); + grn_obj buf, *value_ = value; + uint32_t element_size = ((grn_ra *)obj)->header->element_size; + GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); + if (range != value->header.domain) { + rc = grn_obj_cast(ctx, value, &buf, GRN_TRUE); + if (rc) { + grn_obj *range_obj; + range_obj = grn_ctx_at(ctx, range); + ERR_CAST(obj, range_obj, value); + grn_obj_unlink(ctx, range_obj); + } else { + value_ = &buf; + v = GRN_BULK_HEAD(&buf); + s = GRN_BULK_VSIZE(&buf); + } + } else { + rc = GRN_SUCCESS; + } + if (rc) { + /* do nothing because it already has error. */ + } else if (element_size < s) { + ERR(GRN_INVALID_ARGUMENT, "too long value (%d)", s); + } else { + void *p = grn_ra_ref(ctx, (grn_ra *)obj, id); + if (!p) { + ERR(GRN_NO_MEMORY_AVAILABLE, "ra get failed"); + rc = GRN_NO_MEMORY_AVAILABLE; + return rc; + } + switch (flags & GRN_OBJ_SET_MASK) { + case GRN_OBJ_SET : + if (call_hook(ctx, obj, id, value_, flags)) { + if (ctx->rc) { + rc = ctx->rc; + } + GRN_OBJ_FIN(ctx, &buf); + grn_ra_unref(ctx, (grn_ra *)obj, id); + return rc; + } + if (element_size != s) { + if (!s) { + memset(p, 0, element_size); + } else { + void *b; + if ((b = GRN_CALLOC(element_size))) { + grn_memcpy(b, v, s); + grn_memcpy(p, b, element_size); + GRN_FREE(b); + } + } + } else { + grn_memcpy(p, v, s); + } + rc = GRN_SUCCESS; + break; + case GRN_OBJ_INCR : + /* todo : support hook */ + INCRDECR(+=); + break; + case GRN_OBJ_DECR : + /* todo : support hook */ + INCRDECR(-=); + break; + default : + rc = GRN_OPERATION_NOT_SUPPORTED; + break; + } + grn_ra_unref(ctx, (grn_ra *)obj, id); + } + GRN_OBJ_FIN(ctx, &buf); + return rc; +} + +static grn_rc +grn_obj_set_value_column_index(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_obj *value, int flags) +{ + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + column_name_size = grn_obj_name(ctx, obj, column_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "can't set value to index column directly: <%.*s>", + column_name_size, column_name); + return ctx->rc; +} + +grn_rc +grn_obj_set_value(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_obj *value, int flags) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (!GRN_DB_OBJP(obj)) { + if (obj->header.type == GRN_ACCESSOR) { + rc = grn_accessor_set_value(ctx, (grn_accessor *)obj, id, value, flags); + } else { + ERR(GRN_INVALID_ARGUMENT, "not db_obj"); + } + } else { + switch (obj->header.type) { + case GRN_TABLE_PAT_KEY : + rc = grn_obj_set_value_table_pat_key(ctx, obj, id, value, flags); + break; + case GRN_TABLE_DAT_KEY : + rc = GRN_OPERATION_NOT_SUPPORTED; + break; + case GRN_TABLE_HASH_KEY : + rc = grn_obj_set_value_table_hash_key(ctx, obj, id, value, flags); + break; + case GRN_TABLE_NO_KEY : + rc = grn_obj_set_value_table_no_key(ctx, obj, id, value, flags); + break; + case GRN_COLUMN_VAR_SIZE : + switch (obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { + case GRN_OBJ_COLUMN_SCALAR : + rc = grn_obj_set_value_column_var_size_scalar(ctx, obj, id, value, + flags); + break; + case GRN_OBJ_COLUMN_VECTOR : + rc = grn_obj_set_value_column_var_size_vector(ctx, obj, id, value, + flags); + break; + default : + ERR(GRN_FILE_CORRUPT, "invalid GRN_OBJ_COLUMN_TYPE"); + break; + } + break; + case GRN_COLUMN_FIX_SIZE : + rc = grn_obj_set_value_column_fix_size(ctx, obj, id, value, flags); + break; + case GRN_COLUMN_INDEX : + rc = grn_obj_set_value_column_index(ctx, obj, id, value, flags); + break; + } + } + GRN_API_RETURN(rc); +} + +const char * +grn_obj_get_value_(grn_ctx *ctx, grn_obj *obj, grn_id id, uint32_t *size) +{ + const char *value = NULL; + *size = 0; + switch (obj->header.type) { + case GRN_ACCESSOR : + value = grn_accessor_get_value_(ctx, (grn_accessor *)obj, id, size); + break; + case GRN_TABLE_PAT_KEY : + value = grn_pat_get_value_(ctx, (grn_pat *)obj, id, size); + break; + case GRN_TABLE_DAT_KEY : + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "GRN_TABLE_DAT_KEY not supported"); + break; + case GRN_TABLE_HASH_KEY : + value = grn_hash_get_value_(ctx, (grn_hash *)obj, id, size); + break; + case GRN_TABLE_NO_KEY : + if ((value = _grn_array_get_value(ctx, (grn_array *)obj, id))) { + *size = ((grn_array *)obj)->value_size; + } + break; + case GRN_COLUMN_VAR_SIZE : + { + grn_io_win jw; + if ((value = grn_ja_ref(ctx, (grn_ja *)obj, id, &jw, size))) { + grn_ja_unref(ctx, &jw); + } + } + break; + case GRN_COLUMN_FIX_SIZE : + if ((value = grn_ra_ref(ctx, (grn_ra *)obj, id))) { + grn_ra_unref(ctx, (grn_ra *)obj, id); + *size = ((grn_ra *)obj)->header->element_size; + } + break; + case GRN_COLUMN_INDEX : + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "todo: GRN_COLUMN_INDEX"); + break; + } + return value; +} + +static void +grn_obj_get_value_expr(grn_ctx *ctx, grn_obj *expr, grn_id id, grn_obj *value) +{ + grn_expr *e = (grn_expr *)expr; + grn_expr_code *code; + + if (e->codes_curr != 1) { + return; + } + + code = e->codes; + if (code->op != GRN_OP_GET_VALUE) { + return; + } + + if (!code->value) { + return; + } + + switch (code->value->header.type) { + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_FIX_SIZE : + grn_obj_get_value(ctx, code->value, id, value); + break; + default : + break; + } +} + +static void +grn_obj_get_value_column_index(grn_ctx *ctx, grn_obj *index_column, + grn_id id, grn_obj *value) +{ + grn_ii *ii = (grn_ii *)index_column; + grn_obj_ensure_bulk(ctx, value); + if (id) { + GRN_UINT32_SET(ctx, value, grn_ii_estimate_size(ctx, ii, id)); + } else { + GRN_UINT32_SET(ctx, value, 0); + } + value->header.domain = GRN_DB_UINT32; +} + +static grn_obj * +grn_obj_get_value_column_vector(grn_ctx *ctx, grn_obj *obj, + grn_id id, grn_obj *value) +{ + grn_obj *lexicon; + + lexicon = grn_ctx_at(ctx, DB_OBJ(obj)->range); + if (lexicon && !GRN_OBJ_TABLEP(lexicon) && + (lexicon->header.flags & GRN_OBJ_KEY_VAR_SIZE)) { + grn_obj_ensure_vector(ctx, value); + if (id) { + grn_obj v_; + GRN_TEXT_INIT(&v_, 0); + grn_ja_get_value(ctx, (grn_ja *)obj, id, &v_); + grn_vector_decode(ctx, value, GRN_TEXT_VALUE(&v_), GRN_TEXT_LEN(&v_)); + GRN_OBJ_FIN(ctx, &v_); + } + } else { + grn_obj_ensure_bulk(ctx, value); + if (id) { + grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + } + value->header.type = GRN_UVECTOR; + if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) { + value->header.flags |= GRN_OBJ_WITH_WEIGHT; + } else { + value->header.flags &= ~GRN_OBJ_WITH_WEIGHT; + } + } + + return value; +} + +grn_obj * +grn_obj_get_value(grn_ctx *ctx, grn_obj *obj, grn_id id, grn_obj *value) +{ + GRN_API_ENTER; + if (!obj) { + ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed"); + goto exit; + } + if (!value) { + if (!(value = grn_obj_open(ctx, GRN_BULK, 0, 0))) { + ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed"); + goto exit; + } + } + switch (value->header.type) { + case GRN_VOID : + grn_obj_reinit(ctx, value, GRN_DB_TEXT, 0); + break; + case GRN_BULK : + case GRN_VECTOR : + case GRN_UVECTOR : + case GRN_MSG : + break; + default : + ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed"); + goto exit; + } + switch (obj->header.type) { + case GRN_ACCESSOR : + grn_obj_ensure_bulk(ctx, value); + value = grn_accessor_get_value(ctx, (grn_accessor *)obj, id, value); + break; + case GRN_EXPR : + grn_obj_get_value_expr(ctx, obj, id, value); + break; + case GRN_TABLE_PAT_KEY : + { + grn_pat *pat = (grn_pat *)obj; + uint32_t size = pat->value_size; + grn_obj_ensure_bulk(ctx, value); + if (id) { + if (grn_bulk_space(ctx, value, size)) { + MERR("grn_bulk_space failed"); + goto exit; + } + { + char *curr = GRN_BULK_CURR(value); + grn_pat_get_value(ctx, pat, id, curr - size); + } + } + value->header.type = GRN_BULK; + value->header.domain = grn_obj_get_range(ctx, obj); + } + break; + case GRN_TABLE_DAT_KEY : + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "GRN_TABLE_DAT_KEY not supported"); + break; + case GRN_TABLE_HASH_KEY : + { + grn_bool processed = GRN_FALSE; + grn_obj_ensure_bulk(ctx, value); + value->header.domain = grn_obj_get_range(ctx, obj); + if (id) { + if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(obj)) { + grn_obj *domain; + domain = grn_ctx_at(ctx, value->header.domain); + if (GRN_OBJ_TABLEP(domain)) { + grn_id subrec_id; + if (grn_table_get_subrecs(ctx, obj, id, &subrec_id, NULL, 1) == 1) { + GRN_RECORD_SET(ctx, value, subrec_id); + processed = GRN_TRUE; + } + } + } + if (!processed) { + grn_hash *hash = (grn_hash *)obj; + uint32_t size = hash->value_size; + if (grn_bulk_space(ctx, value, size)) { + MERR("grn_bulk_space failed"); + goto exit; + } + { + char *curr = GRN_BULK_CURR(value); + grn_hash_get_value(ctx, hash, id, curr - size); + } + } + } + } + break; + case GRN_TABLE_NO_KEY : + { + grn_array *array = (grn_array *)obj; + uint32_t size = array->value_size; + grn_obj_ensure_bulk(ctx, value); + if (id) { + if (grn_bulk_space(ctx, value, size)) { + MERR("grn_bulk_space failed"); + goto exit; + } + { + char *curr = GRN_BULK_CURR(value); + grn_array_get_value(ctx, array, id, curr - size); + } + } + value->header.type = GRN_BULK; + value->header.domain = grn_obj_get_range(ctx, obj); + } + break; + case GRN_COLUMN_VAR_SIZE : + switch (obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { + case GRN_OBJ_COLUMN_VECTOR : + grn_obj_get_value_column_vector(ctx, obj, id, value); + break; + case GRN_OBJ_COLUMN_SCALAR : + grn_obj_ensure_bulk(ctx, value); + if (id) { + grn_ja_get_value(ctx, (grn_ja *)obj, id, value); + } + value->header.type = GRN_BULK; + break; + default : + ERR(GRN_FILE_CORRUPT, "invalid GRN_OBJ_COLUMN_TYPE"); + break; + } + value->header.domain = grn_obj_get_range(ctx, obj); + break; + case GRN_COLUMN_FIX_SIZE : + grn_obj_ensure_bulk(ctx, value); + value->header.type = GRN_BULK; + value->header.domain = grn_obj_get_range(ctx, obj); + if (id) { + unsigned int element_size; + void *v = grn_ra_ref(ctx, (grn_ra *)obj, id); + if (v) { + element_size = ((grn_ra *)obj)->header->element_size; + grn_bulk_write(ctx, value, v, element_size); + grn_ra_unref(ctx, (grn_ra *)obj, id); + } + } + break; + case GRN_COLUMN_INDEX : + grn_obj_get_value_column_index(ctx, obj, id, value); + break; + } +exit : + GRN_API_RETURN(value); +} + +int +grn_obj_get_values(grn_ctx *ctx, grn_obj *obj, grn_id offset, void **values) +{ + int nrecords = -1; + GRN_API_ENTER; + if (obj->header.type == GRN_COLUMN_FIX_SIZE) { + grn_obj *domain = grn_column_table(ctx, obj); + if (domain) { + int table_size = (int)grn_table_size(ctx, domain); + if (0 < offset && offset <= (grn_id) table_size) { + grn_ra *ra = (grn_ra *)obj; + void *p = grn_ra_ref(ctx, ra, offset); + if (p) { + if ((offset >> ra->element_width) == ((unsigned int) table_size >> ra->element_width)) { + nrecords = (table_size & ra->element_mask) + 1 - (offset & ra->element_mask); + } else { + nrecords = ra->element_mask + 1 - (offset & ra->element_mask); + } + if (values) { *values = p; } + grn_ra_unref(ctx, ra, offset); + } else { + ERR(GRN_NO_MEMORY_AVAILABLE, "ra get failed"); + } + } else { + nrecords = 0; + } + } else { + ERR(GRN_INVALID_ARGUMENT, "no domain found"); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "obj is not a fix sized column"); + } + GRN_API_RETURN(nrecords); +} + +grn_rc +grn_column_index_update(grn_ctx *ctx, grn_obj *column, + grn_id id, unsigned int section, + grn_obj *oldvalue, grn_obj *newvalue) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (column->header.type != GRN_COLUMN_INDEX) { + ERR(GRN_INVALID_ARGUMENT, "invalid column assigned"); + } else { + rc = grn_ii_column_update(ctx, (grn_ii *)column, id, section, oldvalue, newvalue, NULL); + } + GRN_API_RETURN(rc); +} + +grn_obj * +grn_column_table(grn_ctx *ctx, grn_obj *column) +{ + grn_obj *obj = NULL; + grn_db_obj *col = DB_OBJ(column); + GRN_API_ENTER; + if (col) { + obj = grn_ctx_at(ctx, col->header.domain); + } + GRN_API_RETURN(obj); +} + +grn_obj * +grn_obj_get_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *valuebuf) +{ + GRN_API_ENTER; + switch (type) { + case GRN_INFO_SUPPORT_ZLIB : + if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) { + ERR(GRN_INVALID_ARGUMENT, + "failed to open value buffer for GRN_INFO_ZLIB_SUPPORT"); + goto exit; + } +#ifdef GRN_WITH_ZLIB + GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE); +#else + GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); +#endif + break; + case GRN_INFO_SUPPORT_LZ4 : + if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) { + ERR(GRN_INVALID_ARGUMENT, + "failed to open value buffer for GRN_INFO_LZ4_SUPPORT"); + goto exit; + } +#ifdef GRN_WITH_LZ4 + GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE); +#else /* GRN_WITH_LZ4 */ + GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); +#endif /* GRN_WITH_LZ4 */ + break; + case GRN_INFO_SUPPORT_ZSTD : + if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) { + ERR(GRN_INVALID_ARGUMENT, + "failed to open value buffer for GRN_INFO_ZSTD_SUPPORT"); + goto exit; + } +#ifdef GRN_WITH_ZSTD + GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE); +#else /* GRN_WITH_ZSTD */ + GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); +#endif /* GRN_WITH_ZSTD */ + break; + case GRN_INFO_SUPPORT_ARROW : + if (!valuebuf && !(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_BOOL))) { + ERR(GRN_INVALID_ARGUMENT, + "failed to open value buffer for GRN_INFO_ARROW_SUPPORT"); + goto exit; + } +#ifdef GRN_WITH_ARROW + GRN_BOOL_PUT(ctx, valuebuf, GRN_TRUE); +#else /* GRN_WITH_ARROW */ + GRN_BOOL_PUT(ctx, valuebuf, GRN_FALSE); +#endif /* GRN_WITH_ARROW */ + break; + default : + if (!obj) { + ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_info failed"); + goto exit; + } + switch (type) { + case GRN_INFO_ENCODING : + if (!valuebuf) { + if (!(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, 0))) { + ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_info failed"); + goto exit; + } + } + { + grn_encoding enc; + if (obj->header.type == GRN_DB) { obj = ((grn_db *)obj)->keys; } + switch (obj->header.type) { + case GRN_TABLE_PAT_KEY : + enc = ((grn_pat *)obj)->encoding; + grn_bulk_write(ctx, valuebuf, (const char *)&enc, sizeof(grn_encoding)); + break; + case GRN_TABLE_DAT_KEY : + enc = ((grn_dat *)obj)->encoding; + grn_bulk_write(ctx, valuebuf, (const char *)&enc, sizeof(grn_encoding)); + break; + case GRN_TABLE_HASH_KEY : + enc = ((grn_hash *)obj)->encoding; + grn_bulk_write(ctx, valuebuf, (const char *)&enc, sizeof(grn_encoding)); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_info failed"); + } + } + break; + case GRN_INFO_SOURCE : + if (!valuebuf) { + if (!(valuebuf = grn_obj_open(ctx, GRN_BULK, 0, 0))) { + ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_info failed"); + goto exit; + } + } + if (!GRN_DB_OBJP(obj)) { + ERR(GRN_INVALID_ARGUMENT, "only db_obj can accept GRN_INFO_SOURCE"); + goto exit; + } + grn_bulk_write(ctx, valuebuf, DB_OBJ(obj)->source, DB_OBJ(obj)->source_size); + break; + case GRN_INFO_DEFAULT_TOKENIZER : + switch (DB_OBJ(obj)->header.type) { + case GRN_TABLE_HASH_KEY : + valuebuf = ((grn_hash *)obj)->tokenizer; + break; + case GRN_TABLE_PAT_KEY : + valuebuf = ((grn_pat *)obj)->tokenizer; + break; + case GRN_TABLE_DAT_KEY : + valuebuf = ((grn_dat *)obj)->tokenizer; + break; + } + break; + case GRN_INFO_NORMALIZER : + switch (DB_OBJ(obj)->header.type) { + case GRN_TABLE_HASH_KEY : + valuebuf = ((grn_hash *)obj)->normalizer; + break; + case GRN_TABLE_PAT_KEY : + valuebuf = ((grn_pat *)obj)->normalizer; + break; + case GRN_TABLE_DAT_KEY : + valuebuf = ((grn_dat *)obj)->normalizer; + break; + } + break; + case GRN_INFO_TOKEN_FILTERS : + if (!valuebuf) { + if (!(valuebuf = grn_obj_open(ctx, GRN_PVECTOR, 0, 0))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "grn_obj_get_info: failed to allocate value buffer"); + goto exit; + } + } + { + grn_obj *token_filters = NULL; + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY : + token_filters = &(((grn_hash *)obj)->token_filters); + break; + case GRN_TABLE_PAT_KEY : + token_filters = &(((grn_pat *)obj)->token_filters); + break; + case GRN_TABLE_DAT_KEY : + token_filters = &(((grn_dat *)obj)->token_filters); + break; + default : + ERR(GRN_INVALID_ARGUMENT, + /* TODO: Show type name instead of type ID */ + "[info][get][token-filters] target object must be one of " + "GRN_TABLE_HASH_KEY, GRN_TABLE_PAT_KEY and GRN_TABLE_DAT_KEY: %d", + obj->header.type); + break; + } + if (token_filters) { + grn_bulk_write(ctx, + valuebuf, + GRN_BULK_HEAD(token_filters), + GRN_BULK_VSIZE(token_filters)); + } + } + break; + default : + /* todo */ + break; + } + } +exit : + GRN_API_RETURN(valuebuf); +} + +static void +update_source_hook(grn_ctx *ctx, grn_obj *obj) +{ + grn_id *s = DB_OBJ(obj)->source; + int i, n = DB_OBJ(obj)->source_size / sizeof(grn_id); + grn_obj_default_set_value_hook_data hook_data = { DB_OBJ(obj)->id, 0 }; + grn_obj *source, data; + GRN_TEXT_INIT(&data, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET_REF(&data, &hook_data, sizeof(hook_data)); + for (i = 1; i <= n; i++, s++) { + hook_data.section = i; + if ((source = grn_ctx_at(ctx, *s))) { + switch (source->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + grn_obj_add_hook(ctx, source, GRN_HOOK_INSERT, 0, NULL, &data); + grn_obj_add_hook(ctx, source, GRN_HOOK_DELETE, 0, NULL, &data); + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + grn_obj_add_hook(ctx, source, GRN_HOOK_SET, 0, NULL, &data); + break; + default : + /* invalid target */ + break; + } + } + } + grn_obj_close(ctx, &data); +} + +static void +del_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, grn_obj *hld) +{ + int i; + void *hld_value = NULL; + uint32_t hld_size = 0; + grn_hook **last; + hld_value = GRN_BULK_HEAD(hld); + hld_size = GRN_BULK_VSIZE(hld); + if (!hld_size) { return; } + for (i = 0, last = &DB_OBJ(obj)->hooks[entry]; *last; i++, last = &(*last)->next) { + if (!memcmp(GRN_NEXT_ADDR(*last), hld_value, hld_size)) { + grn_obj_delete_hook(ctx, obj, entry, i); + return; + } + } +} + +static void +delete_source_hook(grn_ctx *ctx, grn_obj *obj) +{ + grn_id *s = DB_OBJ(obj)->source; + int i, n = DB_OBJ(obj)->source_size / sizeof(grn_id); + grn_obj_default_set_value_hook_data hook_data = { DB_OBJ(obj)->id, 0 }; + grn_obj *source, data; + GRN_TEXT_INIT(&data, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET_REF(&data, &hook_data, sizeof(hook_data)); + for (i = 1; i <= n; i++, s++) { + hook_data.section = i; + + source = grn_ctx_at(ctx, *s); + if (!source) { + ERRCLR(ctx); + continue; + } + + switch (source->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + del_hook(ctx, source, GRN_HOOK_INSERT, &data); + del_hook(ctx, source, GRN_HOOK_DELETE, &data); + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + del_hook(ctx, source, GRN_HOOK_SET, &data); + break; + default : + /* invalid target */ + break; + } + } + grn_obj_close(ctx, &data); +} + +#define N_HOOK_ENTRIES 5 + +grn_rc +grn_hook_pack(grn_ctx *ctx, grn_db_obj *obj, grn_obj *buf) +{ + grn_rc rc; + grn_hook_entry e; + for (e = 0; e < N_HOOK_ENTRIES; e++) { + grn_hook *hooks; + for (hooks = obj->hooks[e]; hooks; hooks = hooks->next) { + grn_id id = hooks->proc ? hooks->proc->obj.id : 0; + if ((rc = grn_text_benc(ctx, buf, id + 1))) { goto exit; } + if ((rc = grn_text_benc(ctx, buf, hooks->hld_size))) { goto exit; } + if ((rc = grn_bulk_write(ctx, buf, (char *)GRN_NEXT_ADDR(hooks), hooks->hld_size))) { goto exit; } + } + if ((rc = grn_text_benc(ctx, buf, 0))) { goto exit; } + } +exit : + return rc; +} + +static grn_rc +grn_hook_unpack(grn_ctx *ctx, grn_db_obj *obj, const char *buf, uint32_t buf_size) +{ + grn_hook_entry e; + const uint8_t *p = (uint8_t *)buf, *pe = p + buf_size; + for (e = 0; e < N_HOOK_ENTRIES; e++) { + grn_hook *new, **last = &obj->hooks[e]; + for (;;) { + grn_id id; + uint32_t hld_size; + GRN_B_DEC(id, p); + if (!id--) { break; } + if (p >= pe) { return GRN_FILE_CORRUPT; } + GRN_B_DEC(hld_size, p); + if (p >= pe) { return GRN_FILE_CORRUPT; } + if (!(new = GRN_MALLOC(sizeof(grn_hook) + hld_size))) { + return GRN_NO_MEMORY_AVAILABLE; + } + if (id) { + new->proc = (grn_proc *)grn_ctx_at(ctx, id); + if (!new->proc) { + GRN_FREE(new); + return ctx->rc; + } + } else { + new->proc = NULL; + } + if ((new->hld_size = hld_size)) { + grn_memcpy(GRN_NEXT_ADDR(new), p, hld_size); + p += hld_size; + } + *last = new; + last = &new->next; + if (p >= pe) { return GRN_FILE_CORRUPT; } + } + *last = NULL; + } + return GRN_SUCCESS; +} + +static void +grn_token_filters_pack(grn_ctx *ctx, + grn_obj *token_filters, + grn_obj *buffer) +{ + unsigned int i, n_token_filters; + + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + for (i = 0; i < n_token_filters; i++) { + grn_obj *token_filter = GRN_PTR_VALUE_AT(token_filters, i); + grn_id token_filter_id; + + token_filter_id = grn_obj_id(ctx, token_filter); + GRN_RECORD_PUT(ctx, buffer, token_filter_id); + } +} + +static grn_bool +grn_obj_encoded_spec_equal(grn_ctx *ctx, + grn_obj *encoded_spec1, + grn_obj *encoded_spec2) +{ + unsigned int i, n_elements; + + if (encoded_spec1->header.type != GRN_VECTOR) { + return GRN_FALSE; + } + + if (encoded_spec1->header.type != encoded_spec2->header.type) { + return GRN_FALSE; + } + + n_elements = grn_vector_size(ctx, encoded_spec1); + if (grn_vector_size(ctx, encoded_spec2) != n_elements) { + return GRN_FALSE; + } + + for (i = 0; i < n_elements; i++) { + const char *content1; + const char *content2; + unsigned int content_size1; + unsigned int content_size2; + unsigned int weight1; + unsigned int weight2; + grn_id domain1; + grn_id domain2; + + content_size1 = grn_vector_get_element(ctx, + encoded_spec1, + i, + &content1, + &weight1, + &domain1); + content_size2 = grn_vector_get_element(ctx, + encoded_spec2, + i, + &content2, + &weight2, + &domain2); + if (content_size1 != content_size2) { + return GRN_FALSE; + } + if (memcmp(content1, content2, content_size1) != 0) { + return GRN_FALSE; + } + if (weight1 != weight2) { + return GRN_FALSE; + } + if (domain1 != domain2) { + return GRN_FALSE; + } + } + + return GRN_TRUE; +} + +void +grn_obj_spec_save(grn_ctx *ctx, grn_db_obj *obj) +{ + grn_db *s; + grn_obj v, *b; + grn_obj_spec spec; + grn_bool need_update = GRN_TRUE; + + if (obj->id & GRN_OBJ_TMP_OBJECT) { return; } + if (!ctx->impl || !GRN_DB_OBJP(obj)) { return; } + if (!(s = (grn_db *)ctx->impl->db) || !s->specs) { return; } + if (obj->header.type == GRN_PROC && obj->range == GRN_ID_NIL) { + return; + } + GRN_OBJ_INIT(&v, GRN_VECTOR, 0, GRN_DB_TEXT); + if (!(b = grn_vector_body(ctx, &v))) { return; } + spec.header = obj->header; + spec.range = obj->range; + grn_bulk_write(ctx, b, (void *)&spec, sizeof(grn_obj_spec)); + grn_vector_delimit(ctx, &v, 0, 0); + if (obj->header.flags & GRN_OBJ_CUSTOM_NAME) { + GRN_TEXT_PUTS(ctx, b, grn_obj_path(ctx, (grn_obj *)obj)); + } + grn_vector_delimit(ctx, &v, 0, 0); + grn_bulk_write(ctx, b, obj->source, obj->source_size); + grn_vector_delimit(ctx, &v, 0, 0); + grn_hook_pack(ctx, obj, b); + grn_vector_delimit(ctx, &v, 0, 0); + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY : + grn_token_filters_pack(ctx, &(((grn_hash *)obj)->token_filters), b); + grn_vector_delimit(ctx, &v, 0, 0); + break; + case GRN_TABLE_PAT_KEY : + grn_token_filters_pack(ctx, &(((grn_pat *)obj)->token_filters), b); + grn_vector_delimit(ctx, &v, 0, 0); + break; + case GRN_TABLE_DAT_KEY : + grn_token_filters_pack(ctx, &(((grn_dat *)obj)->token_filters), b); + grn_vector_delimit(ctx, &v, 0, 0); + break; + case GRN_EXPR : + grn_expr_pack(ctx, b, (grn_obj *)obj); + grn_vector_delimit(ctx, &v, 0, 0); + break; + } + + { + grn_io_win jw; + uint32_t current_spec_raw_len; + char *current_spec_raw; + + current_spec_raw = grn_ja_ref(ctx, + s->specs, + obj->id, + &jw, + ¤t_spec_raw_len); + if (current_spec_raw) { + grn_rc rc; + grn_obj current_spec; + + GRN_OBJ_INIT(¤t_spec, GRN_VECTOR, 0, GRN_DB_TEXT); + rc = grn_vector_decode(ctx, + ¤t_spec, + current_spec_raw, + current_spec_raw_len); + if (rc == GRN_SUCCESS) { + need_update = !grn_obj_encoded_spec_equal(ctx, &v, ¤t_spec); + } + GRN_OBJ_FIN(ctx, ¤t_spec); + grn_ja_unref(ctx, &jw); + } + } + + if (!need_update) { + grn_obj_close(ctx, &v); + return; + } + + { + const char *name; + uint32_t name_size = 0; + const char *range_name = NULL; + uint32_t range_name_size = 0; + + name = _grn_table_key(ctx, s->keys, obj->id, &name_size); + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + if (obj->range != GRN_ID_NIL) { + range_name = _grn_table_key(ctx, s->keys, obj->range, &range_name_size); + } + break; + default : + break; + } + /* TODO: reduce log level. */ + GRN_LOG(ctx, GRN_LOG_NOTICE, + "spec:%u:update:%.*s:%u(%s):%u%s%.*s%s", + obj->id, + name_size, name, + obj->header.type, + grn_obj_type_to_string(obj->header.type), + obj->range, + range_name_size == 0 ? "" : "(", + range_name_size, range_name, + range_name_size == 0 ? "" : ")"); + } + grn_ja_putv(ctx, s->specs, obj->id, &v, 0); + grn_obj_close(ctx, &v); +} + +inline static void +grn_obj_set_info_source_invalid_lexicon_error(grn_ctx *ctx, + const char *message, + grn_obj *actual_type, + grn_obj *expected_type, + grn_obj *index_column, + grn_obj *source) +{ + char actual_type_name[GRN_TABLE_MAX_KEY_SIZE]; + int actual_type_name_size; + char expected_type_name[GRN_TABLE_MAX_KEY_SIZE]; + int expected_type_name_size; + char index_column_name[GRN_TABLE_MAX_KEY_SIZE]; + int index_column_name_size; + char source_name[GRN_TABLE_MAX_KEY_SIZE]; + int source_name_size; + + actual_type_name_size = grn_obj_name(ctx, actual_type, + actual_type_name, + GRN_TABLE_MAX_KEY_SIZE); + expected_type_name_size = grn_obj_name(ctx, expected_type, + expected_type_name, + GRN_TABLE_MAX_KEY_SIZE); + index_column_name_size = grn_obj_name(ctx, index_column, + index_column_name, + GRN_TABLE_MAX_KEY_SIZE); + + source_name_size = grn_obj_name(ctx, source, + source_name, GRN_TABLE_MAX_KEY_SIZE); + if (grn_obj_is_table(ctx, source)) { + source_name[source_name_size] = '\0'; + grn_strncat(source_name, + GRN_TABLE_MAX_KEY_SIZE, + "._key", + GRN_TABLE_MAX_KEY_SIZE - source_name_size - 1); + source_name_size = strlen(source_name); + } + + ERR(GRN_INVALID_ARGUMENT, + "[column][index][source] %s: " + "<%.*s> -> <%.*s>: " + "index-column:<%.*s> " + "source:<%.*s>", + message, + actual_type_name_size, actual_type_name, + expected_type_name_size, expected_type_name, + index_column_name_size, index_column_name, + source_name_size, source_name); +} + +inline static grn_rc +grn_obj_set_info_source_validate(grn_ctx *ctx, grn_obj *obj, grn_obj *value) +{ + grn_id lexicon_id; + grn_obj *lexicon = NULL; + grn_id lexicon_domain_id; + grn_obj *lexicon_domain = NULL; + grn_bool lexicon_domain_is_table; + grn_bool lexicon_have_tokenizer; + grn_id *source_ids; + int i, n_source_ids; + + lexicon_id = obj->header.domain; + lexicon = grn_ctx_at(ctx, lexicon_id); + if (!lexicon) { + goto exit; + } + + lexicon_domain_id = lexicon->header.domain; + lexicon_domain = grn_ctx_at(ctx, lexicon_domain_id); + if (!lexicon_domain) { + goto exit; + } + + source_ids = (grn_id *)GRN_BULK_HEAD(value); + n_source_ids = GRN_BULK_VSIZE(value) / sizeof(grn_id); + if (n_source_ids > 1 && !(obj->header.flags & GRN_OBJ_WITH_SECTION)) { + char index_name[GRN_TABLE_MAX_KEY_SIZE]; + int index_name_size; + index_name_size = grn_obj_name(ctx, obj, + index_name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "grn_obj_set_info(): GRN_INFO_SOURCE: " + "multi column index must be created with WITH_SECTION flag: <%.*s>", + index_name_size, index_name); + goto exit; + } + + lexicon_domain_is_table = grn_obj_is_table(ctx, lexicon_domain); + { + grn_obj *tokenizer; + grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL); + lexicon_have_tokenizer = (tokenizer != NULL); + } + + for (i = 0; i < n_source_ids; i++) { + grn_id source_id = source_ids[i]; + grn_obj *source; + grn_id source_type_id; + grn_obj *source_type; + + source = grn_ctx_at(ctx, source_id); + if (!source) { + continue; + } + if (grn_obj_is_table(ctx, source)) { + source_type_id = source->header.domain; + } else { + source_type_id = DB_OBJ(source)->range; + } + source_type = grn_ctx_at(ctx, source_type_id); + if (!lexicon_have_tokenizer) { + if (grn_obj_is_table(ctx, source_type)) { + if (lexicon_id != source_type_id) { + grn_obj_set_info_source_invalid_lexicon_error( + ctx, + "index table must equal to source type", + lexicon, + source_type, + obj, + source); + } + } else { + if (!(lexicon_domain_id == source_type_id || + (grn_type_id_is_text_family(ctx, lexicon_domain_id) && + grn_type_id_is_text_family(ctx, source_type_id)))) { + grn_obj_set_info_source_invalid_lexicon_error( + ctx, + "index table's key must equal source type", + lexicon_domain, + source_type, + obj, + source); + } + } + } + grn_obj_unlink(ctx, source); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + } + +exit: + if (lexicon) { + grn_obj_unlink(ctx, lexicon); + } + if (lexicon_domain) { + grn_obj_unlink(ctx, lexicon_domain); + } + return ctx->rc; +} + +inline static void +grn_obj_set_info_source_log(grn_ctx *ctx, grn_obj *obj, grn_obj *value) +{ + grn_obj buf; + grn_id *vp = (grn_id *)GRN_BULK_HEAD(value); + uint32_t vs = GRN_BULK_VSIZE(value), s = 0; + grn_id id; + const char *n; + + id = DB_OBJ(obj)->id; + n = _grn_table_key(ctx, ctx->impl->db, id, &s); + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_PUT(ctx, &buf, n, s); + GRN_TEXT_PUTC(ctx, &buf, ' '); + while (vs) { + n = _grn_table_key(ctx, ctx->impl->db, *vp++, &s); + GRN_TEXT_PUT(ctx, &buf, n, s); + vs -= sizeof(grn_id); + if (vs) { GRN_TEXT_PUTC(ctx, &buf, ','); } + } + GRN_LOG(ctx, GRN_LOG_NOTICE, + "DDL:%u:set_source %.*s", + id, + (int)GRN_BULK_VSIZE(&buf), GRN_BULK_HEAD(&buf)); + GRN_OBJ_FIN(ctx, &buf); +} + +inline static grn_rc +grn_obj_set_info_source_update(grn_ctx *ctx, grn_obj *obj, grn_obj *value) +{ + void *v = GRN_BULK_HEAD(value); + uint32_t s = GRN_BULK_VSIZE(value); + if (s) { + void *v2 = GRN_MALLOC(s); + if (!v2) { + return ctx->rc; + } + grn_memcpy(v2, v, s); + if (DB_OBJ(obj)->source) { GRN_FREE(DB_OBJ(obj)->source); } + DB_OBJ(obj)->source = v2; + DB_OBJ(obj)->source_size = s; + + if (obj->header.type == GRN_COLUMN_INDEX) { + update_source_hook(ctx, obj); + grn_index_column_build(ctx, obj); + } + } else { + DB_OBJ(obj)->source = NULL; + DB_OBJ(obj)->source_size = 0; + } + + return GRN_SUCCESS; +} + +inline static grn_rc +grn_obj_set_info_source(grn_ctx *ctx, grn_obj *obj, grn_obj *value) +{ + grn_rc rc; + + rc = grn_obj_set_info_source_validate(ctx, obj, value); + if (rc != GRN_SUCCESS) { + return rc; + } + grn_obj_set_info_source_log(ctx, obj, value); + rc = grn_obj_set_info_source_update(ctx, obj, value); + if (rc != GRN_SUCCESS) { + return rc; + } + grn_obj_spec_save(ctx, DB_OBJ(obj)); + + return rc; +} + +static grn_rc +grn_obj_set_info_token_filters(grn_ctx *ctx, + grn_obj *table, + grn_obj *token_filters) +{ + grn_obj *current_token_filters; + unsigned int i, n_current_token_filters, n_token_filters; + grn_obj token_filter_names; + + switch (table->header.type) { + case GRN_TABLE_HASH_KEY : + current_token_filters = &(((grn_hash *)table)->token_filters); + break; + case GRN_TABLE_PAT_KEY : + current_token_filters = &(((grn_pat *)table)->token_filters); + break; + case GRN_TABLE_DAT_KEY : + current_token_filters = &(((grn_dat *)table)->token_filters); + break; + default : + /* TODO: Show type name instead of type ID */ + ERR(GRN_INVALID_ARGUMENT, + "[info][set][token-filters] target object must be one of " + "GRN_TABLE_HASH_KEY, GRN_TABLE_PAT_KEY and GRN_TABLE_DAT_KEY: %d", + table->header.type); + return ctx->rc; + } + + n_current_token_filters = + GRN_BULK_VSIZE(current_token_filters) / sizeof(grn_obj *); + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + + GRN_TEXT_INIT(&token_filter_names, 0); + GRN_BULK_REWIND(current_token_filters); + for (i = 0; i < n_token_filters; i++) { + grn_obj *token_filter = GRN_PTR_VALUE_AT(token_filters, i); + char token_filter_name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int token_filter_name_size; + + GRN_PTR_PUT(ctx, current_token_filters, token_filter); + + if (i > 0) { + GRN_TEXT_PUTC(ctx, &token_filter_names, ','); + } + token_filter_name_size = grn_obj_name(ctx, + token_filter, + token_filter_name, + GRN_TABLE_MAX_KEY_SIZE); + GRN_TEXT_PUT(ctx, + &token_filter_names, + token_filter_name, + token_filter_name_size); + } + if (n_token_filters > 0 || n_token_filters != n_current_token_filters) { + GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:%u:set_token_filters %.*s", + DB_OBJ(table)->id, + (int)GRN_BULK_VSIZE(&token_filter_names), + GRN_BULK_HEAD(&token_filter_names)); + } + GRN_OBJ_FIN(ctx, &token_filter_names); + grn_obj_spec_save(ctx, DB_OBJ(table)); + + return GRN_SUCCESS; +} + +grn_rc +grn_obj_set_info(grn_ctx *ctx, grn_obj *obj, grn_info_type type, grn_obj *value) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (!obj) { + ERR(GRN_INVALID_ARGUMENT, "grn_obj_set_info failed"); + goto exit; + } + switch (type) { + case GRN_INFO_SOURCE : + if (!GRN_DB_OBJP(obj)) { + ERR(GRN_INVALID_ARGUMENT, "only db_obj can accept GRN_INFO_SOURCE"); + goto exit; + } + rc = grn_obj_set_info_source(ctx, obj, value); + break; + case GRN_INFO_DEFAULT_TOKENIZER : + if (!value || DB_OBJ(value)->header.type == GRN_PROC) { + switch (DB_OBJ(obj)->header.type) { + case GRN_TABLE_HASH_KEY : + ((grn_hash *)obj)->tokenizer = value; + ((grn_hash *)obj)->header.common->tokenizer = grn_obj_id(ctx, value); + rc = GRN_SUCCESS; + break; + case GRN_TABLE_PAT_KEY : + ((grn_pat *)obj)->tokenizer = value; + ((grn_pat *)obj)->header->tokenizer = grn_obj_id(ctx, value); + rc = GRN_SUCCESS; + break; + case GRN_TABLE_DAT_KEY : + ((grn_dat *)obj)->tokenizer = value; + ((grn_dat *)obj)->header->tokenizer = grn_obj_id(ctx, value); + rc = GRN_SUCCESS; + break; + } + } + break; + case GRN_INFO_NORMALIZER : + if (!value || DB_OBJ(value)->header.type == GRN_PROC) { + switch (DB_OBJ(obj)->header.type) { + case GRN_TABLE_HASH_KEY : + ((grn_hash *)obj)->normalizer = value; + ((grn_hash *)obj)->header.common->normalizer = grn_obj_id(ctx, value); + rc = GRN_SUCCESS; + break; + case GRN_TABLE_PAT_KEY : + ((grn_pat *)obj)->normalizer = value; + ((grn_pat *)obj)->header->normalizer = grn_obj_id(ctx, value); + rc = GRN_SUCCESS; + break; + case GRN_TABLE_DAT_KEY : + ((grn_dat *)obj)->normalizer = value; + ((grn_dat *)obj)->header->normalizer = grn_obj_id(ctx, value); + rc = GRN_SUCCESS; + break; + } + } + break; + case GRN_INFO_TOKEN_FILTERS : + rc = grn_obj_set_info_token_filters(ctx, obj, value); + break; + default : + /* todo */ + break; + } +exit : + GRN_API_RETURN(rc); +} + +grn_obj * +grn_obj_get_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_info_type type, grn_obj *valuebuf) +{ + GRN_API_ENTER; + GRN_API_RETURN(valuebuf); +} + +grn_rc +grn_obj_set_element_info(grn_ctx *ctx, grn_obj *obj, grn_id id, + grn_info_type type, grn_obj *value) +{ + GRN_API_ENTER; + GRN_API_RETURN(GRN_SUCCESS); +} + +static void +grn_hook_free(grn_ctx *ctx, grn_hook *h) +{ + grn_hook *curr, *next; + for (curr = h; curr; curr = next) { + next = curr->next; + GRN_FREE(curr); + } +} + +grn_rc +grn_obj_add_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, + int offset, grn_obj *proc, grn_obj *hld) +{ + grn_rc rc = GRN_SUCCESS; + GRN_API_ENTER; + if (!GRN_DB_OBJP(obj)) { + rc = GRN_INVALID_ARGUMENT; + } else { + int i; + void *hld_value = NULL; + uint32_t hld_size = 0; + grn_hook *new, **last = &DB_OBJ(obj)->hooks[entry]; + if (hld) { + hld_value = GRN_BULK_HEAD(hld); + hld_size = GRN_BULK_VSIZE(hld); + } + if (!(new = GRN_MALLOC(sizeof(grn_hook) + hld_size))) { + rc = GRN_NO_MEMORY_AVAILABLE; + goto exit; + } + new->proc = (grn_proc *)proc; + new->hld_size = hld_size; + if (hld_size) { + grn_memcpy(GRN_NEXT_ADDR(new), hld_value, hld_size); + } + for (i = 0; i != offset && *last; i++) { last = &(*last)->next; } + new->next = *last; + *last = new; + grn_obj_spec_save(ctx, DB_OBJ(obj)); + } +exit : + GRN_API_RETURN(rc); +} + +int +grn_obj_get_nhooks(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry) +{ + int res = 0; + GRN_API_ENTER; + { + grn_hook *hook = DB_OBJ(obj)->hooks[entry]; + while (hook) { + res++; + hook = hook->next; + } + } + GRN_API_RETURN(res); +} + +grn_obj * +grn_obj_get_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, + int offset, grn_obj *hldbuf) +{ + grn_obj *res = NULL; + GRN_API_ENTER; + { + int i; + grn_hook *hook = DB_OBJ(obj)->hooks[entry]; + for (i = 0; i < offset; i++) { + hook = hook->next; + if (!hook) { return NULL; } + } + res = (grn_obj *)hook->proc; + grn_bulk_write(ctx, hldbuf, (char *)GRN_NEXT_ADDR(hook), hook->hld_size); + } + GRN_API_RETURN(res); +} + +grn_rc +grn_obj_delete_hook(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry, int offset) +{ + GRN_API_ENTER; + { + int i = 0; + grn_hook *h, **last = &DB_OBJ(obj)->hooks[entry]; + for (;;) { + if (!(h = *last)) { return GRN_INVALID_ARGUMENT; } + if (++i > offset) { break; } + last = &h->next; + } + *last = h->next; + GRN_FREE(h); + } + grn_obj_spec_save(ctx, DB_OBJ(obj)); + GRN_API_RETURN(GRN_SUCCESS); +} + +static grn_rc +remove_index(grn_ctx *ctx, grn_obj *obj, grn_hook_entry entry) +{ + grn_rc rc = GRN_SUCCESS; + grn_hook *h0, *hooks = DB_OBJ(obj)->hooks[entry]; + DB_OBJ(obj)->hooks[entry] = NULL; /* avoid mutual recursive call */ + while (hooks) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + if (!target) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int length; + char hook_name[GRN_TABLE_MAX_KEY_SIZE]; + int hook_name_length; + + length = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE); + hook_name_length = grn_table_get_key(ctx, + ctx->impl->db, + data->target, + hook_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_OBJECT_CORRUPT, + "[column][remove][index] " + "hook has a dangling reference: <%.*s> -> <%.*s>", + length, name, + hook_name_length, hook_name); + rc = ctx->rc; + } else if (target->header.type == GRN_COLUMN_INDEX) { + //TODO: multicolumn MULTI_COLUMN_INDEXP + rc = _grn_obj_remove(ctx, target, GRN_FALSE); + } else { + //TODO: err + char fn[GRN_TABLE_MAX_KEY_SIZE]; + int flen; + flen = grn_obj_name(ctx, target, fn, GRN_TABLE_MAX_KEY_SIZE); + fn[flen] = '\0'; + ERR(GRN_UNKNOWN_ERROR, "column has unsupported hooks, col=%s",fn); + rc = ctx->rc; + } + if (rc != GRN_SUCCESS) { + DB_OBJ(obj)->hooks[entry] = hooks; + break; + } + h0 = hooks; + hooks = hooks->next; + GRN_FREE(h0); + } + return rc; +} + +static grn_rc +remove_columns(grn_ctx *ctx, grn_obj *obj) +{ + grn_rc rc = GRN_SUCCESS; + grn_hash *cols; + if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { + if (grn_table_columns(ctx, obj, "", 0, (grn_obj *)cols)) { + GRN_HASH_EACH_BEGIN(ctx, cols, cursor, id) { + grn_id *key; + grn_obj *col; + + grn_hash_cursor_get_key(ctx, cursor, (void **)&key); + col = grn_ctx_at(ctx, *key); + + if (!col) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_table_get_key(ctx, ctx->impl->db, *key, + name, GRN_TABLE_MAX_KEY_SIZE); + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_INVALID_ARGUMENT, + "[object][remove] column is broken: <%.*s>", + name_size, name); + } else { + ERR(ctx->rc, + "[object][remove] column is broken: <%.*s>: %s", + name_size, name, + ctx->errbuf); + } + rc = ctx->rc; + break; + } + + rc = _grn_obj_remove(ctx, col, GRN_FALSE); + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, col); + break; + } + } GRN_HASH_EACH_END(ctx, cursor); + } + grn_hash_close(ctx, cols); + } + return rc; +} + +static grn_rc +_grn_obj_remove_db_index_columns(grn_ctx *ctx, grn_obj *db) +{ + grn_rc rc = GRN_SUCCESS; + grn_table_cursor *cur; + if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_id id; + while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { + grn_obj *obj = grn_ctx_at(ctx, id); + if (obj && obj->header.type == GRN_COLUMN_INDEX) { + rc = _grn_obj_remove(ctx, obj, GRN_FALSE); + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, obj); + break; + } + } + } + grn_table_cursor_close(ctx, cur); + } + return rc; +} + +static grn_rc +_grn_obj_remove_db_reference_columns(grn_ctx *ctx, grn_obj *db) +{ + grn_rc rc = GRN_SUCCESS; + grn_table_cursor *cur; + if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_id id; + while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { + grn_obj *obj = grn_ctx_at(ctx, id); + grn_obj *range = NULL; + + if (!obj) { + continue; + } + + switch (obj->header.type) { + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + if (!DB_OBJ(obj)->range) { + break; + } + + range = grn_ctx_at(ctx, DB_OBJ(obj)->range); + if (!range) { + break; + } + + switch (range->header.type) { + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + rc = _grn_obj_remove(ctx, obj, GRN_FALSE); + break; + } + break; + } + + if (rc != GRN_SUCCESS) { + break; + } + } + grn_table_cursor_close(ctx, cur); + } + return rc; +} + +static grn_rc +_grn_obj_remove_db_reference_tables(grn_ctx *ctx, grn_obj *db) +{ + grn_rc rc = GRN_SUCCESS; + grn_table_cursor *cur; + if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_id id; + while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { + grn_obj *obj = grn_ctx_at(ctx, id); + grn_obj *domain = NULL; + + if (!obj) { + continue; + } + + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + if (!obj->header.domain) { + break; + } + + domain = grn_ctx_at(ctx, obj->header.domain); + if (!domain) { + break; + } + + switch (domain->header.type) { + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + rc = _grn_obj_remove(ctx, obj, GRN_FALSE); + break; + } + break; + } + + if (rc != GRN_SUCCESS) { + break; + } + } + grn_table_cursor_close(ctx, cur); + } + return rc; +} + +static grn_rc +_grn_obj_remove_db_all_tables(grn_ctx *ctx, grn_obj *db) +{ + grn_rc rc = GRN_SUCCESS; + grn_table_cursor *cur; + if ((cur = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_id id; + while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { + grn_obj *obj = grn_ctx_at(ctx, id); + + if (!obj) { + continue; + } + + switch (obj->header.type) { + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + rc = _grn_obj_remove(ctx, obj, GRN_FALSE); + break; + } + + if (rc != GRN_SUCCESS) { + break; + } + } + grn_table_cursor_close(ctx, cur); + } + return rc; +} + +static grn_rc +_grn_obj_remove_db(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path) +{ + grn_rc rc = GRN_SUCCESS; + const char *io_spath; + char *spath; + grn_db *s = (grn_db *)db; + unsigned char key_type; + + rc = _grn_obj_remove_db_index_columns(ctx, db); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_db_reference_columns(ctx, db); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_db_reference_tables(ctx, db); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_db_all_tables(ctx, db); + if (rc != GRN_SUCCESS) { return rc; } + + if (s->specs && + (io_spath = grn_obj_path(ctx, (grn_obj *)s->specs)) && *io_spath != '\0') { + if (!(spath = GRN_STRDUP(io_spath))) { + ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_spath); + return ctx->rc; + } + } else { + spath = NULL; + } + + key_type = s->keys->header.type; + + rc = grn_obj_close(ctx, obj); + if (rc != GRN_SUCCESS) { + if (spath) { + GRN_FREE(spath); + } + return rc; + } + + if (spath) { + rc = grn_ja_remove(ctx, spath); + GRN_FREE(spath); + if (rc != GRN_SUCCESS) { return rc; } + } + + if (path) { + switch (key_type) { + case GRN_TABLE_PAT_KEY : + rc = grn_pat_remove(ctx, path); + break; + case GRN_TABLE_DAT_KEY : + rc = grn_dat_remove(ctx, path); + break; + } + if (rc == GRN_SUCCESS) { + rc = grn_db_config_remove(ctx, path); + } else { + grn_db_config_remove(ctx, path); + } + } + + return rc; +} + +static grn_rc +remove_reference_tables(grn_ctx *ctx, grn_obj *table, grn_obj *db) +{ + grn_rc rc = GRN_SUCCESS; + grn_bool is_close_opened_object_mode = GRN_FALSE; + grn_id table_id; + char table_name[GRN_TABLE_MAX_KEY_SIZE]; + int table_name_size; + grn_table_cursor *cursor; + + if (grn_thread_get_limit() == 1) { + is_close_opened_object_mode = GRN_TRUE; + } + + table_id = DB_OBJ(table)->id; + table_name_size = grn_obj_name(ctx, table, table_name, GRN_TABLE_MAX_KEY_SIZE); + if ((cursor = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, + GRN_CURSOR_BY_ID))) { + grn_id id; + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_obj *object; + grn_bool is_removed = GRN_FALSE; + + if (is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + object = grn_ctx_at(ctx, id); + if (!object) { + ERRCLR(ctx); + if (is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + continue; + } + + switch (object->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + if (DB_OBJ(object)->id == table_id) { + break; + } + + if (object->header.domain == table_id) { + rc = _grn_obj_remove(ctx, object, GRN_TRUE); + is_removed = (grn_table_at(ctx, db, id) == GRN_ID_NIL); + } + break; + case GRN_TABLE_NO_KEY : + break; + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_FIX_SIZE : + if (object->header.domain == table_id) { + break; + } + if (DB_OBJ(object)->range == table_id) { + rc = _grn_obj_remove(ctx, object, GRN_FALSE); + is_removed = (grn_table_at(ctx, db, id) == GRN_ID_NIL); + } + break; + case GRN_COLUMN_INDEX : + break; + default: + break; + } + + if (!is_removed) { + grn_obj_unlink(ctx, object); + } + + if (is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + + if (rc != GRN_SUCCESS) { + break; + } + } + grn_table_cursor_close(ctx, cursor); + } + + return rc; +} + +static grn_bool +is_removable_table(grn_ctx *ctx, grn_obj *table, grn_obj *db) +{ + grn_id table_id; + grn_id reference_object_id; + + table_id = DB_OBJ(table)->id; + if (table_id & GRN_OBJ_TMP_OBJECT) { + return GRN_TRUE; + } + + reference_object_id = grn_table_find_reference_object(ctx, table); + if (reference_object_id == GRN_ID_NIL) { + return GRN_TRUE; + } + + { + grn_obj *db; + const char *table_name; + int table_name_size; + grn_obj *reference_object; + const char *reference_object_name; + int reference_object_name_size; + + db = grn_ctx_db(ctx); + + table_name = _grn_table_key(ctx, db, table_id,&table_name_size); + + reference_object = grn_ctx_at(ctx, reference_object_id); + reference_object_name = _grn_table_key(ctx, + db, + reference_object_id, + &reference_object_name_size); + if (reference_object) { + if (grn_obj_is_table(ctx, reference_object)) { + ERR(GRN_OPERATION_NOT_PERMITTED, + "[table][remove] a table that references the table exists: " + "<%.*s._key> -> <%.*s>", + reference_object_name_size, reference_object_name, + table_name_size, table_name); + } else { + ERR(GRN_OPERATION_NOT_PERMITTED, + "[table][remove] a column that references the table exists: " + "<%.*s> -> <%.*s>", + reference_object_name_size, reference_object_name, + table_name_size, table_name); + } + } else { + ERR(GRN_OPERATION_NOT_PERMITTED, + "[table][remove] a dangling object that references the table exists: " + "<%.*s(%u)> -> <%.*s>", + reference_object_name_size, + reference_object_name, + reference_object_id, + table_name_size, table_name); + } + } + + return GRN_FALSE; +} + +static inline grn_rc +_grn_obj_remove_spec(grn_ctx *ctx, grn_obj *db, grn_id id, uint8_t type) +{ + const char *name; + uint32_t name_size = 0; + + name = _grn_table_key(ctx, db, id, &name_size); + /* TODO: reduce log level. */ + GRN_LOG(ctx, GRN_LOG_NOTICE, + "spec:%u:remove:%.*s:%u(%s)", + id, + name_size, name, + type, + grn_obj_type_to_string(type)); + + return grn_ja_put(ctx, ((grn_db *)db)->specs, id, NULL, 0, GRN_OBJ_SET, NULL); +} + +static grn_rc +_grn_obj_remove_pat(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path, grn_bool dependent) +{ + grn_rc rc = GRN_SUCCESS; + uint8_t type; + + type = obj->header.type; + + if (dependent) { + rc = remove_reference_tables(ctx, obj, db); + if (rc != GRN_SUCCESS) { + return rc; + } + } else { + if (!is_removable_table(ctx, obj, db)) { + return ctx->rc; + } + } + + rc = remove_index(ctx, obj, GRN_HOOK_INSERT); + if (rc != GRN_SUCCESS) { return rc; } + rc = remove_columns(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + rc = grn_obj_close(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + if (path) { + rc = grn_pat_remove(ctx, path); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_spec(ctx, db, id, type); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + if (rc != GRN_SUCCESS) { return rc; } + } + + grn_obj_touch(ctx, db, NULL); + + return rc; +} + +static grn_rc +_grn_obj_remove_dat(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path, grn_bool dependent) +{ + grn_rc rc = GRN_SUCCESS; + uint8_t type; + + type = obj->header.type; + + if (dependent) { + rc = remove_reference_tables(ctx, obj, db); + if (rc != GRN_SUCCESS) { + return rc; + } + } else { + if (!is_removable_table(ctx, obj, db)) { + return ctx->rc; + } + } + + rc = remove_index(ctx, obj, GRN_HOOK_INSERT); + if (rc != GRN_SUCCESS) { return rc; } + rc = remove_columns(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + rc = grn_obj_close(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + if (path) { + rc = grn_dat_remove(ctx, path); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_spec(ctx, db, id, type); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + if (rc != GRN_SUCCESS) { return rc; } + } + + grn_obj_touch(ctx, db, NULL); + + return rc; +} + +static grn_rc +_grn_obj_remove_hash(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path, grn_bool dependent) +{ + grn_rc rc = GRN_SUCCESS; + uint8_t type; + + type = obj->header.type; + + if (dependent) { + rc = remove_reference_tables(ctx, obj, db); + if (rc != GRN_SUCCESS) { + return rc; + } + } else { + if (!is_removable_table(ctx, obj, db)) { + return ctx->rc; + } + } + + rc = remove_index(ctx, obj, GRN_HOOK_INSERT); + if (rc != GRN_SUCCESS) { return rc; } + rc = remove_columns(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + rc = grn_obj_close(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + if (path) { + rc = grn_hash_remove(ctx, path); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_spec(ctx, db, id, type); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + if (rc != GRN_SUCCESS) { return rc; } + } + + grn_obj_touch(ctx, db, NULL); + + return rc; +} + +static grn_rc +_grn_obj_remove_array(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path, grn_bool dependent) +{ + grn_rc rc = GRN_SUCCESS; + uint8_t type; + + type = obj->header.type; + + if (dependent) { + rc = remove_reference_tables(ctx, obj, db); + if (rc != GRN_SUCCESS) { + return rc; + } + } else { + if (!is_removable_table(ctx, obj, db)) { + return ctx->rc; + } + } + + rc = remove_columns(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + rc = grn_obj_close(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + if (path) { + rc = grn_array_remove(ctx, path); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_spec(ctx, db, id, type); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + if (rc != GRN_SUCCESS) { return rc; } + } + + grn_obj_touch(ctx, db, NULL); + + return rc; +} + +static grn_rc +_grn_obj_remove_ja(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path) +{ + grn_rc rc = GRN_SUCCESS; + uint8_t type; + + type = obj->header.type; + + rc = remove_index(ctx, obj, GRN_HOOK_SET); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_close(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + if (path) { + rc = grn_ja_remove(ctx, path); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_spec(ctx, db, id, type); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + if (rc != GRN_SUCCESS) { return rc; } + } + + grn_obj_touch(ctx, db, NULL); + + return rc; +} + +static grn_rc +_grn_obj_remove_ra(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path) +{ + grn_rc rc = GRN_SUCCESS; + uint8_t type; + + type = obj->header.type; + + rc = remove_index(ctx, obj, GRN_HOOK_SET); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_close(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + if (path) { + rc = grn_ra_remove(ctx, path); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_spec(ctx, db, id, type); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + if (rc != GRN_SUCCESS) { return rc; } + } + grn_obj_touch(ctx, db, NULL); + + return rc; +} + +static grn_rc +_grn_obj_remove_index(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path) +{ + grn_rc rc = GRN_SUCCESS; + uint8_t type; + + type = obj->header.type; + + delete_source_hook(ctx, obj); + rc = grn_obj_close(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + if (path) { + rc = grn_ii_remove(ctx, path); + if (rc != GRN_SUCCESS) { return rc; } + rc = _grn_obj_remove_spec(ctx, db, id, type); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + if (rc != GRN_SUCCESS) { return rc; } + } + + grn_obj_touch(ctx, db, NULL); + + return rc; +} + +static grn_rc +_grn_obj_remove_db_obj(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path) +{ + grn_rc rc = GRN_SUCCESS; + uint8_t type; + + type = obj->header.type; + + rc = grn_obj_close(ctx, obj); + if (rc != GRN_SUCCESS) { return rc; } + + if (path) { + rc = grn_io_remove(ctx, path); + if (rc != GRN_SUCCESS) { return rc; } + } + + if (!(id & GRN_OBJ_TMP_OBJECT)) { + rc = _grn_obj_remove_spec(ctx, db, id, type); + if (rc != GRN_SUCCESS) { return rc; } + rc = grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + if (rc != GRN_SUCCESS) { return rc; } + } + + grn_obj_touch(ctx, db, NULL); + + return rc; +} + +static grn_rc +_grn_obj_remove_other(grn_ctx *ctx, grn_obj *obj, grn_obj *db, grn_id id, + const char *path) +{ + return grn_obj_close(ctx, obj); +} + +static grn_rc +_grn_obj_remove(grn_ctx *ctx, grn_obj *obj, grn_bool dependent) +{ + grn_rc rc = GRN_SUCCESS; + grn_id id = GRN_ID_NIL; + grn_obj *db = NULL; + const char *io_path; + char *path; + grn_bool is_temporary_open_target = GRN_FALSE; + + if (ctx->impl && ctx->impl->db) { + grn_id id; + uint32_t s = 0; + const char *n; + + id = DB_OBJ(obj)->id; + n = _grn_table_key(ctx, ctx->impl->db, id, &s); + if (s > 0) { + GRN_LOG(ctx, GRN_LOG_NOTICE, "DDL:%u:obj_remove %.*s", id, s, n); + } + } + if (obj->header.type != GRN_PROC && + (io_path = grn_obj_path(ctx, obj)) && *io_path != '\0') { + if (!(path = GRN_STRDUP(io_path))) { + ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path); + return ctx->rc; + } + } else { + path = NULL; + } + if (GRN_DB_OBJP(obj)) { + id = DB_OBJ(obj)->id; + db = DB_OBJ(obj)->db; + } + switch (obj->header.type) { + case GRN_DB : + rc = _grn_obj_remove_db(ctx, obj, db, id, path); + break; + case GRN_TABLE_PAT_KEY : + rc = _grn_obj_remove_pat(ctx, obj, db, id, path, dependent); + is_temporary_open_target = GRN_TRUE; + break; + case GRN_TABLE_DAT_KEY : + rc = _grn_obj_remove_dat(ctx, obj, db, id, path, dependent); + is_temporary_open_target = GRN_TRUE; + break; + case GRN_TABLE_HASH_KEY : + rc = _grn_obj_remove_hash(ctx, obj, db, id, path, dependent); + is_temporary_open_target = GRN_TRUE; + break; + case GRN_TABLE_NO_KEY : + rc = _grn_obj_remove_array(ctx, obj, db, id, path, dependent); + is_temporary_open_target = GRN_TRUE; + break; + case GRN_COLUMN_VAR_SIZE : + rc = _grn_obj_remove_ja(ctx, obj, db, id, path); + is_temporary_open_target = GRN_TRUE; + break; + case GRN_COLUMN_FIX_SIZE : + rc = _grn_obj_remove_ra(ctx, obj, db, id, path); + is_temporary_open_target = GRN_TRUE; + break; + case GRN_COLUMN_INDEX : + rc = _grn_obj_remove_index(ctx, obj, db, id, path); + is_temporary_open_target = GRN_TRUE; + break; + default : + if (GRN_DB_OBJP(obj)) { + rc = _grn_obj_remove_db_obj(ctx, obj, db, id, path); + } else { + rc = _grn_obj_remove_other(ctx, obj, db, id, path); + } + } + if (path) { + GRN_FREE(path); + } else { + is_temporary_open_target = GRN_FALSE; + } + + if (is_temporary_open_target && rc == GRN_SUCCESS) { + grn_obj *space; + space = ctx->impl->temporary_open_spaces.current; + if (space) { + unsigned int i, n_elements; + n_elements = GRN_BULK_VSIZE(space) / sizeof(grn_obj *); + for (i = 0; i < n_elements; i++) { + if (GRN_PTR_VALUE_AT(space, i) == obj) { + GRN_PTR_SET_AT(ctx, space, i, NULL); + } + } + } + } + + return rc; +} + +grn_rc +grn_obj_remove(grn_ctx *ctx, grn_obj *obj) +{ + grn_rc rc = GRN_SUCCESS; + GRN_API_ENTER; + if (ctx->impl && ctx->impl->db && ctx->impl->db != obj) { + grn_io *io = grn_obj_get_io(ctx, ctx->impl->db); + rc = grn_io_lock(ctx, io, grn_lock_timeout); + if (rc == GRN_SUCCESS) { + rc = _grn_obj_remove(ctx, obj, GRN_FALSE); + grn_io_unlock(io); + } + } else { + rc = _grn_obj_remove(ctx, obj, GRN_FALSE); + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_obj_remove_dependent(grn_ctx *ctx, grn_obj *obj) +{ + grn_rc rc = GRN_SUCCESS; + GRN_API_ENTER; + if (ctx->impl && ctx->impl->db && ctx->impl->db != obj) { + grn_io *io = grn_obj_get_io(ctx, ctx->impl->db); + rc = grn_io_lock(ctx, io, grn_lock_timeout); + if (rc == GRN_SUCCESS) { + rc = _grn_obj_remove(ctx, obj, GRN_TRUE); + grn_io_unlock(io); + } + } else { + rc = _grn_obj_remove(ctx, obj, GRN_TRUE); + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_obj_remove_force(grn_ctx *ctx, const char *name, int name_size) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *db; + grn_id obj_id; + char path[PATH_MAX]; + + GRN_API_ENTER; + + if (!(ctx->impl && ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, + "[object][remove][force] database isn't initialized"); + rc = ctx->rc; + goto exit; + } + + db = ctx->impl->db; + if (name_size == -1) { + name_size = strlen(name); + } + obj_id = grn_table_get(ctx, db, name, name_size); + if (obj_id == GRN_ID_NIL) { + ERR(GRN_INVALID_ARGUMENT, + "[object][remove][force] nonexistent object: <%.*s>", + name_size, name); + rc = ctx->rc; + goto exit; + } + + grn_obj_delete_by_id(ctx, db, obj_id, GRN_TRUE); + grn_obj_path_by_id(ctx, db, obj_id, path); + grn_io_remove_if_exist(ctx, path); + grn_strcat(path, PATH_MAX, ".c"); + grn_io_remove_if_exist(ctx, path); + +exit : + GRN_API_RETURN(rc); +} + +grn_rc +grn_table_update_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, + const void *dest_key, unsigned int dest_key_size) +{ + grn_rc rc = GRN_OPERATION_NOT_SUPPORTED; + GRN_API_ENTER; + if (table->header.type == GRN_TABLE_DAT_KEY) { + grn_dat *dat = (grn_dat *)table; + if (dat->io && !(dat->io->flags & GRN_IO_TEMPORARY)) { + if (grn_io_lock(ctx, dat->io, grn_lock_timeout)) { + rc = ctx->rc; + } else { + rc = grn_dat_update_by_id(ctx, dat, id, dest_key, dest_key_size); + grn_io_unlock(dat->io); + } + } else { + rc = grn_dat_update_by_id(ctx, dat, id, dest_key, dest_key_size); + } + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_table_update(grn_ctx *ctx, grn_obj *table, + const void *src_key, unsigned int src_key_size, + const void *dest_key, unsigned int dest_key_size) +{ + grn_rc rc = GRN_OPERATION_NOT_SUPPORTED; + GRN_API_ENTER; + if (table->header.type == GRN_TABLE_DAT_KEY) { + rc = grn_dat_update(ctx, (grn_dat *)table, + src_key, src_key_size, + dest_key, dest_key_size); + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_obj_rename(grn_ctx *ctx, grn_obj *obj, const char *name, unsigned int name_size) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (ctx && ctx->impl && GRN_DB_P(ctx->impl->db) && GRN_DB_OBJP(obj) && !IS_TEMP(obj)) { + grn_db *s = (grn_db *)ctx->impl->db; + grn_obj *keys = (grn_obj *)s->keys; + rc = grn_table_update_by_id(ctx, keys, DB_OBJ(obj)->id, name, name_size); + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_table_rename(grn_ctx *ctx, grn_obj *table, const char *name, unsigned int name_size) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_hash *cols; + + GRN_API_ENTER; + + if (!GRN_OBJ_TABLEP(table)) { + char table_name[GRN_TABLE_MAX_KEY_SIZE]; + int table_name_size; + table_name_size = grn_obj_name(ctx, table, table_name, + GRN_TABLE_MAX_KEY_SIZE); + rc = GRN_INVALID_ARGUMENT; + ERR(rc, + "[table][rename] isn't table: <%.*s> -> <%.*s>", + table_name_size, table_name, + name_size, name); + goto exit; + } + if (IS_TEMP(table)) { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, + "[table][rename] temporary table doesn't have name: " + "(anonymous) -> <%.*s>", + name_size, name); + goto exit; + } + + if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { + grn_table_columns(ctx, table, "", 0, (grn_obj *)cols); + if (!(rc = grn_obj_rename(ctx, table, name, name_size))) { + grn_id *key; + char fullname[GRN_TABLE_MAX_KEY_SIZE]; + grn_memcpy(fullname, name, name_size); + fullname[name_size] = GRN_DB_DELIMITER; + GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { + grn_obj *col = grn_ctx_at(ctx, *key); + if (col) { + int colname_len = grn_column_name(ctx, col, fullname + name_size + 1, + GRN_TABLE_MAX_KEY_SIZE - name_size - 1); + if (colname_len) { + if ((rc = grn_obj_rename(ctx, col, fullname, + name_size + 1 + colname_len))) { + break; + } + } + } + }); + } + grn_hash_close(ctx, cols); + } +exit: + GRN_API_RETURN(rc); +} + +grn_rc +grn_column_rename(grn_ctx *ctx, grn_obj *column, const char *name, unsigned int name_size) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (GRN_DB_OBJP(column)) { + char fullname[GRN_TABLE_MAX_KEY_SIZE]; + grn_db *s = (grn_db *)DB_OBJ(column)->db; + int len = grn_table_get_key(ctx, s->keys, DB_OBJ(column)->header.domain, + fullname, GRN_TABLE_MAX_KEY_SIZE); + if (name_size + 1 + len > GRN_TABLE_MAX_KEY_SIZE) { + ERR(GRN_INVALID_ARGUMENT, + "[column][rename] too long column name: required name_size(%d) < %d" + ": <%.*s>.<%.*s>", + name_size, GRN_TABLE_MAX_KEY_SIZE - 1 - len, + len, fullname, name_size, name); + goto exit; + } + fullname[len] = GRN_DB_DELIMITER; + grn_memcpy(fullname + len + 1, name, name_size); + name_size += len + 1; + rc = grn_obj_rename(ctx, column, fullname, name_size); + if (rc == GRN_SUCCESS) { + grn_obj_touch(ctx, column, NULL); + } + } +exit : + GRN_API_RETURN(rc); +} + +grn_rc +grn_obj_path_rename(grn_ctx *ctx, const char *old_path, const char *new_path) +{ + GRN_API_ENTER; + GRN_API_RETURN(GRN_SUCCESS); +} + +/* db must be validated by caller */ +grn_id +grn_obj_register(grn_ctx *ctx, grn_obj *db, const char *name, unsigned int name_size) +{ + grn_id id = GRN_ID_NIL; + if (name && name_size) { + grn_db *s = (grn_db *)db; + int added; + if (!(id = grn_table_add(ctx, s->keys, name, name_size, &added))) { + grn_rc rc; + rc = ctx->rc; + if (rc == GRN_SUCCESS) { + rc = GRN_NO_MEMORY_AVAILABLE; + } + ERR(rc, + "[object][register] failed to register a name: <%.*s>%s%s%s", + name_size, name, + ctx->rc == GRN_SUCCESS ? "" : ": <", + ctx->rc == GRN_SUCCESS ? "" : ctx->errbuf, + ctx->rc == GRN_SUCCESS ? "" : ">"); + } else if (!added) { + ERR(GRN_INVALID_ARGUMENT, + "[object][register] already used name was assigned: <%.*s>", + name_size, name); + id = GRN_ID_NIL; + } + } else if (ctx->impl && ctx->impl->values) { + id = grn_array_add(ctx, ctx->impl->values, NULL) | GRN_OBJ_TMP_OBJECT; + } + return id; +} + +grn_rc +grn_obj_delete_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, grn_bool removep) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (id) { + if (id & GRN_OBJ_TMP_OBJECT) { + if (ctx->impl) { + if (id & GRN_OBJ_TMP_COLUMN) { + if (ctx->impl->temporary_columns) { + rc = grn_pat_delete_by_id(ctx, ctx->impl->temporary_columns, + id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT), + NULL); + } + } else { + if (ctx->impl->values) { + rc = grn_array_delete_by_id(ctx, ctx->impl->values, + id & ~GRN_OBJ_TMP_OBJECT, NULL); + } + } + } + } else { + db_value *vp; + grn_db *s = (grn_db *)db; + if ((vp = grn_tiny_array_at(&s->values, id))) { + GRN_ASSERT(!vp->lock); + vp->lock = 0; + vp->ptr = NULL; + vp->done = 0; + } + if (removep) { + switch (s->keys->header.type) { + case GRN_TABLE_PAT_KEY : + rc = grn_pat_delete_by_id(ctx, (grn_pat *)s->keys, id, NULL); + break; + case GRN_TABLE_DAT_KEY : + rc = grn_dat_delete_by_id(ctx, (grn_dat *)s->keys, id, NULL); + break; + } + } else { + rc = GRN_SUCCESS; + } + } + } + GRN_API_RETURN(rc); +} + + +grn_rc +grn_obj_path_by_id(grn_ctx *ctx, grn_obj *db, grn_id id, char *buffer) +{ + grn_rc rc = GRN_SUCCESS; + GRN_API_ENTER; + if (!GRN_DB_P(db) || !buffer) { + rc = GRN_INVALID_ARGUMENT; + } else { + grn_db_generate_pathname(ctx, db, id, buffer); + } + GRN_API_RETURN(rc); +} + +/* db must be validated by caller */ +grn_rc +grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj) +{ + grn_rc rc = GRN_SUCCESS; + if (id) { + if (id & GRN_OBJ_TMP_OBJECT) { + if (id & GRN_OBJ_TMP_COLUMN) { + if (ctx->impl && ctx->impl->temporary_columns) { + grn_id real_id = id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT); + rc = grn_pat_set_value(ctx, ctx->impl->temporary_columns, + real_id, &obj, GRN_OBJ_SET); + } + } else { + if (ctx->impl && ctx->impl->values) { + rc = grn_array_set_value(ctx, ctx->impl->values, + id & ~GRN_OBJ_TMP_OBJECT, &obj, GRN_OBJ_SET); + } + } + } else { + db_value *vp; + vp = grn_tiny_array_at(&((grn_db *)db)->values, id); + if (!vp) { + rc = GRN_NO_MEMORY_AVAILABLE; + ERR(rc, "grn_tiny_array_at failed (%d)", id); + return rc; + } + vp->lock = 1; + vp->ptr = (grn_obj *)obj; + } + } + obj->id = id; + obj->db = db; + obj->source = NULL; + obj->source_size = 0; + { + grn_hook_entry entry; + for (entry = 0; entry < N_HOOK_ENTRIES; entry++) { + obj->hooks[entry] = NULL; + } + } + grn_obj_spec_save(ctx, obj); + return rc; +} + +#define GET_PATH(spec,decoded_spec,buffer,s,id) do {\ + if (spec->header.flags & GRN_OBJ_CUSTOM_NAME) {\ + const char *path;\ + unsigned int size = grn_vector_get_element(ctx,\ + decoded_spec,\ + GRN_SERIALIZED_SPEC_INDEX_PATH,\ + &path,\ + NULL,\ + NULL);\ + if (size > PATH_MAX) { ERR(GRN_FILENAME_TOO_LONG, "too long path"); }\ + grn_memcpy(buffer, path, size);\ + buffer[size] = '\0';\ + } else {\ + grn_db_generate_pathname(ctx, (grn_obj *)s, id, buffer);\ + }\ +} while (0) + +#define UNPACK_INFO(spec,decoded_spec) do {\ + if (vp->ptr) {\ + const char *p;\ + uint32_t size;\ + grn_db_obj *r = DB_OBJ(vp->ptr);\ + r->header = spec->header;\ + r->id = id;\ + r->range = spec->range;\ + r->db = (grn_obj *)s;\ + size = grn_vector_get_element(ctx,\ + decoded_spec,\ + GRN_SERIALIZED_SPEC_INDEX_SOURCE,\ + &p,\ + NULL,\ + NULL);\ + if (size) {\ + if ((r->source = GRN_MALLOC(size))) {\ + grn_memcpy(r->source, p, size);\ + r->source_size = size;\ + }\ + }\ + size = grn_vector_get_element(ctx,\ + decoded_spec,\ + GRN_SERIALIZED_SPEC_INDEX_HOOK,\ + &p,\ + NULL,\ + NULL);\ + grn_hook_unpack(ctx, r, p, size);\ + }\ +} while (0) + +static void +grn_token_filters_unpack(grn_ctx *ctx, + grn_obj *token_filters, + grn_obj *spec_vector) +{ + grn_id *token_filter_ids; + unsigned int element_size; + unsigned int i, n_token_filter_ids; + + if (grn_vector_size(ctx, spec_vector) <= GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS) { + return; + } + + element_size = grn_vector_get_element(ctx, + spec_vector, + GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS, + (const char **)(&token_filter_ids), + NULL, + NULL); + n_token_filter_ids = element_size / sizeof(grn_id); + for (i = 0; i < n_token_filter_ids; i++) { + grn_id token_filter_id = token_filter_ids[i]; + grn_obj *token_filter; + + token_filter = grn_ctx_at(ctx, token_filter_id); + if (!token_filter) { + ERR(GRN_INVALID_ARGUMENT, + "nonexistent token filter ID: %d", token_filter_id); + return; + } + GRN_PTR_PUT(ctx, token_filters, token_filter); + } +} + +grn_bool +grn_db_spec_unpack(grn_ctx *ctx, + grn_id id, + void *encoded_spec, + uint32_t encoded_spec_size, + grn_obj_spec **spec, + grn_obj *decoded_spec, + const char *error_message_tag) +{ + grn_obj *db; + grn_db *db_raw; + grn_rc rc; + uint32_t spec_size; + + db = ctx->impl->db; + db_raw = (grn_db *)db; + + rc = grn_vector_decode(ctx, + decoded_spec, + encoded_spec, + encoded_spec_size); + if (rc != GRN_SUCCESS) { + const char *name; + uint32_t name_size; + name = _grn_table_key(ctx, db, id, &name_size); + GRN_LOG((ctx), GRN_LOG_ERROR, + "%s: failed to decode spec: <%u>(<%.*s>):<%u>: %s", + error_message_tag, + id, + name_size, name, + encoded_spec_size, + grn_rc_to_string(rc)); + return GRN_FALSE; + } + + spec_size = grn_vector_get_element(ctx, + decoded_spec, + GRN_SERIALIZED_SPEC_INDEX_SPEC, + (const char **)spec, + NULL, + NULL); + if (spec_size == 0) { + const char *name; + uint32_t name_size; + name = _grn_table_key(ctx, db, id, &name_size); + GRN_LOG(ctx, GRN_LOG_ERROR, + "%s: spec value is empty: <%u>(<%.*s>)", + error_message_tag, + id, + name_size, name); + return GRN_FALSE; + } + + return GRN_TRUE; +} + +grn_obj * +grn_ctx_at(grn_ctx *ctx, grn_id id) +{ + grn_obj *res = NULL; + if (!ctx || !ctx->impl || !id) { return res; } + GRN_API_ENTER; + if (id & GRN_OBJ_TMP_OBJECT) { + if (id & GRN_OBJ_TMP_COLUMN) { + if (ctx->impl->temporary_columns) { + grn_id real_id = id & ~(GRN_OBJ_TMP_COLUMN | GRN_OBJ_TMP_OBJECT); + grn_obj **tmp_obj; + uint32_t size; + tmp_obj = (grn_obj **)grn_pat_get_value_(ctx, + ctx->impl->temporary_columns, + real_id, + &size); + if (tmp_obj) { + res = *tmp_obj; + } + } + } else { + if (ctx->impl->values) { + grn_obj **tmp_obj; + tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, + id & ~GRN_OBJ_TMP_OBJECT); + if (tmp_obj) { + res = *tmp_obj; + } + } + } + } else { + grn_db *s = (grn_db *)ctx->impl->db; + if (s) { + db_value *vp; + uint32_t l, *pl, ntrial; + if (!(vp = grn_tiny_array_at(&s->values, id))) { goto exit; } +#ifdef USE_NREF + pl = &vp->lock; + for (ntrial = 0;; ntrial++) { + GRN_ATOMIC_ADD_EX(pl, 1, l); + if (l < GRN_IO_MAX_REF) { break; } + if (ntrial >= 10) { + GRN_LOG(ctx, GRN_LOG_NOTICE, "max trial in ctx_at(%p,%d)", vp->ptr, vp->lock); + break; + } + GRN_ATOMIC_ADD_EX(pl, -1, l); + GRN_FUTEX_WAIT(pl); + } +#endif /* USE_NREF */ + if (s->specs && !vp->ptr /* && !vp->done */) { +#ifndef USE_NREF + pl = &vp->lock; + for (ntrial = 0;; ntrial++) { + GRN_ATOMIC_ADD_EX(pl, 1, l); + if (l < GRN_IO_MAX_REF) { break; } + if (ntrial >= 10) { + GRN_LOG(ctx, GRN_LOG_NOTICE, "max trial in ctx_at(%p,%d)", vp->ptr, vp->lock); + break; + } + GRN_ATOMIC_ADD_EX(pl, -1, l); + GRN_FUTEX_WAIT(pl); + } +#endif /* USE_NREF */ + if (!l) { + grn_io_win iw; + uint32_t encoded_spec_size; + void *encoded_spec; + + encoded_spec = grn_ja_ref(ctx, s->specs, id, &iw, &encoded_spec_size); + if (encoded_spec) { + grn_bool success; + grn_obj_spec *spec; + grn_obj decoded_spec; + + GRN_OBJ_INIT(&decoded_spec, GRN_VECTOR, 0, GRN_DB_TEXT); + success = grn_db_spec_unpack(ctx, + id, + encoded_spec, + encoded_spec_size, + &spec, + &decoded_spec, + "grn_ctx_at"); + if (success) { + char buffer[PATH_MAX]; + switch (spec->header.type) { + case GRN_TYPE : + vp->ptr = (grn_obj *)grn_type_open(ctx, spec); + UNPACK_INFO(spec, &decoded_spec); + break; + case GRN_TABLE_HASH_KEY : + GET_PATH(spec, &decoded_spec, buffer, s, id); + vp->ptr = (grn_obj *)grn_hash_open(ctx, buffer); + if (vp->ptr) { + grn_hash *hash = (grn_hash *)(vp->ptr); + grn_obj_flags flags = vp->ptr->header.flags; + UNPACK_INFO(spec, &decoded_spec); + vp->ptr->header.flags = flags; + grn_token_filters_unpack(ctx, + &(hash->token_filters), + &decoded_spec); + } + break; + case GRN_TABLE_PAT_KEY : + GET_PATH(spec, &decoded_spec, buffer, s, id); + vp->ptr = (grn_obj *)grn_pat_open(ctx, buffer); + if (vp->ptr) { + grn_pat *pat = (grn_pat *)(vp->ptr); + grn_obj_flags flags = vp->ptr->header.flags; + UNPACK_INFO(spec, &decoded_spec); + vp->ptr->header.flags = flags; + grn_token_filters_unpack(ctx, + &(pat->token_filters), + &decoded_spec); + } + break; + case GRN_TABLE_DAT_KEY : + GET_PATH(spec, &decoded_spec, buffer, s, id); + vp->ptr = (grn_obj *)grn_dat_open(ctx, buffer); + if (vp->ptr) { + grn_dat *dat = (grn_dat *)(vp->ptr); + grn_obj_flags flags = vp->ptr->header.flags; + UNPACK_INFO(spec, &decoded_spec); + vp->ptr->header.flags = flags; + grn_token_filters_unpack(ctx, + &(dat->token_filters), + &decoded_spec); + } + break; + case GRN_TABLE_NO_KEY : + GET_PATH(spec, &decoded_spec, buffer, s, id); + vp->ptr = (grn_obj *)grn_array_open(ctx, buffer); + UNPACK_INFO(spec, &decoded_spec); + break; + case GRN_COLUMN_VAR_SIZE : + GET_PATH(spec, &decoded_spec, buffer, s, id); + vp->ptr = (grn_obj *)grn_ja_open(ctx, buffer); + UNPACK_INFO(spec, &decoded_spec); + break; + case GRN_COLUMN_FIX_SIZE : + GET_PATH(spec, &decoded_spec, buffer, s, id); + vp->ptr = (grn_obj *)grn_ra_open(ctx, buffer); + UNPACK_INFO(spec, &decoded_spec); + break; + case GRN_COLUMN_INDEX : + GET_PATH(spec, &decoded_spec, buffer, s, id); + { + grn_obj *table = grn_ctx_at(ctx, spec->header.domain); + vp->ptr = (grn_obj *)grn_ii_open(ctx, buffer, table); + } + UNPACK_INFO(spec, &decoded_spec); + break; + case GRN_PROC : + GET_PATH(spec, &decoded_spec, buffer, s, id); + grn_plugin_register(ctx, buffer); + break; + case GRN_EXPR : + { + const char *p; + uint32_t size; + uint8_t *u; + size = grn_vector_get_element(ctx, + &decoded_spec, + GRN_SERIALIZED_SPEC_INDEX_EXPR, + &p, + NULL, + NULL); + u = (uint8_t *)p; + vp->ptr = grn_expr_open(ctx, spec, u, u + size); + } + break; + } + if (!vp->ptr) { + const char *name; + uint32_t name_size = 0; + name = _grn_table_key(ctx, (grn_obj *)s, id, &name_size); + GRN_LOG(ctx, GRN_LOG_ERROR, + "grn_ctx_at: failed to open object: " + "<%u>(<%.*s>):<%u>(<%s>)", + id, + name_size, name, + spec->header.type, + grn_obj_type_to_string(spec->header.type)); + } + } + GRN_OBJ_FIN(ctx, &decoded_spec); + grn_ja_unref(ctx, &iw); + } +#ifndef USE_NREF + GRN_ATOMIC_ADD_EX(pl, -1, l); +#endif /* USE_NREF */ + vp->done = 1; + GRN_FUTEX_WAKE(&vp->ptr); + } else { + for (ntrial = 0; !vp->ptr; ntrial++) { + if (ntrial >= 1000) { + GRN_LOG(ctx, GRN_LOG_NOTICE, "max trial in ctx_at(%d,%p,%d)!", id, vp->ptr, vp->lock); + break; + } + GRN_FUTEX_WAIT(&vp->ptr); + } + } + if (vp->ptr) { + switch (vp->ptr->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + { + grn_obj *space; + space = ctx->impl->temporary_open_spaces.current; + if (space) { + GRN_PTR_PUT(ctx, space, vp->ptr); + } + } + break; + } + } + } + res = vp->ptr; + if (res && res->header.type == GRN_PROC) { + grn_plugin_ensure_registered(ctx, res); + } + } + } +exit : + GRN_API_RETURN(res); +} + +grn_bool +grn_ctx_is_opened(grn_ctx *ctx, grn_id id) +{ + grn_bool is_opened = GRN_FALSE; + + if (!ctx || !ctx->impl || !id) { + return GRN_FALSE; + } + + GRN_API_ENTER; + if (id & GRN_OBJ_TMP_OBJECT) { + if (ctx->impl->values) { + grn_obj **tmp_obj; + tmp_obj = _grn_array_get_value(ctx, ctx->impl->values, + id & ~GRN_OBJ_TMP_OBJECT); + if (tmp_obj) { + is_opened = GRN_TRUE; + } + } + } else { + grn_db *s = (grn_db *)ctx->impl->db; + if (s) { + db_value *vp; + vp = grn_tiny_array_at(&s->values, id); + if (vp && vp->ptr) { + is_opened = GRN_TRUE; + } + } + } + GRN_API_RETURN(is_opened); +} + +grn_obj * +grn_obj_open(grn_ctx *ctx, unsigned char type, grn_obj_flags flags, grn_id domain) +{ + grn_obj *obj = GRN_MALLOCN(grn_obj, 1); + if (obj) { + GRN_OBJ_INIT(obj, type, flags, domain); + obj->header.impl_flags |= GRN_OBJ_ALLOCATED; + } + return obj; +} + +grn_obj * +grn_obj_graft(grn_ctx *ctx, grn_obj *obj) +{ + grn_obj *new = grn_obj_open(ctx, obj->header.type, obj->header.impl_flags, obj->header.domain); + if (new) { + /* todo : deep copy if (obj->header.impl_flags & GRN_OBJ_DO_SHALLOW_COPY) */ + new->u.b.head = obj->u.b.head; + new->u.b.curr = obj->u.b.curr; + new->u.b.tail = obj->u.b.tail; + obj->u.b.head = NULL; + obj->u.b.curr = NULL; + obj->u.b.tail = NULL; + } + return new; +} + +grn_rc +grn_pvector_fin(grn_ctx *ctx, grn_obj *obj) +{ + grn_rc rc; + if (obj->header.impl_flags & GRN_OBJ_OWN) { + /* + * Note that GRN_OBJ_OWN should not be used outside the DB API function + * because grn_obj_close is a DB API function. + */ + unsigned int i, n_elements; + n_elements = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *); + for (i = 0; i < n_elements; i++) { + grn_obj *element = GRN_PTR_VALUE_AT(obj, n_elements - i - 1); + if (element) { + grn_obj_close(ctx, element); + } + } + } + obj->header.type = GRN_VOID; + rc = grn_bulk_fin(ctx, obj); + if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { + GRN_FREE(obj); + } + return rc; +} + +static void +grn_table_close_columns(grn_ctx *ctx, grn_obj *table) +{ + grn_hash *columns; + int n_columns; + + columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); + if (!columns) { + return; + } + + n_columns = grn_table_columns(ctx, table, "", 0, (grn_obj *)columns); + if (n_columns > 0) { + grn_hash_cursor *cursor; + cursor = grn_hash_cursor_open(ctx, columns, NULL, 0, NULL, 0, 0, -1, 0); + if (cursor) { + while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { + grn_id *id; + grn_obj *column; + + grn_hash_cursor_get_key(ctx, cursor, (void **)&id); + column = grn_ctx_at(ctx, *id); + if (column) { + grn_obj_close(ctx, column); + } + } + grn_hash_cursor_close(ctx, cursor); + } + } + + grn_hash_close(ctx, columns); +} + +grn_rc +grn_obj_close(grn_ctx *ctx, grn_obj *obj) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + GRN_API_ENTER; + if (obj) { + if (grn_obj_is_table(ctx, obj) && + (DB_OBJ(obj)->id & GRN_OBJ_TMP_OBJECT)) { + grn_table_close_columns(ctx, obj); + } + if (GRN_DB_OBJP(obj)) { + grn_hook_entry entry; + if (DB_OBJ(obj)->finalizer) { + DB_OBJ(obj)->finalizer(ctx, 1, &obj, &DB_OBJ(obj)->user_data); + } + if (DB_OBJ(obj)->source) { + GRN_FREE(DB_OBJ(obj)->source); + } + for (entry = 0; entry < N_HOOK_ENTRIES; entry++) { + grn_hook_free(ctx, DB_OBJ(obj)->hooks[entry]); + } + grn_obj_delete_by_id(ctx, DB_OBJ(obj)->db, DB_OBJ(obj)->id, GRN_FALSE); + } + switch (obj->header.type) { + case GRN_VECTOR : + if (obj->u.v.body && !(obj->header.impl_flags & GRN_OBJ_REFER)) { + grn_obj_close(ctx, obj->u.v.body); + } + if (obj->u.v.sections) { GRN_FREE(obj->u.v.sections); } + if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { GRN_FREE(obj); } + rc = GRN_SUCCESS; + break; + case GRN_VOID : + case GRN_BULK : + case GRN_UVECTOR : + case GRN_MSG : + obj->header.type = GRN_VOID; + rc = grn_bulk_fin(ctx, obj); + if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { GRN_FREE(obj); } + break; + case GRN_PTR : + if (obj->header.impl_flags & GRN_OBJ_OWN) { + if (GRN_BULK_VSIZE(obj) == sizeof(grn_obj *)) { + grn_obj_close(ctx, GRN_PTR_VALUE(obj)); + } + } + obj->header.type = GRN_VOID; + rc = grn_bulk_fin(ctx, obj); + if (obj->header.impl_flags & GRN_OBJ_ALLOCATED) { GRN_FREE(obj); } + break; + case GRN_PVECTOR : + rc = grn_pvector_fin(ctx, obj); + break; + case GRN_ACCESSOR : + { + grn_accessor *p, *n; + for (p = (grn_accessor *)obj; p; p = n) { + n = p->next; + GRN_FREE(p); + } + } + rc = GRN_SUCCESS; + break; + case GRN_SNIP : + rc = grn_snip_close(ctx, (grn_snip *)obj); + break; + case GRN_STRING : + rc = grn_string_close(ctx, obj); + break; + case GRN_CURSOR_TABLE_PAT_KEY : + grn_pat_cursor_close(ctx, (grn_pat_cursor *)obj); + break; + case GRN_CURSOR_TABLE_DAT_KEY : + grn_dat_cursor_close(ctx, (grn_dat_cursor *)obj); + break; + case GRN_CURSOR_TABLE_HASH_KEY : + grn_hash_cursor_close(ctx, (grn_hash_cursor *)obj); + break; + case GRN_CURSOR_TABLE_NO_KEY : + grn_array_cursor_close(ctx, (grn_array_cursor *)obj); + break; + case GRN_CURSOR_COLUMN_INDEX : + { + grn_index_cursor *ic = (grn_index_cursor *)obj; + if (ic->iic) { grn_ii_cursor_close(ctx, ic->iic); } + GRN_FREE(ic); + } + break; + case GRN_CURSOR_COLUMN_GEO_INDEX : + grn_geo_cursor_close(ctx, obj); + break; + case GRN_CURSOR_CONFIG : + grn_config_cursor_close(ctx, (grn_config_cursor *)obj); + break; + case GRN_TYPE : + GRN_FREE(obj); + rc = GRN_SUCCESS; + break; + case GRN_DB : + rc = grn_db_close(ctx, obj); + break; + case GRN_TABLE_PAT_KEY : + rc = grn_pat_close(ctx, (grn_pat *)obj); + break; + case GRN_TABLE_DAT_KEY : + rc = grn_dat_close(ctx, (grn_dat *)obj); + break; + case GRN_TABLE_HASH_KEY : + rc = grn_hash_close(ctx, (grn_hash *)obj); + break; + case GRN_TABLE_NO_KEY : + rc = grn_array_close(ctx, (grn_array *)obj); + break; + case GRN_COLUMN_VAR_SIZE : + rc = grn_ja_close(ctx, (grn_ja *)obj); + break; + case GRN_COLUMN_FIX_SIZE : + rc = grn_ra_close(ctx, (grn_ra *)obj); + break; + case GRN_COLUMN_INDEX : + rc = grn_ii_close(ctx, (grn_ii *)obj); + break; + case GRN_PROC : + { + uint32_t i; + grn_proc *p = (grn_proc *)obj; + /* + if (obj->header.domain) { + grn_hash_delete(ctx, ctx->impl->qe, &obj->header.domain, sizeof(grn_id), NULL); + } + */ + for (i = 0; i < p->nvars; i++) { + grn_obj_close(ctx, &p->vars[i].value); + } + GRN_REALLOC(p->vars, 0); + grn_obj_close(ctx, &p->name_buf); + if (p->obj.range != GRN_ID_NIL) { + grn_plugin_close(ctx, p->obj.range); + } + GRN_FREE(obj); + rc = GRN_SUCCESS; + } + break; + case GRN_EXPR : + rc = grn_expr_close(ctx, obj); + break; + } + } + GRN_API_RETURN(rc); +} + +void +grn_obj_unlink(grn_ctx *ctx, grn_obj *obj) +{ + if (obj && + (!GRN_DB_OBJP(obj) || + (((grn_db_obj *)obj)->id & GRN_OBJ_TMP_OBJECT) || + (((grn_db_obj *)obj)->id == GRN_ID_NIL) || + obj->header.type == GRN_DB)) { + grn_obj_close(ctx, obj); + } else if (GRN_DB_OBJP(obj)) { +#ifdef USE_NREF + grn_db_obj *dob = DB_OBJ(obj); + grn_db *s = (grn_db *)dob->db; + db_value *vp = grn_tiny_array_at(&s->values, dob->id); + if (vp) { + uint32_t l, *pl = &vp->lock; + if (!vp->lock) { + GRN_LOG(ctx, GRN_LOG_ERROR, "invalid unlink(%p,%d)", obj, vp->lock); + return; + } + GRN_ATOMIC_ADD_EX(pl, -1, l); + if (l == 1) { + GRN_ATOMIC_ADD_EX(pl, GRN_IO_MAX_REF, l); + if (l == GRN_IO_MAX_REF) { +#ifdef CALL_FINALIZER + grn_obj_close(ctx, obj); + vp->done = 0; + if (dob->finalizer) { + dob->finalizer(ctx, 1, &obj, &dob->user_data); + dob->finalizer = NULL; + dob->user_data.ptr = NULL; + } +#endif /* CALL_FINALIZER */ + } + GRN_ATOMIC_ADD_EX(pl, -GRN_IO_MAX_REF, l); + GRN_FUTEX_WAKE(pl); + } + } +#endif /* USE_NREF */ + } +} + +#define VECTOR_CLEAR(ctx,obj) do {\ + if ((obj)->u.v.body && !((obj)->header.impl_flags & GRN_OBJ_REFER)) {\ + grn_obj_close((ctx), (obj)->u.v.body);\ + }\ + if ((obj)->u.v.sections) { GRN_FREE((obj)->u.v.sections); }\ + (obj)->header.impl_flags &= ~GRN_OBJ_DO_SHALLOW_COPY;\ + (obj)->u.b.head = NULL;\ + (obj)->u.b.curr = NULL;\ + (obj)->u.b.tail = NULL;\ +} while (0) + +static void +grn_obj_ensure_vector(grn_ctx *ctx, grn_obj *obj) +{ + if (obj->header.type != GRN_VECTOR) { grn_bulk_fin(ctx, obj); } + obj->header.type = GRN_VECTOR; + obj->header.flags &= ~GRN_OBJ_WITH_WEIGHT; +} + +static void +grn_obj_ensure_bulk(grn_ctx *ctx, grn_obj *obj) +{ + if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } + obj->header.type = GRN_BULK; + obj->header.flags &= ~GRN_OBJ_WITH_WEIGHT; +} + +grn_rc +grn_obj_reinit(grn_ctx *ctx, grn_obj *obj, grn_id domain, unsigned char flags) +{ + if (!GRN_OBJ_MUTABLE(obj)) { + ERR(GRN_INVALID_ARGUMENT, "invalid obj assigned"); + } else { + switch (obj->header.type) { + case GRN_PTR : + if (obj->header.impl_flags & GRN_OBJ_OWN) { + if (GRN_BULK_VSIZE(obj) == sizeof(grn_obj *)) { + grn_obj_close(ctx, GRN_PTR_VALUE(obj)); + } + obj->header.impl_flags &= ~GRN_OBJ_OWN; + } + break; + case GRN_PVECTOR : + if (obj->header.impl_flags & GRN_OBJ_OWN) { + unsigned int i, n_elements; + n_elements = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *); + for (i = 0; i < n_elements; i++) { + grn_obj *element = GRN_PTR_VALUE_AT(obj, i); + grn_obj_close(ctx, element); + } + obj->header.impl_flags &= ~GRN_OBJ_OWN; + } + break; + default : + break; + } + + switch (domain) { + case GRN_DB_VOID : + if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } + obj->header.type = GRN_VOID; + obj->header.domain = domain; + GRN_BULK_REWIND(obj); + break; + case GRN_DB_OBJECT : + case GRN_DB_BOOL : + case GRN_DB_INT8 : + case GRN_DB_UINT8 : + case GRN_DB_INT16 : + case GRN_DB_UINT16 : + case GRN_DB_INT32 : + case GRN_DB_UINT32 : + case GRN_DB_INT64 : + case GRN_DB_UINT64 : + case GRN_DB_FLOAT : + case GRN_DB_TIME : + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } + obj->header.type = (flags & GRN_OBJ_VECTOR) ? GRN_UVECTOR : GRN_BULK; + obj->header.domain = domain; + GRN_BULK_REWIND(obj); + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + if (flags & GRN_OBJ_VECTOR) { + if (obj->header.type != GRN_VECTOR) { grn_bulk_fin(ctx, obj); } + obj->header.type = GRN_VECTOR; + if (obj->u.v.body) { + grn_obj_reinit(ctx, obj->u.v.body, domain, 0); + } + obj->u.v.n_sections = 0; + } else { + if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } + obj->header.type = GRN_BULK; + } + obj->header.domain = domain; + GRN_BULK_REWIND(obj); + break; + default : + { + grn_obj *d = grn_ctx_at(ctx, domain); + if (!d) { + ERR(GRN_INVALID_ARGUMENT, "invalid domain assigned"); + } else { + if (d->header.type == GRN_TYPE && (d->header.flags & GRN_OBJ_KEY_VAR_SIZE)) { + if (flags & GRN_OBJ_VECTOR) { + if (obj->header.type != GRN_VECTOR) { grn_bulk_fin(ctx, obj); } + obj->header.type = GRN_VECTOR; + } else { + if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } + obj->header.type = GRN_BULK; + } + } else { + if (obj->header.type == GRN_VECTOR) { VECTOR_CLEAR(ctx, obj); } + obj->header.type = (flags & GRN_OBJ_VECTOR) ? GRN_UVECTOR : GRN_BULK; + } + obj->header.domain = domain; + GRN_BULK_REWIND(obj); + } + } + break; + } + } + return ctx->rc; +} + +grn_rc +grn_obj_reinit_for(grn_ctx *ctx, grn_obj *obj, grn_obj *domain_obj) +{ + grn_id domain = GRN_ID_NIL; + grn_obj_flags flags = 0; + + if (!GRN_DB_OBJP(domain_obj) && domain_obj->header.type != GRN_ACCESSOR) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect_limited(ctx, &inspected, domain_obj); + ERR(GRN_INVALID_ARGUMENT, + "[reinit] invalid domain object: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return ctx->rc; + } + + if (grn_column_is_index(ctx, domain_obj)) { + domain = GRN_DB_UINT32; + } else { + grn_obj_get_range_info(ctx, domain_obj, &domain, &flags); + if (GRN_OBJ_TABLEP(domain_obj) && + domain_obj->header.type != GRN_TABLE_NO_KEY) { + domain = domain_obj->header.domain; + } + } + return grn_obj_reinit(ctx, obj, domain, flags); +} + +const char * +grn_obj_path(grn_ctx *ctx, grn_obj *obj) +{ + grn_io *io; + const char *path = NULL; + GRN_API_ENTER; + if (obj->header.type == GRN_PROC) { + path = grn_plugin_path(ctx, DB_OBJ(obj)->range); + GRN_API_RETURN(path); + } + io = grn_obj_get_io(ctx, obj); + if (io && !(io->flags & GRN_IO_TEMPORARY)) { path = io->path; } + GRN_API_RETURN(path); +} + +int +grn_obj_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size) +{ + int len = 0; + GRN_API_ENTER; + if (GRN_DB_OBJP(obj)) { + if (DB_OBJ(obj)->id) { + grn_db *s = (grn_db *)DB_OBJ(obj)->db; + grn_id id = DB_OBJ(obj)->id; + if (id & GRN_OBJ_TMP_OBJECT) { + if (id & GRN_OBJ_TMP_COLUMN) { + grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN); + len = grn_pat_get_key(ctx, ctx->impl->temporary_columns, + real_id, namebuf, buf_size); + } + } else { + len = grn_table_get_key(ctx, s->keys, id, namebuf, buf_size); + } + } + } + GRN_API_RETURN(len); +} + +int +grn_column_name(grn_ctx *ctx, grn_obj *obj, char *namebuf, int buf_size) +{ + int len = 0; + char buf[GRN_TABLE_MAX_KEY_SIZE]; + if (!obj) { return len; } + GRN_API_ENTER; + if (GRN_DB_OBJP(obj)) { + grn_id id = DB_OBJ(obj)->id; + if (id & GRN_OBJ_TMP_OBJECT) { + if (id & GRN_OBJ_TMP_COLUMN) { + grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN); + len = grn_pat_get_key(ctx, ctx->impl->temporary_columns, + real_id, buf, GRN_TABLE_MAX_KEY_SIZE); + } + } else if (id && id < GRN_ID_MAX) { + grn_db *s = (grn_db *)DB_OBJ(obj)->db; + len = grn_table_get_key(ctx, s->keys, id, buf, GRN_TABLE_MAX_KEY_SIZE); + } + if (len) { + int cl; + char *p = buf, *p0 = p, *pe = p + len; + for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) { + if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; } + } + len = pe - p0; + if (len && len <= buf_size) { + grn_memcpy(namebuf, p0, len); + } + } + } else if (obj->header.type == GRN_ACCESSOR) { + grn_obj name; + grn_accessor *a; + + GRN_TEXT_INIT(&name, 0); + +#define ADD_DELMITER() do { \ + if (GRN_TEXT_LEN(&name) > 0) { \ + GRN_TEXT_PUTC(ctx, &name, GRN_DB_DELIMITER); \ + } \ + } while (GRN_FALSE) + + for (a = (grn_accessor *)obj; a; a = a->next) { + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + ADD_DELMITER(); + GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_ID); + break; + case GRN_ACCESSOR_GET_KEY : + if (!a->next) { + ADD_DELMITER(); + GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_KEY); + } + break; + case GRN_ACCESSOR_GET_VALUE : + if (!a->next) { + ADD_DELMITER(); + GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_VALUE); + } + break; + case GRN_ACCESSOR_GET_SCORE : + ADD_DELMITER(); + GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_SCORE); + break; + case GRN_ACCESSOR_GET_NSUBRECS : + ADD_DELMITER(); + GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_NSUBRECS); + break; + case GRN_ACCESSOR_GET_MAX : + ADD_DELMITER(); + GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_MAX); + break; + case GRN_ACCESSOR_GET_MIN : + ADD_DELMITER(); + GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_MIN); + break; + case GRN_ACCESSOR_GET_SUM : + ADD_DELMITER(); + GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_SUM); + break; + case GRN_ACCESSOR_GET_AVG : + ADD_DELMITER(); + GRN_TEXT_PUTS(ctx, &name, GRN_COLUMN_NAME_AVG); + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + ADD_DELMITER(); + { + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + column_name_size = grn_column_name(ctx, a->obj, + column_name, + GRN_TABLE_MAX_KEY_SIZE); + GRN_TEXT_PUT(ctx, &name, column_name, column_name_size); + } + break; + case GRN_ACCESSOR_GET_DB_OBJ : + case GRN_ACCESSOR_LOOKUP : + case GRN_ACCESSOR_FUNCALL : + break; + } + } +#undef ADD_DELIMITER + + len = GRN_TEXT_LEN(&name); + if (len > 0 && len <= buf_size) { + grn_memcpy(namebuf, GRN_TEXT_VALUE(&name), len); + } + + GRN_OBJ_FIN(ctx, &name); + } + GRN_API_RETURN(len); +} + +grn_rc +grn_column_name_(grn_ctx *ctx, grn_obj *obj, grn_obj *buf) +{ + if (GRN_DB_OBJP(obj)) { + uint32_t len = 0; + const char *p = NULL; + grn_id id = DB_OBJ(obj)->id; + if (id & GRN_OBJ_TMP_OBJECT) { + if (id & GRN_OBJ_TMP_COLUMN) { + grn_id real_id = id & ~(GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN); + p = _grn_pat_key(ctx, ctx->impl->temporary_columns, real_id, &len); + } + } else if (id && id < GRN_ID_MAX) { + grn_db *s = (grn_db *)DB_OBJ(obj)->db; + p = _grn_table_key(ctx, s->keys, id, &len); + } + if (len) { + int cl; + const char *p0 = p, *pe = p + len; + for (; p < pe && (cl = grn_charlen(ctx, p, pe)); p += cl) { + if (*p == GRN_DB_DELIMITER && cl == 1) { p0 = p + cl; } + } + GRN_TEXT_PUT(ctx, buf, p0, pe - p0); + } + } else if (obj->header.type == GRN_ACCESSOR) { + grn_accessor *a; + for (a = (grn_accessor *)obj; a; a = a->next) { + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + GRN_TEXT_PUT(ctx, buf, GRN_COLUMN_NAME_ID, GRN_COLUMN_NAME_ID_LEN); + break; + case GRN_ACCESSOR_GET_KEY : + if (!a->next) { + GRN_TEXT_PUT(ctx, buf, GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_KEY_LEN); + } + break; + case GRN_ACCESSOR_GET_VALUE : + if (!a->next) { + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_VALUE, + GRN_COLUMN_NAME_VALUE_LEN); + } + break; + case GRN_ACCESSOR_GET_SCORE : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_SCORE, + GRN_COLUMN_NAME_SCORE_LEN); + break; + case GRN_ACCESSOR_GET_NSUBRECS : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_NSUBRECS, + GRN_COLUMN_NAME_NSUBRECS_LEN); + break; + case GRN_ACCESSOR_GET_MAX : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_MAX, + GRN_COLUMN_NAME_MAX_LEN); + break; + case GRN_ACCESSOR_GET_MIN : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_MIN, + GRN_COLUMN_NAME_MIN_LEN); + break; + case GRN_ACCESSOR_GET_SUM : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_SUM, + GRN_COLUMN_NAME_SUM_LEN); + break; + case GRN_ACCESSOR_GET_AVG : + GRN_TEXT_PUT(ctx, buf, + GRN_COLUMN_NAME_AVG, + GRN_COLUMN_NAME_AVG_LEN); + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + grn_column_name_(ctx, a->obj, buf); + if (a->next) { GRN_TEXT_PUTC(ctx, buf, '.'); } + break; + case GRN_ACCESSOR_GET_DB_OBJ : + case GRN_ACCESSOR_LOOKUP : + case GRN_ACCESSOR_FUNCALL : + break; + } + } + } + return ctx->rc; +} + +int +grn_obj_expire(grn_ctx *ctx, grn_obj *obj, int threshold) +{ + GRN_API_ENTER; + GRN_API_RETURN(0); +} + +int +grn_obj_check(grn_ctx *ctx, grn_obj *obj) +{ + GRN_API_ENTER; + GRN_API_RETURN(0); +} + +grn_rc +grn_obj_lock(grn_ctx *ctx, grn_obj *obj, grn_id id, int timeout) +{ + grn_rc rc = GRN_SUCCESS; + GRN_API_ENTER; + rc = grn_io_lock(ctx, grn_obj_get_io(ctx, obj), timeout); + if (rc == GRN_SUCCESS && obj && obj->header.type == GRN_COLUMN_INDEX) { + rc = grn_io_lock(ctx, ((grn_ii *)obj)->chunk, timeout); + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_obj_unlock(grn_ctx *ctx, grn_obj *obj, grn_id id) +{ + GRN_API_ENTER; + if (obj && obj->header.type == GRN_COLUMN_INDEX) { + grn_io_unlock(((grn_ii *)obj)->chunk); + } + grn_io_unlock(grn_obj_get_io(ctx, obj)); + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_user_data * +grn_obj_user_data(grn_ctx *ctx, grn_obj *obj) +{ + if (!GRN_DB_OBJP(obj)) { return NULL; } + return &DB_OBJ(obj)->user_data; +} + +grn_rc +grn_obj_set_finalizer(grn_ctx *ctx, grn_obj *obj, grn_proc_func *func) +{ + if (!GRN_DB_OBJP(obj)) { return GRN_INVALID_ARGUMENT; } + DB_OBJ(obj)->finalizer = func; + return GRN_SUCCESS; +} + +grn_rc +grn_obj_clear_lock(grn_ctx *ctx, grn_obj *obj) +{ + GRN_API_ENTER; + switch (obj->header.type) { + case GRN_DB: + { + grn_table_cursor *cur; + if ((cur = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_id id; + while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { + grn_obj *tbl = grn_ctx_at(ctx, id); + if (tbl) { + switch (tbl->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: + case GRN_TABLE_NO_KEY: + grn_obj_clear_lock(ctx, tbl); + break; + } + } else { + if (ctx->rc != GRN_SUCCESS) { + ERRCLR(ctx); + } + } + } + grn_table_cursor_close(ctx, cur); + } + } + grn_io_clear_lock(grn_obj_get_io(ctx, obj)); + { + grn_db *db = (grn_db *)obj; + if (db->specs) { + grn_obj_clear_lock(ctx, (grn_obj *)(db->specs)); + } + } + break; + case GRN_TABLE_NO_KEY : + grn_array_queue_lock_clear(ctx, (grn_array *)obj); + /* fallthru */ + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + { + grn_hash *cols; + if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { + if (grn_table_columns(ctx, obj, "", 0, (grn_obj *)cols)) { + grn_id *key; + GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { + grn_obj *col = grn_ctx_at(ctx, *key); + if (col) { grn_obj_clear_lock(ctx, col); } + }); + } + grn_hash_close(ctx, cols); + } + grn_io_clear_lock(grn_obj_get_io(ctx, obj)); + } + break; + case GRN_COLUMN_FIX_SIZE: + case GRN_COLUMN_VAR_SIZE: + grn_io_clear_lock(grn_obj_get_io(ctx, obj)); + break; + case GRN_COLUMN_INDEX: + grn_io_clear_lock(grn_obj_get_io(ctx, obj)); + if (obj) { + grn_io_clear_lock(((grn_ii *)obj)->chunk); + } + break; + } + GRN_API_RETURN(GRN_SUCCESS); +} + +unsigned int +grn_obj_is_locked(grn_ctx *ctx, grn_obj *obj) +{ + unsigned int res = 0; + GRN_API_ENTER; + res = grn_io_is_locked(grn_obj_get_io(ctx, obj)); + if (obj && obj->header.type == GRN_COLUMN_INDEX) { + res += grn_io_is_locked(((grn_ii *)obj)->chunk); + } + GRN_API_RETURN(res); +} + +grn_rc +grn_obj_flush(grn_ctx *ctx, grn_obj *obj) +{ + grn_rc rc = GRN_SUCCESS; + + GRN_API_ENTER; + + switch (obj->header.type) { + case GRN_DB : + { + grn_db *db = (grn_db *)obj; + rc = grn_obj_flush(ctx, db->keys); + if (rc == GRN_SUCCESS && db->specs) { + rc = grn_obj_flush(ctx, (grn_obj *)(db->specs)); + } + if (rc == GRN_SUCCESS) { + rc = grn_obj_flush(ctx, (grn_obj *)(db->config)); + } + } + break; + case GRN_TABLE_DAT_KEY : + rc = grn_dat_flush(ctx, (grn_dat *)obj); + break; + case GRN_COLUMN_INDEX : + rc = grn_ii_flush(ctx, (grn_ii *)obj); + break; + default : + { + grn_io *io; + io = grn_obj_get_io(ctx, obj); + if (io) { + rc = grn_io_flush(ctx, io); + } + } + break; + } + + if (rc == GRN_SUCCESS && + GRN_DB_OBJP(obj) && + DB_OBJ(obj)->id != GRN_ID_NIL && + !IS_TEMP(obj)) { + rc = grn_db_clean(ctx, DB_OBJ(obj)->db); + } + + GRN_API_RETURN(rc); +} + +grn_rc +grn_obj_flush_recursive(grn_ctx *ctx, grn_obj *obj) +{ + grn_rc rc = GRN_SUCCESS; + + GRN_API_ENTER; + switch (obj->header.type) { + case GRN_DB : + { + grn_table_cursor *cursor; + grn_id id; + + cursor = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + GRN_API_RETURN(ctx->rc); + } + + while ((id = grn_table_cursor_next_inline(ctx, cursor)) != GRN_ID_NIL) { + grn_obj *table = grn_ctx_at(ctx, id); + rc = GRN_SUCCESS; + if (table) { + switch (table->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: + case GRN_TABLE_NO_KEY: + rc = grn_obj_flush_recursive(ctx, table); + break; + } + } else { + if (ctx->rc != GRN_SUCCESS) { + ERRCLR(ctx); + } + } + if (rc != GRN_SUCCESS) { + break; + } + } + grn_table_cursor_close(ctx, cursor); + } + if (rc == GRN_SUCCESS) { + rc = grn_obj_flush(ctx, obj); + } + break; + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + { + grn_hash *columns; + columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); + if (!columns) { + GRN_API_RETURN(ctx->rc); + } + + if (grn_table_columns(ctx, obj, "", 0, (grn_obj *)columns) > 0) { + grn_id *key; + GRN_HASH_EACH(ctx, columns, id, &key, NULL, NULL, { + grn_obj *column = grn_ctx_at(ctx, *key); + if (column) { + rc = grn_obj_flush(ctx, column); + if (rc != GRN_SUCCESS) { + break; + } + } + }); + } + grn_hash_close(ctx, columns); + } + + if (rc == GRN_SUCCESS) { + rc = grn_obj_flush(ctx, obj); + } + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + rc = grn_obj_flush(ctx, obj); + break; + default : + { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, obj); + ERR(GRN_INVALID_ARGUMENT, + "[flush] object must be DB, table or column: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + rc = ctx->rc; + GRN_OBJ_FIN(ctx, &inspected); + } + break; + } + + GRN_API_RETURN(rc); +} + +grn_obj * +grn_obj_db(grn_ctx *ctx, grn_obj *obj) +{ + grn_obj *db = NULL; + GRN_API_ENTER; + if (GRN_DB_OBJP(obj)) { db = DB_OBJ(obj)->db; } + GRN_API_RETURN(db); +} + +grn_id +grn_obj_id(grn_ctx *ctx, grn_obj *obj) +{ + grn_id id = GRN_ID_NIL; + GRN_API_ENTER; + if (GRN_DB_OBJP(obj)) { + id = DB_OBJ(obj)->id; + } + GRN_API_RETURN(id); +} + +int +grn_obj_defrag(grn_ctx *ctx, grn_obj *obj, int threshold) +{ + int r = 0; + GRN_API_ENTER; + switch (obj->header.type) { + case GRN_DB: + { + grn_table_cursor *cur; + if ((cur = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, 0, -1, 0))) { + grn_id id; + while ((id = grn_table_cursor_next_inline(ctx, cur)) != GRN_ID_NIL) { + grn_obj *ja = grn_ctx_at(ctx, id); + if (ja && ja->header.type == GRN_COLUMN_VAR_SIZE) { + r += grn_ja_defrag(ctx, (grn_ja *)ja, threshold); + } + } + grn_table_cursor_close(ctx, cur); + } + } + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + { + grn_hash *cols; + if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { + if (grn_table_columns(ctx, obj, "", 0, (grn_obj *)cols)) { + grn_id *key; + GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { + grn_obj *col = grn_ctx_at(ctx, *key); + if (col) { + r += grn_obj_defrag(ctx, col, threshold); + grn_obj_unlink(ctx, col); + } + }); + } + grn_hash_close(ctx, cols); + } + } + break; + case GRN_COLUMN_VAR_SIZE: + r = grn_ja_defrag(ctx, (grn_ja *)obj, threshold); + break; + } + GRN_API_RETURN(r); +} + +/**** sort ****/ + +typedef struct { + grn_id id; + uint32_t size; + const void *value; +} sort_reference_entry; + +enum { + KEY_ID = 0, + KEY_BULK, + KEY_INT8, + KEY_INT16, + KEY_INT32, + KEY_INT64, + KEY_UINT8, + KEY_UINT16, + KEY_UINT32, + KEY_UINT64, + KEY_FLOAT32, + KEY_FLOAT64, +}; + +#define CMPNUM(type) do {\ + if (as) {\ + if (bs) {\ + type va = *((type *)(ap));\ + type vb = *((type *)(bp));\ + if (va != vb) { return va > vb; }\ + } else {\ + return 1;\ + }\ + } else {\ + if (bs) { return 0; }\ + }\ +} while (0) + +inline static int +compare_reference(grn_ctx *ctx, + sort_reference_entry *a, sort_reference_entry *b, + grn_table_sort_key *keys, int n_keys) +{ + int i; + uint8_t type; + uint32_t as, bs; + const unsigned char *ap, *bp; + for (i = 0; i < n_keys; i++, keys++) { + if (i) { + const char *ap_raw, *bp_raw; + if (keys->flags & GRN_TABLE_SORT_DESC) { + ap_raw = grn_obj_get_value_(ctx, keys->key, b->id, &as); + bp_raw = grn_obj_get_value_(ctx, keys->key, a->id, &bs); + } else { + ap_raw = grn_obj_get_value_(ctx, keys->key, a->id, &as); + bp_raw = grn_obj_get_value_(ctx, keys->key, b->id, &bs); + } + ap = (const unsigned char *)ap_raw; + bp = (const unsigned char *)bp_raw; + } else { + if (keys->flags & GRN_TABLE_SORT_DESC) { + ap = b->value; as = b->size; + bp = a->value; bs = a->size; + } else { + ap = a->value; as = a->size; + bp = b->value; bs = b->size; + } + } + type = keys->offset; + switch (type) { + case KEY_ID : + if (ap != bp) { return ap > bp; } + break; + case KEY_BULK : + for (;; ap++, bp++, as--, bs--) { + if (!as) { if (bs) { return 0; } else { break; } } + if (!bs) { return 1; } + if (*ap < *bp) { return 0; } + if (*ap > *bp) { return 1; } + } + break; + case KEY_INT8 : + CMPNUM(int8_t); + break; + case KEY_INT16 : + CMPNUM(int16_t); + break; + case KEY_INT32 : + CMPNUM(int32_t); + break; + case KEY_INT64 : + CMPNUM(int64_t); + break; + case KEY_UINT8 : + CMPNUM(uint8_t); + break; + case KEY_UINT16 : + CMPNUM(uint16_t); + break; + case KEY_UINT32 : + CMPNUM(uint32_t); + break; + case KEY_UINT64 : + CMPNUM(uint64_t); + break; + case KEY_FLOAT32 : + if (as) { + if (bs) { + float va = *((float *)(ap)); + float vb = *((float *)(bp)); + if (va < vb || va > vb) { return va > vb; } + } else { + return 1; + } + } else { + if (bs) { return 0; } + } + break; + case KEY_FLOAT64 : + if (as) { + if (bs) { + double va = *((double *)(ap)); + double vb = *((double *)(bp)); + if (va < vb || va > vb) { return va > vb; } + } else { + return 1; + } + } else { + if (bs) { return 0; } + } + break; + } + } + return 0; +} + +inline static void +swap_reference(sort_reference_entry *a, sort_reference_entry *b) +{ + sort_reference_entry c_ = *a; + *a = *b; + *b = c_; +} + +inline static sort_reference_entry * +part_reference(grn_ctx *ctx, + sort_reference_entry *b, sort_reference_entry *e, + grn_table_sort_key *keys, int n_keys) +{ + sort_reference_entry *c; + intptr_t d = e - b; + if (compare_reference(ctx, b, e, keys, n_keys)) { + swap_reference(b, e); + } + if (d < 2) { return NULL; } + c = b + (d >> 1); + if (compare_reference(ctx, b, c, keys, n_keys)) { + swap_reference(b, c); + } else { + if (compare_reference(ctx, c, e, keys, n_keys)) { + swap_reference(c, e); + } + } + if (d < 3) { return NULL; } + b++; + swap_reference(b, c); + c = b; + for (;;) { + do { + b++; + } while (compare_reference(ctx, c, b, keys, n_keys)); + do { + e--; + } while (compare_reference(ctx, e, c, keys, n_keys)); + if (b >= e) { break; } + swap_reference(b, e); + } + swap_reference(c, e); + return e; +} + +static void +sort_reference(grn_ctx *ctx, + sort_reference_entry *head, sort_reference_entry *tail, + int from, int to, + grn_table_sort_key *keys, int n_keys) +{ + sort_reference_entry *c; + if (head < tail && (c = part_reference(ctx, head, tail, keys, n_keys))) { + intptr_t m = c - head + 1; + if (from < m - 1) { + sort_reference(ctx, head, c - 1, from, to, keys, n_keys); + } + if (m < to) { + sort_reference(ctx, c + 1, tail, from - m, to - m, keys, n_keys); + } + } +} + +static sort_reference_entry * +pack_reference(grn_ctx *ctx, grn_obj *table, + sort_reference_entry *head, sort_reference_entry *tail, + grn_table_sort_key *keys, int n_keys) +{ + int i = 0; + sort_reference_entry e, c; + grn_table_cursor *tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); + if (!tc) { return NULL; } + if ((c.id = grn_table_cursor_next_inline(ctx, tc))) { + c.value = grn_obj_get_value_(ctx, keys->key, c.id, &c.size); + while ((e.id = grn_table_cursor_next_inline(ctx, tc))) { + e.value = grn_obj_get_value_(ctx, keys->key, e.id, &e.size); + if (compare_reference(ctx, &c, &e, keys, n_keys)) { + *head++ = e; + } else { + *tail-- = e; + } + i++; + } + *head = c; + i++; + } + grn_table_cursor_close(ctx, tc); + return i > 2 ? head : NULL; +} + +static int +grn_table_sort_reference(grn_ctx *ctx, grn_obj *table, + int offset, int limit, + grn_obj *result, + grn_table_sort_key *keys, int n_keys) +{ + int e, n; + sort_reference_entry *array, *ep; + e = offset + limit; + n = grn_table_size(ctx, table); + if (!(array = GRN_MALLOC(sizeof(sort_reference_entry) * n))) { + return 0; + } + if ((ep = pack_reference(ctx, table, array, array + n - 1, keys, n_keys))) { + intptr_t m = ep - array + 1; + if (offset < m - 1) { + sort_reference(ctx, array, ep - 1, offset, e, keys, n_keys); + } + if (m < e) { + sort_reference(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys); + } + } + { + int i; + grn_id *v; + for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) { + if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } + *v = ep->id; + } + GRN_FREE(array); + return i; + } +} + + +typedef struct { + grn_id id; + grn_obj value; +} sort_value_entry; + +inline static int +compare_value(grn_ctx *ctx, + sort_value_entry *a, sort_value_entry *b, + grn_table_sort_key *keys, int n_keys, + grn_obj *a_buffer, grn_obj *b_buffer) +{ + int i; + uint8_t type; + uint32_t as, bs; + const unsigned char *ap, *bp; + for (i = 0; i < n_keys; i++, keys++) { + if (i) { + GRN_BULK_REWIND(a_buffer); + GRN_BULK_REWIND(b_buffer); + if (keys->flags & GRN_TABLE_SORT_DESC) { + grn_obj_get_value(ctx, keys->key, b->id, a_buffer); + grn_obj_get_value(ctx, keys->key, a->id, b_buffer); + } else { + grn_obj_get_value(ctx, keys->key, a->id, a_buffer); + grn_obj_get_value(ctx, keys->key, b->id, b_buffer); + } + ap = (const unsigned char *)GRN_BULK_HEAD(a_buffer); + as = GRN_BULK_VSIZE(a_buffer); + bp = (const unsigned char *)GRN_BULK_HEAD(b_buffer); + bs = GRN_BULK_VSIZE(b_buffer); + } else { + if (keys->flags & GRN_TABLE_SORT_DESC) { + ap = (const unsigned char *)GRN_BULK_HEAD(&b->value); + as = GRN_BULK_VSIZE(&b->value); + bp = (const unsigned char *)GRN_BULK_HEAD(&a->value); + bs = GRN_BULK_VSIZE(&a->value); + } else { + ap = (const unsigned char *)GRN_BULK_HEAD(&a->value); + as = GRN_BULK_VSIZE(&a->value); + bp = (const unsigned char *)GRN_BULK_HEAD(&b->value); + bs = GRN_BULK_VSIZE(&b->value); + } + } + type = keys->offset; + switch (type) { + case KEY_ID : + if (ap != bp) { return ap > bp; } + break; + case KEY_BULK : + for (;; ap++, bp++, as--, bs--) { + if (!as) { if (bs) { return 0; } else { break; } } + if (!bs) { return 1; } + if (*ap < *bp) { return 0; } + if (*ap > *bp) { return 1; } + } + break; + case KEY_INT8 : + CMPNUM(int8_t); + break; + case KEY_INT16 : + CMPNUM(int16_t); + break; + case KEY_INT32 : + CMPNUM(int32_t); + break; + case KEY_INT64 : + CMPNUM(int64_t); + break; + case KEY_UINT8 : + CMPNUM(uint8_t); + break; + case KEY_UINT16 : + CMPNUM(uint16_t); + break; + case KEY_UINT32 : + CMPNUM(uint32_t); + break; + case KEY_UINT64 : + CMPNUM(uint64_t); + break; + case KEY_FLOAT32 : + if (as) { + if (bs) { + float va = *((float *)(ap)); + float vb = *((float *)(bp)); + if (va < vb || va > vb) { return va > vb; } + } else { + return 1; + } + } else { + if (bs) { return 0; } + } + break; + case KEY_FLOAT64 : + if (as) { + if (bs) { + double va = *((double *)(ap)); + double vb = *((double *)(bp)); + if (va < vb || va > vb) { return va > vb; } + } else { + return 1; + } + } else { + if (bs) { return 0; } + } + break; + } + } + return 0; +} + +inline static void +swap_value(sort_value_entry *a, sort_value_entry *b) +{ + sort_value_entry c_ = *a; + *a = *b; + *b = c_; +} + +inline static sort_value_entry * +part_value(grn_ctx *ctx, + sort_value_entry *b, sort_value_entry *e, + grn_table_sort_key *keys, int n_keys, + grn_obj *a_buffer, grn_obj *b_buffer) +{ + sort_value_entry *c; + intptr_t d = e - b; + if (compare_value(ctx, b, e, keys, n_keys, a_buffer, b_buffer)) { + swap_value(b, e); + } + if (d < 2) { return NULL; } + c = b + (d >> 1); + if (compare_value(ctx, b, c, keys, n_keys, a_buffer, b_buffer)) { + swap_value(b, c); + } else { + if (compare_value(ctx, c, e, keys, n_keys, a_buffer, b_buffer)) { + swap_value(c, e); + } + } + if (d < 3) { return NULL; } + b++; + swap_value(b, c); + c = b; + for (;;) { + do { + b++; + } while (compare_value(ctx, c, b, keys, n_keys, a_buffer, b_buffer)); + do { + e--; + } while (compare_value(ctx, e, c, keys, n_keys, a_buffer, b_buffer)); + if (b >= e) { break; } + swap_value(b, e); + } + swap_value(c, e); + return e; +} + +static void +sort_value(grn_ctx *ctx, + sort_value_entry *head, sort_value_entry *tail, + int from, int to, + grn_table_sort_key *keys, int n_keys, + grn_obj *a_buffer, grn_obj *b_buffer) +{ + sort_value_entry *c; + if (head < tail && (c = part_value(ctx, head, tail, keys, n_keys, + a_buffer, b_buffer))) { + intptr_t m = c - head + 1; + if (from < m - 1) { + sort_value(ctx, head, c - 1, from, to, keys, n_keys, a_buffer, b_buffer); + } + if (m < to) { + sort_value(ctx, c + 1, tail, from - m, to - m, keys, n_keys, + a_buffer, b_buffer); + } + } +} + +static sort_value_entry * +pack_value(grn_ctx *ctx, grn_obj *table, + sort_value_entry *head, sort_value_entry *tail, + grn_table_sort_key *keys, int n_keys, + grn_obj *a_buffer, grn_obj *b_buffer) +{ + int i = 0; + sort_value_entry e, c; + grn_table_cursor *tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0); + if (!tc) { return NULL; } + if ((c.id = grn_table_cursor_next_inline(ctx, tc))) { + GRN_TEXT_INIT(&c.value, 0); + grn_obj_get_value(ctx, keys->key, c.id, &c.value); + while ((e.id = grn_table_cursor_next_inline(ctx, tc))) { + GRN_TEXT_INIT(&e.value, 0); + grn_obj_get_value(ctx, keys->key, e.id, &e.value); + if (compare_value(ctx, &c, &e, keys, n_keys, a_buffer, b_buffer)) { + *head++ = e; + } else { + *tail-- = e; + } + i++; + } + *head = c; + i++; + } + grn_table_cursor_close(ctx, tc); + return i > 2 ? head : NULL; +} + +static int +grn_table_sort_value(grn_ctx *ctx, grn_obj *table, + int offset, int limit, + grn_obj *result, + grn_table_sort_key *keys, int n_keys) +{ + int e, n; + sort_value_entry *array, *ep; + e = offset + limit; + n = grn_table_size(ctx, table); + if (!(array = GRN_MALLOC(sizeof(sort_value_entry) * n))) { + return 0; + } + { + grn_obj a_buffer; + grn_obj b_buffer; + GRN_TEXT_INIT(&a_buffer, 0); + GRN_TEXT_INIT(&b_buffer, 0); + if ((ep = pack_value(ctx, table, array, array + n - 1, keys, n_keys, + &a_buffer, &b_buffer))) { + intptr_t m = ep - array + 1; + if (offset < m - 1) { + sort_value(ctx, array, ep - 1, offset, e, keys, n_keys, + &a_buffer, &b_buffer); + } + if (m < e) { + sort_value(ctx, ep + 1, array + n - 1, offset - m, e - m, keys, n_keys, + &a_buffer, &b_buffer); + } + } + GRN_OBJ_FIN(ctx, &a_buffer); + GRN_OBJ_FIN(ctx, &b_buffer); + } + { + int i; + grn_id *v; + for (i = 0, ep = array + offset; i < limit && ep < array + n; i++, ep++) { + if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } + *v = ep->id; + } + GRN_FREE(array); + return i; + } +} + +static grn_bool +is_compressed_column(grn_ctx *ctx, grn_obj *obj) +{ + grn_obj *target_obj; + + if (!obj) { + return GRN_FALSE; + } + + if (obj->header.type == GRN_ACCESSOR) { + grn_accessor *a = (grn_accessor *)obj; + while (a->next) { + a = a->next; + } + target_obj = a->obj; + } else { + target_obj = obj; + } + + if (target_obj->header.type != GRN_COLUMN_VAR_SIZE) { + return GRN_FALSE; + } + + switch (target_obj->header.flags & GRN_OBJ_COMPRESS_MASK) { + case GRN_OBJ_COMPRESS_ZLIB : + case GRN_OBJ_COMPRESS_LZ4 : + case GRN_OBJ_COMPRESS_ZSTD : + return GRN_TRUE; + default : + return GRN_FALSE; + } +} + +static grn_bool +is_sub_record_accessor(grn_ctx *ctx, grn_obj *obj) +{ + grn_accessor *accessor; + + if (!obj) { + return GRN_FALSE; + } + + if (obj->header.type != GRN_ACCESSOR) { + return GRN_FALSE; + } + + for (accessor = (grn_accessor *)obj; accessor; accessor = accessor->next) { + switch (accessor->action) { + case GRN_ACCESSOR_GET_VALUE : + if (GRN_TABLE_IS_MULTI_KEYS_GROUPED(accessor->obj)) { + return GRN_TRUE; + } + break; + default : + break; + } + } + + return GRN_FALSE; +} + +static grn_bool +is_encoded_pat_key_accessor(grn_ctx *ctx, grn_obj *obj) +{ + grn_accessor *accessor; + + if (!grn_obj_is_accessor(ctx, obj)) { + return GRN_FALSE; + } + + accessor = (grn_accessor *)obj; + while (accessor->next) { + accessor = accessor->next; + } + + if (accessor->action != GRN_ACCESSOR_GET_KEY) { + return GRN_FALSE; + } + + if (accessor->obj->header.type != GRN_TABLE_PAT_KEY) { + return GRN_FALSE; + } + + return grn_pat_is_key_encoded(ctx, (grn_pat *)(accessor->obj)); +} + +static int +range_is_idp(grn_obj *obj) +{ + if (obj && obj->header.type == GRN_ACCESSOR) { + grn_accessor *a; + for (a = (grn_accessor *)obj; a; a = a->next) { + if (a->action == GRN_ACCESSOR_GET_ID) { return 1; } + } + } + return 0; +} + +int +grn_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit, + grn_obj *result, grn_table_sort_key *keys, int n_keys) +{ + grn_rc rc; + grn_obj *index; + int n, e, i = 0; + GRN_API_ENTER; + if (!n_keys || !keys) { + WARN(GRN_INVALID_ARGUMENT, "keys is null"); + goto exit; + } + if (!table) { + WARN(GRN_INVALID_ARGUMENT, "table is null"); + goto exit; + } + if (!(result && result->header.type == GRN_TABLE_NO_KEY)) { + WARN(GRN_INVALID_ARGUMENT, "result is not a array"); + goto exit; + } + n = grn_table_size(ctx, table); + if ((rc = grn_normalize_offset_and_limit(ctx, n, &offset, &limit))) { + ERR(rc, "grn_normalize_offset_and_limit failed"); + goto exit; + } else { + e = offset + limit; + } + if (keys->flags & GRN_TABLE_SORT_GEO) { + if (n_keys == 2) { + i = grn_geo_table_sort(ctx, table, offset, limit, result, + keys[0].key, keys[1].key); + } else { + i = 0; + } + goto exit; + } + if (n_keys == 1 && !GRN_ACCESSORP(keys->key) && + grn_column_index(ctx, keys->key, GRN_OP_LESS, &index, 1, NULL)) { + grn_id tid; + grn_pat *lexicon = (grn_pat *)grn_ctx_at(ctx, index->header.domain); + grn_pat_cursor *pc = grn_pat_cursor_open(ctx, lexicon, NULL, 0, NULL, 0, + 0 /* offset : can be used in unique index */, + -1 /* limit : can be used in unique index */, + (keys->flags & GRN_TABLE_SORT_DESC) + ? GRN_CURSOR_DESCENDING + : GRN_CURSOR_ASCENDING); + if (pc) { + while (i < e && (tid = grn_pat_cursor_next(ctx, pc))) { + grn_ii_cursor *ic = grn_ii_cursor_open(ctx, (grn_ii *)index, tid, 0, 0, 1, 0); + if (ic) { + grn_posting *posting; + while (i < e && (posting = grn_ii_cursor_next(ctx, ic))) { + if (offset <= i) { + grn_id *v; + if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } + *v = posting->rid; + } + i++; + } + grn_ii_cursor_close(ctx, ic); + } + } + grn_pat_cursor_close(ctx, pc); + } + } else { + int j; + grn_bool have_compressed_column = GRN_FALSE; + grn_bool have_sub_record_accessor = GRN_FALSE; + grn_bool have_encoded_pat_key_accessor = GRN_FALSE; + grn_bool have_index_value_get = GRN_FALSE; + grn_table_sort_key *kp; + for (kp = keys, j = n_keys; j; kp++, j--) { + if (is_compressed_column(ctx, kp->key)) { + have_compressed_column = GRN_TRUE; + } + if (is_sub_record_accessor(ctx, kp->key)) { + have_sub_record_accessor = GRN_TRUE; + } + if (is_encoded_pat_key_accessor(ctx, kp->key)) { + have_encoded_pat_key_accessor = GRN_TRUE; + } + if (range_is_idp(kp->key)) { + kp->offset = KEY_ID; + } else { + grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, kp->key)); + if (range->header.type == GRN_TYPE) { + if (range->header.flags & GRN_OBJ_KEY_VAR_SIZE) { + kp->offset = KEY_BULK; + } else { + uint8_t key_type = range->header.flags & GRN_OBJ_KEY_MASK; + switch (key_type) { + case GRN_OBJ_KEY_UINT : + case GRN_OBJ_KEY_GEO_POINT : + switch (GRN_TYPE_SIZE(DB_OBJ(range))) { + case 1 : + kp->offset = KEY_UINT8; + break; + case 2 : + kp->offset = KEY_UINT16; + break; + case 4 : + kp->offset = KEY_UINT32; + break; + case 8 : + kp->offset = KEY_UINT64; + break; + default : + ERR(GRN_INVALID_ARGUMENT, "unsupported uint value"); + goto exit; + } + break; + case GRN_OBJ_KEY_INT : + switch (GRN_TYPE_SIZE(DB_OBJ(range))) { + case 1 : + kp->offset = KEY_INT8; + break; + case 2 : + kp->offset = KEY_INT16; + break; + case 4 : + kp->offset = KEY_INT32; + break; + case 8 : + kp->offset = KEY_INT64; + break; + default : + ERR(GRN_INVALID_ARGUMENT, "unsupported int value"); + goto exit; + } + break; + case GRN_OBJ_KEY_FLOAT : + switch (GRN_TYPE_SIZE(DB_OBJ(range))) { + case 4 : + kp->offset = KEY_FLOAT32; + break; + case 8 : + kp->offset = KEY_FLOAT64; + break; + default : + ERR(GRN_INVALID_ARGUMENT, "unsupported float value"); + goto exit; + } + break; + } + } + } else { + if (kp->key->header.type == GRN_COLUMN_INDEX) { + have_index_value_get = GRN_TRUE; + } + kp->offset = KEY_UINT32; + } + } + } + if (have_compressed_column || + have_sub_record_accessor || + have_encoded_pat_key_accessor || + have_index_value_get) { + i = grn_table_sort_value(ctx, table, offset, limit, result, + keys, n_keys); + } else { + i = grn_table_sort_reference(ctx, table, offset, limit, result, + keys, n_keys); + } + } +exit : + GRN_API_RETURN(i); +} + +static grn_obj * +deftype(grn_ctx *ctx, const char *name, + grn_obj_flags flags, unsigned int size) +{ + grn_obj *o = grn_ctx_get(ctx, name, strlen(name)); + if (!o) { o = grn_type_create(ctx, name, strlen(name), flags, size); } + return o; +} + +grn_rc +grn_db_init_builtin_types(grn_ctx *ctx) +{ + grn_id id; + grn_obj *obj, *db = ctx->impl->db; + char buf[] = "Sys00"; + grn_obj_register(ctx, db, buf, 5); + obj = deftype(ctx, "Object", + GRN_OBJ_KEY_UINT, sizeof(uint64_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_OBJECT) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "Bool", + GRN_OBJ_KEY_UINT, sizeof(uint8_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_BOOL) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "Int8", + GRN_OBJ_KEY_INT, sizeof(int8_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_INT8) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "UInt8", + GRN_OBJ_KEY_UINT, sizeof(uint8_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_UINT8) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "Int16", + GRN_OBJ_KEY_INT, sizeof(int16_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_INT16) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "UInt16", + GRN_OBJ_KEY_UINT, sizeof(uint16_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_UINT16) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "Int32", + GRN_OBJ_KEY_INT, sizeof(int32_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_INT32) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "UInt32", + GRN_OBJ_KEY_UINT, sizeof(uint32_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_UINT32) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "Int64", + GRN_OBJ_KEY_INT, sizeof(int64_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_INT64) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "UInt64", + GRN_OBJ_KEY_UINT, sizeof(uint64_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_UINT64) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "Float", + GRN_OBJ_KEY_FLOAT, sizeof(double)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_FLOAT) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "Time", + GRN_OBJ_KEY_INT, sizeof(int64_t)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_TIME) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "ShortText", + GRN_OBJ_KEY_VAR_SIZE, GRN_TABLE_MAX_KEY_SIZE); + if (!obj || DB_OBJ(obj)->id != GRN_DB_SHORT_TEXT) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "Text", + GRN_OBJ_KEY_VAR_SIZE, 1 << 16); + if (!obj || DB_OBJ(obj)->id != GRN_DB_TEXT) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "LongText", + GRN_OBJ_KEY_VAR_SIZE, 1U << 31); + if (!obj || DB_OBJ(obj)->id != GRN_DB_LONG_TEXT) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "TokyoGeoPoint", + GRN_OBJ_KEY_GEO_POINT, sizeof(grn_geo_point)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_TOKYO_GEO_POINT) { return GRN_FILE_CORRUPT; } + obj = deftype(ctx, "WGS84GeoPoint", + GRN_OBJ_KEY_GEO_POINT, sizeof(grn_geo_point)); + if (!obj || DB_OBJ(obj)->id != GRN_DB_WGS84_GEO_POINT) { return GRN_FILE_CORRUPT; } + for (id = grn_db_curr_id(ctx, db) + 1; id < GRN_DB_MECAB; id++) { + grn_itoh(id, buf + 3, 2); + grn_obj_register(ctx, db, buf, 5); + } +#ifdef GRN_WITH_MECAB + if (grn_db_init_mecab_tokenizer(ctx)) { + ERRCLR(ctx); +#endif + grn_obj_register(ctx, db, "TokenMecab", 10); +#ifdef GRN_WITH_MECAB + } +#endif + grn_db_init_builtin_tokenizers(ctx); + grn_db_init_builtin_normalizers(ctx); + grn_db_init_builtin_scorers(ctx); + for (id = grn_db_curr_id(ctx, db) + 1; id < 128; id++) { + grn_itoh(id, buf + 3, 2); + grn_obj_register(ctx, db, buf, 5); + } + grn_db_init_builtin_commands(ctx); + grn_db_init_builtin_window_functions(ctx); + for (id = grn_db_curr_id(ctx, db) + 1; id < GRN_N_RESERVED_TYPES; id++) { + grn_itoh(id, buf + 3, 2); + grn_obj_register(ctx, db, buf, 5); + } + return ctx->rc; +} + +#define MULTI_COLUMN_INDEXP(i) (DB_OBJ(i)->source_size > sizeof(grn_id)) + +static grn_obj * +grn_index_column_get_tokenizer(grn_ctx *ctx, grn_obj *index_column) +{ + grn_obj *tokenizer; + grn_obj *lexicon; + + lexicon = grn_ctx_at(ctx, index_column->header.domain); + if (!lexicon) { + return NULL; + } + + grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL); + return tokenizer; +} + +static grn_bool +is_full_text_searchable_index(grn_ctx *ctx, grn_obj *index_column) +{ + grn_obj *tokenizer; + + tokenizer = grn_index_column_get_tokenizer(ctx, index_column); + return tokenizer != NULL; +} + +static int +grn_column_find_index_data_column_equal(grn_ctx *ctx, grn_obj *obj, + grn_operator op, + grn_index_datum *index_data, + unsigned int n_index_data, + grn_obj **index_buf, int buf_size, + int *section_buf) +{ + int n = 0; + grn_obj **ip = index_buf; + grn_hook *hooks; + + for (hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + int section; + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + if (obj->header.type != GRN_COLUMN_FIX_SIZE) { + if (is_full_text_searchable_index(ctx, target)) { continue; } + } + section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; + if (section_buf) { *section_buf = section; } + if (n < buf_size) { + *ip++ = target; + } + if ((unsigned int) n < n_index_data) { + index_data[n].index = target; + index_data[n].section = section; + } + n++; + } + + return n; +} + +static grn_bool +is_valid_regexp_index(grn_ctx *ctx, grn_obj *index_column) +{ + grn_obj *tokenizer; + + tokenizer = grn_index_column_get_tokenizer(ctx, index_column); + /* TODO: Restrict to TokenRegexp? */ + return tokenizer != NULL; +} + +static int +grn_column_find_index_data_column_match(grn_ctx *ctx, grn_obj *obj, + grn_operator op, + grn_index_datum *index_data, + unsigned int n_index_data, + grn_obj **index_buf, int buf_size, + int *section_buf) +{ + int n = 0; + grn_obj **ip = index_buf; + grn_hook_entry hook_entry; + grn_hook *hooks; + grn_bool prefer_full_text_search_index = GRN_FALSE; + + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + hook_entry = GRN_HOOK_INSERT; + break; + default : + hook_entry = GRN_HOOK_SET; + break; + } + + if (op != GRN_OP_REGEXP && !grn_column_is_vector(ctx, obj)) { + prefer_full_text_search_index = GRN_TRUE; + } + + if (prefer_full_text_search_index) { + for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + int section; + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + if (!is_full_text_searchable_index(ctx, target)) { continue; } + section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; + if (section_buf) { *section_buf = section; } + if (n < buf_size) { + *ip++ = target; + } + if ((unsigned int) n < n_index_data) { + index_data[n].index = target; + index_data[n].section = section; + } + n++; + } + } + + for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + int section; + + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + if (op == GRN_OP_REGEXP && !is_valid_regexp_index(ctx, target)) { + continue; + } + + if (prefer_full_text_search_index) { + if (is_full_text_searchable_index(ctx, target)) { continue; } + } + + section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; + if (section_buf) { *section_buf = section; } + if (n < buf_size) { + *ip++ = target; + } + if ((unsigned int) n < n_index_data) { + index_data[n].index = target; + index_data[n].section = section; + } + n++; + } + + return n; +} + +static int +grn_column_find_index_data_column_range(grn_ctx *ctx, grn_obj *obj, + grn_operator op, + grn_index_datum *index_data, + unsigned int n_index_data, + grn_obj **index_buf, int buf_size, + int *section_buf) +{ + int n = 0; + grn_obj **ip = index_buf; + grn_hook_entry hook_entry; + grn_hook *hooks; + + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + hook_entry = GRN_HOOK_INSERT; + break; + default : + hook_entry = GRN_HOOK_SET; + break; + } + + for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + int section; + if (!target) { continue; } + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; + if (section_buf) { *section_buf = section; } + { + grn_obj *tokenizer, *lexicon = grn_ctx_at(ctx, target->header.domain); + if (!lexicon) { continue; } + if (lexicon->header.type != GRN_TABLE_PAT_KEY) { continue; } + /* FIXME: GRN_TABLE_DAT_KEY should be supported */ + grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL); + if (tokenizer) { continue; } + } + if (n < buf_size) { + *ip++ = target; + } + if ((unsigned int) n < n_index_data) { + index_data[n].index = target; + index_data[n].section = section; + } + n++; + } + + return n; +} + +static grn_bool +is_valid_match_index(grn_ctx *ctx, grn_obj *index_column) +{ + return GRN_TRUE; +} + +static grn_bool +is_valid_range_index(grn_ctx *ctx, grn_obj *index_column) +{ + grn_obj *tokenizer; + grn_obj *lexicon; + + lexicon = grn_ctx_at(ctx, index_column->header.domain); + if (!lexicon) { return GRN_FALSE; } + /* FIXME: GRN_TABLE_DAT_KEY should be supported */ + if (lexicon->header.type != GRN_TABLE_PAT_KEY) { + grn_obj_unlink(ctx, lexicon); + return GRN_FALSE; + } + + grn_table_get_info(ctx, lexicon, NULL, NULL, &tokenizer, NULL, NULL); + grn_obj_unlink(ctx, lexicon); + if (tokenizer) { return GRN_FALSE; } + + return GRN_TRUE; +} + +static grn_bool +is_valid_index(grn_ctx *ctx, grn_obj *index_column, grn_operator op) +{ + switch (op) { + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + case GRN_OP_SIMILAR : + return is_valid_match_index(ctx, index_column); + break; + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + case GRN_OP_CALL : + return is_valid_range_index(ctx, index_column); + break; + case GRN_OP_REGEXP : + return is_valid_regexp_index(ctx, index_column); + break; + default : + return GRN_FALSE; + break; + } +} + +static int +find_section(grn_ctx *ctx, grn_obj *index_column, grn_obj *indexed_column) +{ + int section = 0; + grn_id indexed_column_id; + grn_id *source_ids; + int i, n_source_ids; + + indexed_column_id = DB_OBJ(indexed_column)->id; + + source_ids = DB_OBJ(index_column)->source; + n_source_ids = DB_OBJ(index_column)->source_size / sizeof(grn_id); + for (i = 0; i < n_source_ids; i++) { + grn_id source_id = source_ids[i]; + if (source_id == indexed_column_id) { + section = i + 1; + break; + } + } + + return section; +} + +static int +grn_column_find_index_data_accessor_index_column(grn_ctx *ctx, grn_accessor *a, + grn_operator op, + grn_index_datum *index_data, + unsigned int n_index_data, + grn_obj **index_buf, + int buf_size, + int *section_buf) +{ + grn_obj *index_column = a->obj; + int section = 0; + + if (!is_valid_index(ctx, index_column, op)) { + return 0; + } + + if (a->next) { + int specified_section; + grn_bool is_invalid_section; + if (a->next->next) { + return 0; + } + specified_section = find_section(ctx, index_column, a->next->obj); + is_invalid_section = (specified_section == 0); + if (is_invalid_section) { + return 0; + } + section = specified_section; + if (section_buf) { + *section_buf = section; + } + } + if (buf_size > 0) { + *index_buf = index_column; + } + if (n_index_data > 0) { + index_data[0].index = index_column; + index_data[0].section = section; + } + + return 1; +} + +static grn_bool +grn_column_find_index_data_accessor_is_key_search(grn_ctx *ctx, + grn_accessor *accessor, + grn_operator op) +{ + if (accessor->next) { + return GRN_FALSE; + } + + if (accessor->action != GRN_ACCESSOR_GET_KEY) { + return GRN_FALSE; + } + + if (!grn_obj_is_table(ctx, accessor->obj)) { + return GRN_FALSE; + } + + switch (op) { + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + switch (accessor->obj->header.type) { + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + return GRN_TRUE; + default : + return GRN_FALSE; + } + case GRN_OP_EQUAL : + switch (accessor->obj->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + return GRN_TRUE; + default : + return GRN_FALSE; + } + default : + return GRN_FALSE; + } +} + +static int +grn_column_find_index_data_accessor_match(grn_ctx *ctx, grn_obj *obj, + grn_operator op, + grn_index_datum *index_data, + unsigned n_index_data, + grn_obj **index_buf, int buf_size, + int *section_buf) +{ + int n = 0; + grn_obj **ip = index_buf; + grn_accessor *a = (grn_accessor *)obj; + + while (a) { + grn_hook *hooks; + grn_bool found = GRN_FALSE; + grn_hook_entry entry = (grn_hook_entry)-1; + + if (a->action == GRN_ACCESSOR_GET_COLUMN_VALUE && + GRN_OBJ_INDEX_COLUMNP(a->obj)) { + return grn_column_find_index_data_accessor_index_column(ctx, a, op, + index_data, + n_index_data, + index_buf, + buf_size, + section_buf); + } + + switch (a->action) { + case GRN_ACCESSOR_GET_KEY : + entry = GRN_HOOK_INSERT; + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + entry = GRN_HOOK_SET; + break; + default : + break; + } + + if (entry == (grn_hook_entry)-1) { + break; + } + + for (hooks = DB_OBJ(a->obj)->hooks[entry]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + + if (target->header.type != GRN_COLUMN_INDEX) { continue; } + + found = GRN_TRUE; + if (!a->next) { + int section; + + if (!is_valid_index(ctx, target, op)) { + continue; + } + + section = (MULTI_COLUMN_INDEXP(target)) ? data->section : 0; + if (section_buf) { + *section_buf = section; + } + if (n < buf_size) { + *ip++ = target; + } + if ((unsigned int) n < n_index_data) { + index_data[n].index = target; + index_data[n].section = section; + } + n++; + } + } + + if (!found && + grn_column_find_index_data_accessor_is_key_search(ctx, a, op)) { + grn_obj *index; + int section = 0; + + if ((grn_obj *)a == obj) { + index = a->obj; + } else { + index = (grn_obj *)a; + } + + found = GRN_TRUE; + if (section_buf) { + *section_buf = section; + } + if (n < buf_size) { + *ip++ = index; + } + if ((unsigned int) n < n_index_data) { + index_data[n].index = index; + index_data[n].section = section; + } + n++; + } + + if (!found && + a->next && + grn_obj_is_table(ctx, a->obj) && + a->obj->header.domain == a->next->obj->header.domain) { + grn_obj *index = (grn_obj *)a; + int section = 0; + + found = GRN_TRUE; + if (section_buf) { + *section_buf = section; + } + if (n < buf_size) { + *ip++ = index; + } + if ((unsigned int) n < n_index_data) { + index_data[n].index = index; + index_data[n].section = section; + } + n++; + } + + if (!found) { + break; + } + a = a->next; + } + + return n; +} + +static int +grn_column_find_index_data_accessor(grn_ctx *ctx, grn_obj *obj, + grn_operator op, + grn_index_datum *index_data, + unsigned n_index_data, + grn_obj **index_buf, int buf_size, + int *section_buf) +{ + int n = 0; + + if (section_buf) { + *section_buf = 0; + } + switch (op) { + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + case GRN_OP_TERM_EXTRACT : + if (buf_size > 0) { + index_buf[n] = obj; + } + if (n_index_data > 0) { + index_data[n].index = obj; + index_data[n].section = 0; + } + n++; + break; + case GRN_OP_PREFIX : + { + grn_accessor *a = (grn_accessor *)obj; + if (a->action == GRN_ACCESSOR_GET_KEY) { + if (a->obj->header.type == GRN_TABLE_PAT_KEY) { + if (buf_size > 0) { + index_buf[n] = obj; + } + if (n_index_data > 0) { + index_data[n].index = obj; + index_data[n].section = 0; + } + n++; + } + /* FIXME: GRN_TABLE_DAT_KEY should be supported */ + } + } + break; + case GRN_OP_SUFFIX : + { + grn_accessor *a = (grn_accessor *)obj; + if (a->action == GRN_ACCESSOR_GET_KEY) { + if (a->obj->header.type == GRN_TABLE_PAT_KEY && + a->obj->header.flags & GRN_OBJ_KEY_WITH_SIS) { + if (buf_size > 0) { + index_buf[n] = obj; + } + if (n_index_data > 0) { + index_data[n].index = obj; + index_data[n].section = 0; + } + n++; + } + } + } + break; + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + case GRN_OP_SIMILAR : + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + case GRN_OP_CALL : + case GRN_OP_REGEXP : + case GRN_OP_FUZZY : + n = grn_column_find_index_data_accessor_match(ctx, obj, op, + index_data, n_index_data, + index_buf, buf_size, + section_buf); + break; + default : + break; + } + + return n; +} + +int +grn_column_index(grn_ctx *ctx, grn_obj *obj, grn_operator op, + grn_obj **index_buf, int buf_size, int *section_buf) +{ + int n = 0; + GRN_API_ENTER; + if (GRN_DB_OBJP(obj)) { + switch (op) { + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + n = grn_column_find_index_data_column_equal(ctx, obj, op, + NULL, 0, + index_buf, buf_size, + section_buf); + break; + case GRN_OP_PREFIX : + case GRN_OP_SUFFIX : + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + case GRN_OP_SIMILAR : + case GRN_OP_REGEXP : + case GRN_OP_FUZZY : + n = grn_column_find_index_data_column_match(ctx, obj, op, + NULL, 0, + index_buf, buf_size, + section_buf); + break; + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + case GRN_OP_CALL : + n = grn_column_find_index_data_column_range(ctx, obj, op, + NULL, 0, + index_buf, buf_size, + section_buf); + break; + default : + break; + } + } else if (GRN_ACCESSORP(obj)) { + n = grn_column_find_index_data_accessor(ctx, obj, op, + NULL, 0, + index_buf, buf_size, + section_buf); + } + GRN_API_RETURN(n); +} + +unsigned int +grn_column_find_index_data(grn_ctx *ctx, grn_obj *obj, grn_operator op, + grn_index_datum *index_data, + unsigned int n_index_data) +{ + unsigned int n = 0; + GRN_API_ENTER; + if (GRN_DB_OBJP(obj)) { + switch (op) { + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + n = grn_column_find_index_data_column_equal(ctx, obj, op, + index_data, n_index_data, + NULL, 0, NULL); + break; + case GRN_OP_PREFIX : + case GRN_OP_SUFFIX : + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + case GRN_OP_SIMILAR : + case GRN_OP_REGEXP : + case GRN_OP_FUZZY : + n = grn_column_find_index_data_column_match(ctx, obj, op, + index_data, n_index_data, + NULL, 0, NULL); + break; + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + case GRN_OP_CALL : + n = grn_column_find_index_data_column_range(ctx, obj, op, + index_data, n_index_data, + NULL, 0, NULL); + break; + default : + break; + } + } else if (GRN_ACCESSORP(obj)) { + n = grn_column_find_index_data_accessor(ctx, obj, op, + index_data, n_index_data, + NULL, 0, NULL); + } + GRN_API_RETURN(n); +} + +static uint32_t +grn_column_get_all_index_data_column(grn_ctx *ctx, + grn_obj *obj, + grn_index_datum *index_data, + uint32_t n_index_data) +{ + uint32_t n = 0; + grn_hook_entry hook_entry; + grn_hook *hooks; + + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + hook_entry = GRN_HOOK_INSERT; + break; + default : + hook_entry = GRN_HOOK_SET; + break; + } + + for (hooks = DB_OBJ(obj)->hooks[hook_entry]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + int section = 0; + if (!target) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int length; + char hook_name[GRN_TABLE_MAX_KEY_SIZE]; + int hook_name_length; + + length = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE); + hook_name_length = grn_table_get_key(ctx, + ctx->impl->db, + data->target, + hook_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_OBJECT_CORRUPT, + "[column][indexes][all] " + "hook has a dangling reference: <%.*s> -> <%.*s>", + length, name, + hook_name_length, hook_name); + continue; + } + if (target->header.type != GRN_COLUMN_INDEX) { + continue; + } + if (MULTI_COLUMN_INDEXP(target)) { + section = data->section; + } + if (n < n_index_data) { + index_data[n].index = target; + index_data[n].section = section; + } + n++; + } + + return n; +} + +static uint32_t +grn_column_get_all_index_data_accessor_index_column(grn_ctx *ctx, + grn_accessor *a, + grn_index_datum *index_data, + uint32_t n_index_data) +{ + grn_obj *index_column = a->obj; + int section = 0; + + if (a->next) { + int specified_section; + grn_bool is_invalid_section; + if (a->next->next) { + return 0; + } + specified_section = find_section(ctx, index_column, a->next->obj); + is_invalid_section = (specified_section == 0); + if (is_invalid_section) { + return 0; + } + section = specified_section; + } + if (n_index_data > 0) { + index_data[0].index = index_column; + index_data[0].section = section; + } + + return 1; +} + +static uint32_t +grn_column_get_all_index_data_accessor(grn_ctx *ctx, + grn_obj *obj, + grn_index_datum *index_data, + uint32_t n_index_data) +{ + uint32_t n = 0; + grn_accessor *a = (grn_accessor *)obj; + + while (a) { + grn_hook *hooks; + grn_bool found = GRN_FALSE; + grn_hook_entry entry = (grn_hook_entry)-1; + + if (a->action == GRN_ACCESSOR_GET_COLUMN_VALUE && + GRN_OBJ_INDEX_COLUMNP(a->obj)) { + return grn_column_get_all_index_data_accessor_index_column(ctx, + a, + index_data, + n_index_data); + } + + switch (a->action) { + case GRN_ACCESSOR_GET_KEY : + entry = GRN_HOOK_INSERT; + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + entry = GRN_HOOK_SET; + break; + default : + break; + } + + if (entry == (grn_hook_entry)-1) { + break; + } + + for (hooks = DB_OBJ(a->obj)->hooks[entry]; hooks; hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + + if (target->header.type != GRN_COLUMN_INDEX) { + continue; + } + + found = GRN_TRUE; + if (!a->next) { + int section = 0; + + if (MULTI_COLUMN_INDEXP(target)) { + section = data->section; + } + if (n < n_index_data) { + index_data[n].index = target; + index_data[n].section = section; + } + n++; + } + } + + if (!found) { + break; + } + a = a->next; + } + + return n; +} + +uint32_t +grn_column_get_all_index_data(grn_ctx *ctx, + grn_obj *obj, + grn_index_datum *index_data, + uint32_t n_index_data) +{ + uint32_t n = 0; + GRN_API_ENTER; + if (GRN_DB_OBJP(obj)) { + n = grn_column_get_all_index_data_column(ctx, obj, + index_data, n_index_data); + } else if (GRN_ACCESSORP(obj)) { + n = grn_column_get_all_index_data_accessor(ctx, obj, + index_data, n_index_data); + } + GRN_API_RETURN(n); +} + +grn_rc +grn_obj_columns(grn_ctx *ctx, grn_obj *table, + const char *str, unsigned int str_size, grn_obj *res) +{ + grn_obj *col; + const char *p = (char *)str, *q, *r, *pe = p + str_size, *tokbuf[256]; + while (p < pe) { + int i, n = grn_tokenize(p, pe - p, tokbuf, 256, &q); + for (i = 0; i < n; i++) { + r = tokbuf[i]; + while (p < r && (' ' == *p || ',' == *p)) { p++; } + if (p < r) { + if (r[-1] == '*') { + grn_hash *cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); + if (cols) { + grn_id *key; + grn_table_columns(ctx, table, p, r - p - 1, (grn_obj *)cols); + GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { + if ((col = grn_ctx_at(ctx, *key))) { GRN_PTR_PUT(ctx, res, col); } + }); + grn_hash_close(ctx, cols); + } + { + grn_obj *type = grn_ctx_at(ctx, table->header.domain); + if (GRN_OBJ_TABLEP(type)) { + grn_obj *ai = grn_obj_column(ctx, table, + GRN_COLUMN_NAME_ID, + GRN_COLUMN_NAME_ID_LEN); + if (ai) { + if (ai->header.type == GRN_ACCESSOR) { + grn_id *key; + grn_accessor *id_accessor; + for (id_accessor = ((grn_accessor *)ai)->next; + id_accessor; + id_accessor = id_accessor->next) { + grn_obj *target_table = id_accessor->obj; + + cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); + if (!cols) { + continue; + } + grn_table_columns(ctx, target_table, + p, r - p - 1, (grn_obj *)cols); + GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { + if ((col = grn_ctx_at(ctx, *key))) { + grn_accessor *a; + grn_accessor *ac; + ac = accessor_new(ctx); + GRN_PTR_PUT(ctx, res, (grn_obj *)ac); + for (a = (grn_accessor *)ai; a; a = a->next) { + if (a->action != GRN_ACCESSOR_GET_ID) { + ac->action = a->action; + ac->obj = a->obj; + ac->next = accessor_new(ctx); + if (!(ac = ac->next)) { break; } + } else { + ac->action = GRN_ACCESSOR_GET_COLUMN_VALUE; + ac->obj = col; + ac->next = NULL; + break; + } + } + } + }); + grn_hash_close(ctx, cols); + } + } + grn_obj_unlink(ctx, ai); + } + } + } + } else if ((col = grn_obj_column(ctx, table, p, r - p))) { + GRN_PTR_PUT(ctx, res, col); + } + } + p = r; + } + p = q; + } + return ctx->rc; +} + +static grn_table_sort_key * +grn_table_sort_key_from_str_geo(grn_ctx *ctx, const char *str, unsigned int str_size, + grn_obj *table, unsigned int *nkeys) +{ + const char **tokbuf; + const char *p = str, *pe = str + str_size; + grn_table_sort_key *keys = NULL, *k = NULL; + while ((*p++ != '(')) { if (p == pe) { return NULL; } } + str = p; + while ((*p != ')')) { if (++p == pe) { return NULL; } } + str_size = p - str; + p = str; + if ((tokbuf = GRN_MALLOCN(const char *, str_size))) { + grn_id domain = GRN_ID_NIL; + int i, n = grn_tokenize(str, str_size, tokbuf, str_size, NULL); + if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) { + k = keys; + for (i = 0; i < n; i++) { + const char *r = tokbuf[i]; + while (p < r && (' ' == *p || ',' == *p)) { p++; } + if (p < r) { + k->flags = GRN_TABLE_SORT_ASC; + k->offset = 0; + if (*p == '+') { + p++; + } else if (*p == '-') { + k->flags = GRN_TABLE_SORT_DESC; + p++; + } + if (k == keys) { + if (!(k->key = grn_obj_column(ctx, table, p, r - p))) { + WARN(GRN_INVALID_ARGUMENT, "invalid sort key: <%.*s>(<%.*s>)", + (int)(tokbuf[i] - p), p, str_size, str); + break; + } + domain = grn_obj_get_range(ctx, k->key); + } else { + grn_obj buf; + GRN_TEXT_INIT(&buf, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET(ctx, &buf, p + 1, r - p - 2); /* should be quoted */ + k->key = grn_obj_open(ctx, GRN_BULK, 0, domain); + grn_obj_cast(ctx, &buf, k->key, GRN_FALSE); + GRN_OBJ_FIN(ctx, &buf); + } + k->flags |= GRN_TABLE_SORT_GEO; + k++; + } + p = r; + } + } + GRN_FREE(tokbuf); + } + if (!ctx->rc && k - keys > 0) { + *nkeys = k - keys; + } else { + grn_table_sort_key_close(ctx, keys, k - keys); + *nkeys = 0; + keys = NULL; + } + return keys; +} + +grn_table_sort_key * +grn_table_sort_key_from_str(grn_ctx *ctx, const char *str, unsigned int str_size, + grn_obj *table, unsigned int *nkeys) +{ + const char *p = str; + const char **tokbuf; + grn_table_sort_key *keys = NULL, *k = NULL; + + if (str_size == 0) { + return NULL; + } + + if ((keys = grn_table_sort_key_from_str_geo(ctx, str, str_size, table, nkeys))) { + return keys; + } + if ((tokbuf = GRN_MALLOCN(const char *, str_size))) { + int i, n = grn_tokenize(str, str_size, tokbuf, str_size, NULL); + if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) { + k = keys; + for (i = 0; i < n; i++) { + const char *r = tokbuf[i]; + while (p < r && (' ' == *p || ',' == *p)) { p++; } + if (p < r) { + k->flags = GRN_TABLE_SORT_ASC; + k->offset = 0; + if (*p == '+') { + p++; + } else if (*p == '-') { + k->flags = GRN_TABLE_SORT_DESC; + p++; + } + if ((k->key = grn_obj_column(ctx, table, p, r - p))) { + k++; + } else { + if (r - p == GRN_COLUMN_NAME_SCORE_LEN && + memcmp(p, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN) == 0) { + char table_name[GRN_TABLE_MAX_KEY_SIZE]; + int table_name_size; + table_name_size = grn_obj_name(ctx, table, + table_name, + GRN_TABLE_MAX_KEY_SIZE); + if (table_name_size == 0) { + grn_strcpy(table_name, GRN_TABLE_MAX_KEY_SIZE, "(anonymous)"); + table_name_size = strlen(table_name); + } + GRN_LOG(ctx, GRN_WARN, + "ignore invalid sort key: <%.*s>: " + "table:<%*.s> keys:<%.*s>", + (int)(r - p), p, + table_name_size, table_name, + str_size, str); + } else { + char table_name[GRN_TABLE_MAX_KEY_SIZE]; + int table_name_size; + table_name_size = grn_obj_name(ctx, table, + table_name, + GRN_TABLE_MAX_KEY_SIZE); + if (table_name_size == 0) { + grn_strcpy(table_name, GRN_TABLE_MAX_KEY_SIZE, "(anonymous)"); + table_name_size = strlen(table_name); + } + WARN(GRN_INVALID_ARGUMENT, + "invalid sort key: <%.*s>: " + "table:<%.*s> keys:<%.*s>", + (int)(r - p), p, + table_name_size, table_name, + str_size, str); + break; + } + } + } + p = r; + } + } + GRN_FREE(tokbuf); + } + if (!ctx->rc && k - keys > 0) { + *nkeys = k - keys; + } else { + grn_table_sort_key_close(ctx, keys, k - keys); + *nkeys = 0; + keys = NULL; + } + return keys; +} + +grn_rc +grn_table_sort_key_close(grn_ctx *ctx, grn_table_sort_key *keys, unsigned int nkeys) +{ + unsigned int i; + if (keys) { + for (i = 0; i < nkeys; i++) { + grn_obj *key = keys[i].key; + if (!grn_obj_is_column(ctx, key)) { + grn_obj_unlink(ctx, key); + } + } + GRN_FREE(keys); + } + return ctx->rc; +} + +grn_bool +grn_table_is_grouped(grn_ctx *ctx, grn_obj *table) +{ + if (GRN_OBJ_TABLEP(table) && GRN_TABLE_IS_GROUPED(table)) { + return GRN_TRUE; + } + return GRN_FALSE; +} + +unsigned int +grn_table_max_n_subrecs(grn_ctx *ctx, grn_obj *table) +{ + if (GRN_OBJ_TABLEP(table)) { + return DB_OBJ(table)->max_n_subrecs; + } + return 0; +} + +grn_obj * +grn_table_tokenize(grn_ctx *ctx, grn_obj *table, + const char *str, unsigned int str_len, + grn_obj *buf, grn_bool addp) +{ + grn_token_cursor *token_cursor = NULL; + grn_tokenize_mode mode = addp ? GRN_TOKENIZE_ADD : GRN_TOKENIZE_GET; + GRN_API_ENTER; + if (!(token_cursor = grn_token_cursor_open(ctx, table, str, str_len, mode, 0))) { + goto exit; + } + if (buf) { + GRN_BULK_REWIND(buf); + } else { + if (!(buf = grn_obj_open(ctx, GRN_UVECTOR, 0, DB_OBJ(table)->id))) { + goto exit; + } + } + while (token_cursor->status != GRN_TOKEN_CURSOR_DONE && token_cursor->status != GRN_TOKEN_CURSOR_DONE_SKIP) { + grn_id tid; + if ((tid = grn_token_cursor_next(ctx, token_cursor))) { + GRN_RECORD_PUT(ctx, buf, tid); + } + } +exit : + if (token_cursor) { + grn_token_cursor_close(ctx, token_cursor); + } + GRN_API_RETURN(buf); +} + +static void +grn_db_recover_database_remove_orphan_inspect(grn_ctx *ctx, grn_obj *db) +{ + GRN_TABLE_EACH_BEGIN_FLAGS(ctx, db, cursor, id, GRN_CURSOR_BY_ID) { + void *key; + int key_size; + + key_size = grn_table_cursor_get_key(ctx, cursor, &key); +#define INSPECT "inspect" +#define INSPECT_LEN (sizeof(INSPECT) - 1) + if (key_size == INSPECT_LEN && memcmp(key, INSPECT, INSPECT_LEN) == 0) { + if (!grn_ctx_at(ctx, id)) { + ERRCLR(ctx); + grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); + } + break; + } +#undef INSPECT +#undef INSPECT_LEN + } GRN_TABLE_EACH_END(ctx, cursor); +} + +static void +grn_db_recover_database(grn_ctx *ctx, grn_obj *db) +{ + if (grn_obj_is_locked(ctx, db)) { + ERR(GRN_OBJECT_CORRUPT, + "[db][recover] database may be broken. Please re-create the database"); + return; + } + + grn_db_clear_dirty(ctx, db); + grn_db_recover_database_remove_orphan_inspect(ctx, db); +} + +static void +grn_db_recover_table(grn_ctx *ctx, grn_obj *table) +{ + if (!grn_obj_is_locked(ctx, table)) { + return; + } + + { + char name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int name_size; + name_size = grn_obj_name(ctx, table, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_OBJECT_CORRUPT, + "[db][recover] table may be broken: <%.*s>: " + "please truncate the table (or clear lock of the table) " + "and load data again", + (int)name_size, name); + } +} + +static void +grn_db_recover_data_column(grn_ctx *ctx, grn_obj *data_column) +{ + if (!grn_obj_is_locked(ctx, data_column)) { + return; + } + + { + char name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int name_size; + name_size = grn_obj_name(ctx, data_column, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_OBJECT_CORRUPT, + "[db][recover] column may be broken: <%.*s>: " + "please truncate the column (or clear lock of the column) " + "and load data again", + (int)name_size, name); + } +} + +static void +grn_db_recover_index_column(grn_ctx *ctx, grn_obj *index_column) +{ + if (!grn_obj_is_locked(ctx, index_column)) { + return; + } + + grn_index_column_rebuild(ctx, index_column); +} + +static grn_bool +grn_db_recover_is_builtin(grn_ctx *ctx, grn_id id, grn_table_cursor *cursor) +{ + void *key; + const char *name; + int name_size; + + if (id < GRN_N_RESERVED_TYPES) { + return GRN_TRUE; + } + + name_size = grn_table_cursor_get_key(ctx, cursor, &key); + name = key; + +#define NAME_EQUAL(value) \ + (name_size == strlen(value) && memcmp(name, value, strlen(value)) == 0) + + if (NAME_EQUAL("inspect")) { + /* Just for compatibility. It's needed for users who used + Groonga master at between 2016-02-03 and 2016-02-26. */ + return GRN_TRUE; + } + +#undef NAME_EQUAL + + return GRN_FALSE; +} + +grn_rc +grn_db_recover(grn_ctx *ctx, grn_obj *db) +{ + grn_table_cursor *cursor; + grn_id id; + grn_bool is_close_opened_object_mode; + + GRN_API_ENTER; + + is_close_opened_object_mode = (grn_thread_get_limit() == 1); + + grn_db_recover_database(ctx, db); + if (ctx->rc != GRN_SUCCESS) { + GRN_API_RETURN(ctx->rc); + } + + cursor = grn_table_cursor_open(ctx, db, + NULL, 0, NULL, 0, + 0, -1, + GRN_CURSOR_BY_ID); + if (!cursor) { + GRN_API_RETURN(ctx->rc); + } + + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_obj *object; + + if (is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + if ((object = grn_ctx_at(ctx, id))) { + switch (object->header.type) { + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + grn_db_recover_table(ctx, object); + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + grn_db_recover_data_column(ctx, object); + break; + case GRN_COLUMN_INDEX : + grn_db_recover_index_column(ctx, object); + break; + default: + break; + } + grn_obj_unlink(ctx, object); + } else { + if (grn_db_recover_is_builtin(ctx, id, cursor)) { + ERRCLR(ctx); + } + } + + if (is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + + if (ctx->rc != GRN_SUCCESS) { + break; + } + } + grn_table_cursor_close(ctx, cursor); + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_db_unmap(grn_ctx *ctx, grn_obj *db) +{ + grn_id id; + db_value *vp; + grn_db *s = (grn_db *)db; + + GRN_API_ENTER; + + GRN_TINY_ARRAY_EACH(&s->values, 1, grn_db_curr_id(ctx, db), id, vp, { + grn_obj *obj = vp->ptr; + + if (obj) { + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + grn_obj_close(ctx, obj); + break; + } + } + }); + + GRN_API_RETURN(ctx->rc); +} + +static grn_rc +grn_ctx_get_all_objects(grn_ctx *ctx, grn_obj *objects_buffer, + grn_bool (*predicate)(grn_ctx *ctx, grn_obj *object)) +{ + grn_obj *db; + grn_table_cursor *cursor; + grn_id id; + + GRN_API_ENTER; + + db = ctx->impl->db; + if (!db) { + ERR(GRN_INVALID_ARGUMENT, "DB isn't associated"); + GRN_API_RETURN(ctx->rc); + } + + cursor = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + GRN_API_RETURN(ctx->rc); + } + + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_obj *object; + + if ((object = grn_ctx_at(ctx, id))) { + if (predicate(ctx, object)) { + GRN_PTR_PUT(ctx, objects_buffer, object); + } else { + grn_obj_unlink(ctx, object); + } + } else { + if (ctx->rc != GRN_SUCCESS) { + ERRCLR(ctx); + } + } + } + grn_table_cursor_close(ctx, cursor); + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_ctx_get_all_tables(grn_ctx *ctx, grn_obj *tables_buffer) +{ + return grn_ctx_get_all_objects(ctx, tables_buffer, grn_obj_is_table); +} + +grn_rc +grn_ctx_get_all_types(grn_ctx *ctx, grn_obj *types_buffer) +{ + return grn_ctx_get_all_objects(ctx, types_buffer, grn_obj_is_type); +} + +grn_rc +grn_ctx_get_all_tokenizers(grn_ctx *ctx, grn_obj *tokenizers_buffer) +{ + return grn_ctx_get_all_objects(ctx, tokenizers_buffer, + grn_obj_is_tokenizer_proc); +} + +grn_rc +grn_ctx_get_all_normalizers(grn_ctx *ctx, grn_obj *normalizers_buffer) +{ + return grn_ctx_get_all_objects(ctx, normalizers_buffer, + grn_obj_is_normalizer_proc); +} + +grn_rc +grn_ctx_get_all_token_filters(grn_ctx *ctx, grn_obj *token_filters_buffer) +{ + return grn_ctx_get_all_objects(ctx, token_filters_buffer, + grn_obj_is_token_filter_proc); +} + +grn_rc +grn_ctx_push_temporary_open_space(grn_ctx *ctx) +{ + grn_obj *stack; + grn_obj *space; + grn_obj buffer; + + GRN_API_ENTER; + + stack = &(ctx->impl->temporary_open_spaces.stack); + GRN_VOID_INIT(&buffer); + grn_bulk_write(ctx, stack, (const char *)&buffer, sizeof(grn_obj)); + space = ((grn_obj *)GRN_BULK_CURR(stack)) - 1; + GRN_PTR_INIT(space, GRN_OBJ_VECTOR | GRN_OBJ_OWN, GRN_ID_NIL); + + ctx->impl->temporary_open_spaces.current = space; + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_ctx_pop_temporary_open_space(grn_ctx *ctx) +{ + grn_obj *stack; + grn_obj *space; + + GRN_API_ENTER; + + stack = &(ctx->impl->temporary_open_spaces.stack); + if (GRN_BULK_EMPTYP(stack)) { + ERR(GRN_INVALID_ARGUMENT, + "[ctx][temporary-open-spaces][pop] too much pop"); + GRN_API_RETURN(ctx->rc); + } + + space = ctx->impl->temporary_open_spaces.current; + GRN_OBJ_FIN(ctx, space); + grn_bulk_truncate(ctx, stack, GRN_BULK_VSIZE(stack) - sizeof(grn_obj)); + + if (GRN_BULK_EMPTYP(stack)) { + space = NULL; + } else { + space = ((grn_obj *)GRN_BULK_CURR(stack)) - 1; + } + ctx->impl->temporary_open_spaces.current = space; + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_ctx_merge_temporary_open_space(grn_ctx *ctx) +{ + grn_obj *stack; + grn_obj *space; + grn_obj *next_space; + + GRN_API_ENTER; + + stack = &(ctx->impl->temporary_open_spaces.stack); + if ((unsigned long) GRN_BULK_VSIZE(stack) < (unsigned long) sizeof(grn_obj) * 2) { + ERR(GRN_INVALID_ARGUMENT, + "[ctx][temporary-open-spaces][merge] " + "merge requires at least two spaces"); + GRN_API_RETURN(ctx->rc); + } + + space = ctx->impl->temporary_open_spaces.current; + next_space = ctx->impl->temporary_open_spaces.current - 1; + { + unsigned int i, n_elements; + n_elements = GRN_BULK_VSIZE(space) / sizeof(grn_obj *); + for (i = 0; i < n_elements; i++) { + grn_obj *element = GRN_PTR_VALUE_AT(space, i); + GRN_PTR_PUT(ctx, next_space, element); + } + } + GRN_BULK_REWIND(space); + GRN_OBJ_FIN(ctx, space); + grn_bulk_truncate(ctx, stack, GRN_BULK_VSIZE(stack) - sizeof(grn_obj)); + + if (GRN_BULK_EMPTYP(stack)) { + space = NULL; + } else { + space = ((grn_obj *)GRN_BULK_CURR(stack)) - 1; + } + ctx->impl->temporary_open_spaces.current = space; + + GRN_API_RETURN(ctx->rc); +} diff --git a/storage/mroonga/vendor/groonga/lib/dump.c b/storage/mroonga/vendor/groonga/lib/dump.c new file mode 100644 index 00000000..72017fe3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/dump.c @@ -0,0 +1,112 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_ctx.h" + +grn_rc +grn_dump_table_create_flags(grn_ctx *ctx, + grn_table_flags flags, + grn_obj *buffer) +{ + GRN_API_ENTER; + + switch (flags & GRN_OBJ_TABLE_TYPE_MASK) { + case GRN_OBJ_TABLE_HASH_KEY: + GRN_TEXT_PUTS(ctx, buffer, "TABLE_HASH_KEY"); + break; + case GRN_OBJ_TABLE_PAT_KEY: + GRN_TEXT_PUTS(ctx, buffer, "TABLE_PAT_KEY"); + break; + case GRN_OBJ_TABLE_DAT_KEY: + GRN_TEXT_PUTS(ctx, buffer, "TABLE_DAT_KEY"); + break; + case GRN_OBJ_TABLE_NO_KEY: + GRN_TEXT_PUTS(ctx, buffer, "TABLE_NO_KEY"); + break; + } + if (flags & GRN_OBJ_KEY_LARGE) { + GRN_TEXT_PUTS(ctx, buffer, "|KEY_LARGE"); + } + if (flags & GRN_OBJ_KEY_WITH_SIS) { + GRN_TEXT_PUTS(ctx, buffer, "|KEY_WITH_SIS"); + } + if (flags & GRN_OBJ_KEY_NORMALIZE) { + GRN_TEXT_PUTS(ctx, buffer, "|KEY_NORMALIZE"); + } + if (flags & GRN_OBJ_PERSISTENT) { + GRN_TEXT_PUTS(ctx, buffer, "|PERSISTENT"); + } + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_dump_column_create_flags(grn_ctx *ctx, + grn_column_flags flags, + grn_obj *buffer) +{ + GRN_API_ENTER; + + switch (flags & GRN_OBJ_COLUMN_TYPE_MASK) { + case GRN_OBJ_COLUMN_SCALAR: + GRN_TEXT_PUTS(ctx, buffer, "COLUMN_SCALAR"); + break; + case GRN_OBJ_COLUMN_VECTOR: + GRN_TEXT_PUTS(ctx, buffer, "COLUMN_VECTOR"); + if (flags & GRN_OBJ_WITH_WEIGHT) { + GRN_TEXT_PUTS(ctx, buffer, "|WITH_WEIGHT"); + } + break; + case GRN_OBJ_COLUMN_INDEX: + GRN_TEXT_PUTS(ctx, buffer, "COLUMN_INDEX"); + if (flags & GRN_OBJ_WITH_SECTION) { + GRN_TEXT_PUTS(ctx, buffer, "|WITH_SECTION"); + } + if (flags & GRN_OBJ_WITH_WEIGHT) { + GRN_TEXT_PUTS(ctx, buffer, "|WITH_WEIGHT"); + } + if (flags & GRN_OBJ_WITH_POSITION) { + GRN_TEXT_PUTS(ctx, buffer, "|WITH_POSITION"); + } + if (flags & GRN_OBJ_INDEX_SMALL) { + GRN_TEXT_PUTS(ctx, buffer, "|INDEX_SMALL"); + } + if (flags & GRN_OBJ_INDEX_MEDIUM) { + GRN_TEXT_PUTS(ctx, buffer, "|INDEX_MEDIUM"); + } + break; + } + switch (flags & GRN_OBJ_COMPRESS_MASK) { + case GRN_OBJ_COMPRESS_NONE: + break; + case GRN_OBJ_COMPRESS_ZLIB: + GRN_TEXT_PUTS(ctx, buffer, "|COMPRESS_ZLIB"); + break; + case GRN_OBJ_COMPRESS_LZ4: + GRN_TEXT_PUTS(ctx, buffer, "|COMPRESS_LZ4"); + break; + case GRN_OBJ_COMPRESS_ZSTD: + GRN_TEXT_PUTS(ctx, buffer, "|COMPRESS_ZSTD"); + break; + } + if (flags & GRN_OBJ_PERSISTENT) { + GRN_TEXT_PUTS(ctx, buffer, "|PERSISTENT"); + } + + GRN_API_RETURN(ctx->rc); +} diff --git a/storage/mroonga/vendor/groonga/lib/error.c b/storage/mroonga/vendor/groonga/lib/error.c new file mode 100644 index 00000000..9fd03291 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/error.c @@ -0,0 +1,454 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_error.h" +#include "grn_windows.h" + +#ifdef HAVE_ERRNO_H +#include +#endif /* HAVE_ERRNO_H */ + +#include + +#ifdef WIN32 + +grn_rc +grn_windows_error_code_to_rc(int error_code) +{ + grn_rc rc; + + switch (error_code) { + case ERROR_FILE_NOT_FOUND : + case ERROR_PATH_NOT_FOUND : + rc = GRN_NO_SUCH_FILE_OR_DIRECTORY; + break; + case ERROR_TOO_MANY_OPEN_FILES : + rc = GRN_TOO_MANY_OPEN_FILES; + break; + case ERROR_ACCESS_DENIED : + rc = GRN_PERMISSION_DENIED; + break; + case ERROR_INVALID_HANDLE : + rc = GRN_INVALID_ARGUMENT; + break; + case ERROR_ARENA_TRASHED : + rc = GRN_ADDRESS_IS_NOT_AVAILABLE; + break; + case ERROR_NOT_ENOUGH_MEMORY : + rc = GRN_NO_MEMORY_AVAILABLE; + break; + case ERROR_INVALID_BLOCK : + case ERROR_BAD_ENVIRONMENT : + rc = GRN_INVALID_ARGUMENT; + break; + case ERROR_BAD_FORMAT : + rc = GRN_INVALID_FORMAT; + break; + case ERROR_INVALID_DATA : + rc = GRN_INVALID_ARGUMENT; + break; + case ERROR_OUTOFMEMORY : + rc = GRN_NO_MEMORY_AVAILABLE; + break; + case ERROR_INVALID_DRIVE : + rc = GRN_INVALID_ARGUMENT; + break; + case ERROR_WRITE_PROTECT : + rc = GRN_PERMISSION_DENIED; + break; + case ERROR_BAD_LENGTH : + rc = GRN_INVALID_ARGUMENT; + break; + case ERROR_SEEK : + rc = GRN_INVALID_SEEK; + break; + case ERROR_NOT_SUPPORTED : + rc = GRN_OPERATION_NOT_SUPPORTED; + break; + case ERROR_NETWORK_ACCESS_DENIED : + rc = GRN_OPERATION_NOT_PERMITTED; + break; + case ERROR_FILE_EXISTS : + rc = GRN_FILE_EXISTS; + break; + case ERROR_INVALID_PARAMETER : + rc = GRN_INVALID_ARGUMENT; + break; + case ERROR_BROKEN_PIPE : + rc = GRN_BROKEN_PIPE; + break; + case ERROR_CALL_NOT_IMPLEMENTED : + rc = GRN_FUNCTION_NOT_IMPLEMENTED; + break; + case ERROR_INVALID_NAME : + rc = GRN_INVALID_ARGUMENT; + break; + case ERROR_BUSY_DRIVE : + case ERROR_PATH_BUSY : + rc = GRN_RESOURCE_BUSY; + break; + case ERROR_BAD_ARGUMENTS : + rc = GRN_INVALID_ARGUMENT; + break; + case ERROR_BUSY : + rc = GRN_RESOURCE_BUSY; + break; + case ERROR_ALREADY_EXISTS : + rc = GRN_FILE_EXISTS; + break; + case ERROR_BAD_EXE_FORMAT : + rc = GRN_EXEC_FORMAT_ERROR; + break; + case ERROR_NO_SYSTEM_RESOURCES : + rc = GRN_RESOURCE_TEMPORARILY_UNAVAILABLE; + break; + default: + rc = GRN_UNKNOWN_ERROR; + break; + } + + return rc; +} + +# define LANG_ID_NEUTRAL() MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL) +# define LANG_ID_USER_DEFAULT() MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT) +# define LANG_ID_SYSTEM_DEFAULT() MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT) + +const char * +grn_current_error_message(void) +{ +# define ERROR_MESSAGE_BUFFER_SIZE 4096 + int error_code = GetLastError(); + static WCHAR utf16_message[ERROR_MESSAGE_BUFFER_SIZE]; + DWORD written_utf16_chars; + static char message[ERROR_MESSAGE_BUFFER_SIZE]; + + written_utf16_chars = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + error_code, + LANG_ID_USER_DEFAULT(), + utf16_message, + ERROR_MESSAGE_BUFFER_SIZE, + NULL); + if (written_utf16_chars >= 2) { + if (utf16_message[written_utf16_chars - 1] == L'\n') { + utf16_message[written_utf16_chars - 1] = L'\0'; + written_utf16_chars--; + } + if (utf16_message[written_utf16_chars - 1] == L'\r') { + utf16_message[written_utf16_chars - 1] = L'\0'; + written_utf16_chars--; + } + } + + { + UINT code_page; + DWORD convert_flags = 0; + int written_bytes; + + code_page = grn_windows_encoding_to_code_page(grn_get_default_encoding()); + written_bytes = WideCharToMultiByte(code_page, + convert_flags, + utf16_message, + written_utf16_chars, + message, + ERROR_MESSAGE_BUFFER_SIZE, + NULL, + NULL); + } + + return message; + +# undef ERROR_MESSAGE_BUFFER_SIZE +} +#else +const char * +grn_current_error_message(void) +{ + return strerror(errno); +} +#endif + +const char * +grn_strerror(int error_code) +{ +#ifdef WIN32 +# define MESSAGE_BUFFER_SIZE 1024 + static char message[MESSAGE_BUFFER_SIZE]; + strerror_s(message, MESSAGE_BUFFER_SIZE, error_code); + return message; +# undef MESSAGE_BUFFER_SIZE +#else /* WIN32 */ + return strerror(error_code); +#endif /* WIN32 */ +} + +const char * +grn_rc_to_string(grn_rc rc) +{ + const char *message = "invalid grn_rc"; + + switch (rc) { + case GRN_SUCCESS : + message = "success"; + break; + case GRN_END_OF_DATA : + message = "end of data"; + break; + case GRN_UNKNOWN_ERROR : + message = "unknown error"; + break; + case GRN_OPERATION_NOT_PERMITTED : + message = "operation not permitted"; + break; + case GRN_NO_SUCH_FILE_OR_DIRECTORY : + message = "no such file or directory"; + break; + case GRN_NO_SUCH_PROCESS : + message = "no such process"; + break; + case GRN_INTERRUPTED_FUNCTION_CALL : + message = "interrupted function call"; + break; + case GRN_INPUT_OUTPUT_ERROR : + message = "input output error"; + break; + case GRN_NO_SUCH_DEVICE_OR_ADDRESS : + message = "no such device or address"; + break; + case GRN_ARG_LIST_TOO_LONG : + message = "argument list is too long"; + break; + case GRN_EXEC_FORMAT_ERROR : + message = "exec format error"; + break; + case GRN_BAD_FILE_DESCRIPTOR : + message = "bad file descriptor"; + break; + case GRN_NO_CHILD_PROCESSES : + message = "no child processes"; + break; + case GRN_RESOURCE_TEMPORARILY_UNAVAILABLE : + message = "resource temporarily unavailable"; + break; + case GRN_NOT_ENOUGH_SPACE : + message = "not enough space"; + break; + case GRN_PERMISSION_DENIED : + message = "permission denied"; + break; + case GRN_BAD_ADDRESS : + message = "bad address"; + break; + case GRN_RESOURCE_BUSY : + message = "resource busy"; + break; + case GRN_FILE_EXISTS : + message = "file exists"; + break; + case GRN_IMPROPER_LINK : + message = "improper link"; + break; + case GRN_NO_SUCH_DEVICE : + message = "no such device"; + break; + case GRN_NOT_A_DIRECTORY : + message = "not a directory"; + break; + case GRN_IS_A_DIRECTORY : + message = "is a directory"; + break; + case GRN_INVALID_ARGUMENT : + message = "invalid argument"; + break; + case GRN_TOO_MANY_OPEN_FILES_IN_SYSTEM : + message = "too many open files in system"; + break; + case GRN_TOO_MANY_OPEN_FILES : + message = "too many open files"; + break; + case GRN_INAPPROPRIATE_I_O_CONTROL_OPERATION : + message = "inappropriate I/O control operation"; + break; + case GRN_FILE_TOO_LARGE : + message = "file too large"; + break; + case GRN_NO_SPACE_LEFT_ON_DEVICE : + message = "no space left on device"; + break; + case GRN_INVALID_SEEK : + message = "invalid seek"; + break; + case GRN_READ_ONLY_FILE_SYSTEM : + message = "read only file system"; + break; + case GRN_TOO_MANY_LINKS : + message = "too many links"; + break; + case GRN_BROKEN_PIPE : + message = "broken pipe"; + break; + case GRN_DOMAIN_ERROR : + message = "domain error"; + break; + case GRN_RESULT_TOO_LARGE : + message = "result too large"; + break; + case GRN_RESOURCE_DEADLOCK_AVOIDED : + message = "resource deadlock avoided"; + break; + case GRN_NO_MEMORY_AVAILABLE : + message = "no memory available"; + break; + case GRN_FILENAME_TOO_LONG : + message = "filename too long"; + break; + case GRN_NO_LOCKS_AVAILABLE : + message = "no locks available"; + break; + case GRN_FUNCTION_NOT_IMPLEMENTED : + message = "function not implemented"; + break; + case GRN_DIRECTORY_NOT_EMPTY : + message = "directory not empty"; + break; + case GRN_ILLEGAL_BYTE_SEQUENCE : + message = "illegal byte sequence"; + break; + case GRN_SOCKET_NOT_INITIALIZED : + message = "socket not initialized"; + break; + case GRN_OPERATION_WOULD_BLOCK : + message = "operation would block"; + break; + case GRN_ADDRESS_IS_NOT_AVAILABLE : + message = "address is not available"; + break; + case GRN_NETWORK_IS_DOWN : + message = "network is down"; + break; + case GRN_NO_BUFFER : + message = "no buffer"; + break; + case GRN_SOCKET_IS_ALREADY_CONNECTED : + message = "socket is already connected"; + break; + case GRN_SOCKET_IS_NOT_CONNECTED : + message = "socket is not connected"; + break; + case GRN_SOCKET_IS_ALREADY_SHUTDOWNED : + message = "socket is already shutdowned"; + break; + case GRN_OPERATION_TIMEOUT : + message = "operation timeout"; + break; + case GRN_CONNECTION_REFUSED : + message = "connection refused"; + break; + case GRN_RANGE_ERROR : + message = "range error"; + break; + case GRN_TOKENIZER_ERROR : + message = "tokenizer error"; + break; + case GRN_FILE_CORRUPT : + message = "file corrupt"; + break; + case GRN_INVALID_FORMAT : + message = "invalid format"; + break; + case GRN_OBJECT_CORRUPT : + message = "object corrupt"; + break; + case GRN_TOO_MANY_SYMBOLIC_LINKS : + message = "too many symbolic links"; + break; + case GRN_NOT_SOCKET : + message = "not socket"; + break; + case GRN_OPERATION_NOT_SUPPORTED : + message = "operation not supported"; + break; + case GRN_ADDRESS_IS_IN_USE : + message = "address is in use"; + break; + case GRN_ZLIB_ERROR : + message = "zlib error"; + break; + case GRN_LZ4_ERROR : + message = "LZ4 error"; + break; + case GRN_STACK_OVER_FLOW : + message = "stack over flow"; + break; + case GRN_SYNTAX_ERROR : + message = "syntax error"; + break; + case GRN_RETRY_MAX : + message = "retry max"; + break; + case GRN_INCOMPATIBLE_FILE_FORMAT : + message = "incompatible file format"; + break; + case GRN_UPDATE_NOT_ALLOWED : + message = "update not allowed"; + break; + case GRN_TOO_SMALL_OFFSET : + message = "too small offset"; + break; + case GRN_TOO_LARGE_OFFSET : + message = "too large offset"; + break; + case GRN_TOO_SMALL_LIMIT : + message = "too small limit"; + break; + case GRN_CAS_ERROR : + message = "cas error"; + break; + case GRN_UNSUPPORTED_COMMAND_VERSION : + message = "unsupported command version"; + break; + case GRN_NORMALIZER_ERROR : + message = "normalizer error"; + break; + case GRN_TOKEN_FILTER_ERROR : + message = "token filter error"; + break; + case GRN_COMMAND_ERROR : + message = "command error"; + break; + case GRN_PLUGIN_ERROR : + message = "plugin error"; + break; + case GRN_SCORER_ERROR : + message = "scorer error"; + break; + case GRN_CANCEL : + message = "cancel"; + break; + case GRN_WINDOW_FUNCTION_ERROR : + message = "window function error"; + break; + case GRN_ZSTD_ERROR : + message = "Zstandard error"; + break; + } + + return message; +} diff --git a/storage/mroonga/vendor/groonga/lib/expr.c b/storage/mroonga/vendor/groonga/lib/expr.c new file mode 100644 index 00000000..d190d3e0 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/expr.c @@ -0,0 +1,9294 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include "grn_db.h" +#include "grn_ctx_impl.h" +#include "grn_ctx_impl_mrb.h" +#include +#include "grn_ii.h" +#include "grn_geo.h" +#include "grn_expr.h" +#include "grn_expr_code.h" +#include "grn_expr_executor.h" +#include "grn_scanner.h" +#include "grn_util.h" +#include "grn_report.h" +#include "grn_token_cursor.h" +#include "grn_mrb.h" +#include "mrb/mrb_expr.h" + +#ifdef GRN_WITH_ONIGMO +# define GRN_SUPPORT_REGEXP +#endif + +#ifdef GRN_SUPPORT_REGEXP +# include "grn_normalizer.h" +# include +#endif + +static double grn_table_select_enough_filtered_ratio = 0.0; +static int grn_table_select_max_n_enough_filtered_records = 1000; +static grn_bool grn_table_select_and_min_skip_enable = GRN_TRUE; +static grn_bool grn_scan_info_regexp_dot_asterisk_enable = GRN_TRUE; + +void +grn_expr_init_from_env(void) +{ + { + char grn_table_select_enough_filtered_ratio_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_TABLE_SELECT_ENOUGH_FILTERED_RATIO", + grn_table_select_enough_filtered_ratio_env, + GRN_ENV_BUFFER_SIZE); + if (grn_table_select_enough_filtered_ratio_env[0]) { + grn_table_select_enough_filtered_ratio = + atof(grn_table_select_enough_filtered_ratio_env); + } + } + + { + char grn_table_select_max_n_enough_filtered_records_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_TABLE_SELECT_MAX_N_ENOUGH_FILTERED_RECORDS", + grn_table_select_max_n_enough_filtered_records_env, + GRN_ENV_BUFFER_SIZE); + if (grn_table_select_max_n_enough_filtered_records_env[0]) { + grn_table_select_max_n_enough_filtered_records = + atoi(grn_table_select_max_n_enough_filtered_records_env); + } + } + + { + char grn_table_select_and_min_skip_enable_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_TABLE_SELECT_AND_MIN_SKIP_ENABLE", + grn_table_select_and_min_skip_enable_env, + GRN_ENV_BUFFER_SIZE); + if (strcmp(grn_table_select_and_min_skip_enable_env, "no") == 0) { + grn_table_select_and_min_skip_enable = GRN_FALSE; + } else { + grn_table_select_and_min_skip_enable = GRN_TRUE; + } + } + + { + char grn_scan_info_regexp_dot_asterisk_enable_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_SCAN_INFO_REGEXP_DOT_ASTERISK_ENABLE", + grn_scan_info_regexp_dot_asterisk_enable_env, + GRN_ENV_BUFFER_SIZE); + if (strcmp(grn_scan_info_regexp_dot_asterisk_enable_env, "no") == 0) { + grn_scan_info_regexp_dot_asterisk_enable = GRN_FALSE; + } else { + grn_scan_info_regexp_dot_asterisk_enable = GRN_TRUE; + } + } +} + +grn_obj * +grn_expr_alloc(grn_ctx *ctx, grn_obj *expr, grn_id domain, unsigned char flags) +{ + grn_obj *res = NULL; + grn_expr *e = (grn_expr *)expr; + if (e) { + if (e->values_curr >= e->values_size) { + // todo : expand values. + ERR(GRN_NO_MEMORY_AVAILABLE, "no more e->values"); + return NULL; + } + res = &e->values[e->values_curr++]; + if (e->values_curr > e->values_tail) { e->values_tail = e->values_curr; } + grn_obj_reinit(ctx, res, domain, flags); + } + return res; +} + +grn_hash * +grn_expr_get_vars(grn_ctx *ctx, grn_obj *expr, unsigned int *nvars) +{ + grn_hash *vars = NULL; + if (expr->header.type == GRN_PROC || expr->header.type == GRN_EXPR) { + grn_id id = DB_OBJ(expr)->id; + grn_expr *e = (grn_expr *)expr; + int added = 0; + grn_hash **vp; + if (grn_hash_add(ctx, ctx->impl->expr_vars, &id, sizeof(grn_id), (void **)&vp, &added)) { + if (!*vp) { + *vp = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj), + GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY); + if (*vp) { + uint32_t i; + grn_obj *value; + grn_expr_var *v; + for (v = e->vars, i = e->nvars; i; v++, i--) { + grn_hash_add(ctx, *vp, v->name, v->name_size, (void **)&value, &added); + GRN_OBJ_INIT(value, v->value.header.type, 0, v->value.header.domain); + GRN_TEXT_PUT(ctx, value, GRN_TEXT_VALUE(&v->value), GRN_TEXT_LEN(&v->value)); + } + } + } + vars = *vp; + } + } + *nvars = vars ? GRN_HASH_SIZE(vars) : 0; + return vars; +} + +grn_rc +grn_expr_clear_vars(grn_ctx *ctx, grn_obj *expr) +{ + if (expr->header.type == GRN_PROC || expr->header.type == GRN_EXPR) { + grn_hash **vp; + grn_id eid, id = DB_OBJ(expr)->id; + if ((eid = grn_hash_get(ctx, ctx->impl->expr_vars, &id, sizeof(grn_id), (void **)&vp))) { + if (*vp) { + grn_obj *value; + GRN_HASH_EACH(ctx, *vp, i, NULL, NULL, (void **)&value, { + GRN_OBJ_FIN(ctx, value); + }); + grn_hash_close(ctx, *vp); + } + grn_hash_delete_by_id(ctx, ctx->impl->expr_vars, eid, NULL); + } + } + return ctx->rc; +} + +grn_obj * +grn_proc_get_info(grn_ctx *ctx, grn_user_data *user_data, + grn_expr_var **vars, unsigned int *nvars, grn_obj **caller) +{ + grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; + if (caller) { *caller = pctx->caller; } + if (pctx->proc) { + if (vars) { + *vars = pctx->proc->vars; + // *vars = grn_expr_get_vars(ctx, (grn_obj *)pctx->proc, nvars); + } + if (nvars) { *nvars = pctx->proc->nvars; } + } else { + if (vars) { *vars = NULL; } + if (nvars) { *nvars = 0; } + } + return (grn_obj *)pctx->proc; +} + +grn_obj * +grn_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data) +{ + uint32_t n; + grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; + if (pctx->proc) { + return (grn_obj *)grn_expr_get_vars(ctx, (grn_obj *)pctx->proc, &n); + } else { + return NULL; + } +} + +grn_obj * +grn_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, const char *name, unsigned int name_size) +{ + grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; + return pctx->proc ? grn_expr_get_var(ctx, (grn_obj *)pctx->proc, name, name_size) : NULL; +} + +grn_obj * +grn_proc_get_var_by_offset(grn_ctx *ctx, grn_user_data *user_data, unsigned int offset) +{ + grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; + return pctx->proc ? grn_expr_get_var_by_offset(ctx, (grn_obj *)pctx->proc, offset) : NULL; +} + +grn_obj * +grn_proc_get_or_add_var(grn_ctx *ctx, grn_user_data *user_data, + const char *name, unsigned int name_size) +{ + grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; + return pctx->proc ? grn_expr_get_or_add_var(ctx, (grn_obj *)pctx->proc, name, name_size) : NULL; +} + +grn_obj * +grn_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, grn_id domain, unsigned char flags) +{ + grn_proc_ctx *pctx = (grn_proc_ctx *)user_data; + return pctx->caller ? grn_expr_alloc(ctx, (grn_obj *)pctx->caller, domain, flags) : NULL; +} + +grn_proc_type +grn_proc_get_type(grn_ctx *ctx, grn_obj *proc) +{ + grn_proc *proc_ = (grn_proc *)proc; + return proc_ ? proc_->type : GRN_PROC_INVALID; +} + +grn_rc +grn_proc_set_selector(grn_ctx *ctx, grn_obj *proc, grn_selector_func selector) +{ + grn_proc *proc_ = (grn_proc *)proc; + if (!grn_obj_is_function_proc(ctx, proc)) { + return GRN_INVALID_ARGUMENT; + } + proc_->callbacks.function.selector = selector; + return GRN_SUCCESS; +} + +grn_rc +grn_proc_set_selector_operator(grn_ctx *ctx, grn_obj *proc, grn_operator op) +{ + grn_proc *proc_ = (grn_proc *)proc; + if (!grn_obj_is_function_proc(ctx, proc)) { + return GRN_INVALID_ARGUMENT; + } + proc_->callbacks.function.selector_op = op; + return GRN_SUCCESS; +} + +grn_operator +grn_proc_get_selector_operator(grn_ctx *ctx, grn_obj *proc) +{ + grn_proc *proc_ = (grn_proc *)proc; + if (!grn_obj_is_function_proc(ctx, proc)) { + return GRN_OP_NOP; + } + return proc_->callbacks.function.selector_op; +} + +grn_rc +grn_proc_set_is_stable(grn_ctx *ctx, grn_obj *proc, grn_bool is_stable) +{ + grn_proc *proc_ = (grn_proc *)proc; + if (!grn_obj_is_function_proc(ctx, proc)) { + return GRN_INVALID_ARGUMENT; + } + proc_->callbacks.function.is_stable = is_stable; + return GRN_SUCCESS; +} + +grn_bool +grn_proc_is_stable(grn_ctx *ctx, grn_obj *proc) +{ + grn_proc *proc_ = (grn_proc *)proc; + if (!grn_obj_is_function_proc(ctx, proc)) { + return GRN_FALSE; + } + return proc_->callbacks.function.is_stable; +} + +/* grn_expr */ + +grn_obj * +grn_ctx_pop(grn_ctx *ctx) +{ + if (ctx && ctx->impl && ctx->impl->stack_curr) { + return ctx->impl->stack[--ctx->impl->stack_curr]; + } + return NULL; +} + +grn_rc +grn_ctx_push(grn_ctx *ctx, grn_obj *obj) +{ + if (ctx && ctx->impl && ctx->impl->stack_curr < GRN_STACK_SIZE) { + ctx->impl->stack[ctx->impl->stack_curr++] = obj; + return GRN_SUCCESS; + } + return GRN_STACK_OVER_FLOW; +} + +grn_obj * +grn_expr_alloc_const(grn_ctx *ctx, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + uint32_t id = e->nconsts % GRN_EXPR_CONST_BLK_SIZE; + uint32_t blk_id = e->nconsts / GRN_EXPR_CONST_BLK_SIZE; + + if (id == 0) { + uint32_t nblks = blk_id + 1; + grn_obj **blks = (grn_obj **)GRN_REALLOC(e->const_blks, + sizeof(grn_obj *) * nblks); + if (!blks) { + ERR(GRN_NO_MEMORY_AVAILABLE, "realloc failed"); + return NULL; + } + e->const_blks = blks; + blks[blk_id] = GRN_MALLOCN(grn_obj, GRN_EXPR_CONST_BLK_SIZE); + if (!blks[blk_id]) { + ERR(GRN_NO_MEMORY_AVAILABLE, "malloc failed"); + return NULL; + } + } + e->nconsts++; + return &e->const_blks[blk_id][id]; +} + +void +grn_obj_pack(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_text_benc(ctx, buf, obj->header.type); + if (GRN_DB_OBJP(obj)) { + grn_text_benc(ctx, buf, DB_OBJ(obj)->id); + } else { + // todo : support vector, query, accessor, snip.. + uint32_t vs = GRN_BULK_VSIZE(obj); + grn_text_benc(ctx, buf, obj->header.domain); + grn_text_benc(ctx, buf, vs); + if (vs) { GRN_TEXT_PUT(ctx, buf, GRN_BULK_HEAD(obj), vs); } + } +} + +const uint8_t * +grn_obj_unpack(grn_ctx *ctx, const uint8_t *p, const uint8_t *pe, uint8_t type, uint8_t flags, grn_obj *obj) +{ + grn_id domain; + uint32_t vs; + GRN_B_DEC(domain, p); + GRN_OBJ_INIT(obj, type, flags, domain); + GRN_B_DEC(vs, p); + if (pe < p + vs) { + ERR(GRN_INVALID_FORMAT, "benced image is corrupt"); + return p; + } + grn_bulk_write(ctx, obj, (const char *)p, vs); + return p + vs; +} + +typedef enum { + GRN_EXPR_PACK_TYPE_NULL = 0, + GRN_EXPR_PACK_TYPE_VARIABLE = 1, + GRN_EXPR_PACK_TYPE_OTHERS = 2 +} grn_expr_pack_type; + +void +grn_expr_pack(grn_ctx *ctx, grn_obj *buf, grn_obj *expr) +{ + grn_expr_code *c; + grn_expr_var *v; + grn_expr *e = (grn_expr *)expr; + uint32_t i, j; + grn_text_benc(ctx, buf, e->nvars); + for (i = e->nvars, v = e->vars; i; i--, v++) { + grn_text_benc(ctx, buf, v->name_size); + if (v->name_size) { GRN_TEXT_PUT(ctx, buf, v->name, v->name_size); } + grn_obj_pack(ctx, buf, &v->value); + } + i = e->codes_curr; + grn_text_benc(ctx, buf, i); + for (c = e->codes; i; i--, c++) { + grn_text_benc(ctx, buf, c->op); + grn_text_benc(ctx, buf, c->nargs); + if (!c->value) { + grn_text_benc(ctx, buf, GRN_EXPR_PACK_TYPE_NULL); + } else { + for (j = 0, v = e->vars; j < e->nvars; j++, v++) { + if (&v->value == c->value) { + grn_text_benc(ctx, buf, GRN_EXPR_PACK_TYPE_VARIABLE); + grn_text_benc(ctx, buf, j); + break; + } + } + if (j == e->nvars) { + grn_text_benc(ctx, buf, GRN_EXPR_PACK_TYPE_OTHERS); + grn_obj_pack(ctx, buf, c->value); + } + } + } +} + +const uint8_t * +grn_expr_unpack(grn_ctx *ctx, const uint8_t *p, const uint8_t *pe, grn_obj *expr) +{ + grn_obj *v; + grn_expr_pack_type type; + uint32_t i, n, ns; + grn_expr_code *code; + grn_expr *e = (grn_expr *)expr; + GRN_B_DEC(n, p); + for (i = 0; i < n; i++) { + uint32_t object_type; + GRN_B_DEC(ns, p); + v = grn_expr_add_var(ctx, expr, ns ? (const char *)p : NULL, ns); + p += ns; + GRN_B_DEC(object_type, p); + if (GRN_TYPE <= object_type && object_type <= GRN_COLUMN_INDEX) { /* error */ } + p = grn_obj_unpack(ctx, p, pe, object_type, 0, v); + if (pe < p) { + ERR(GRN_INVALID_FORMAT, "benced image is corrupt"); + return p; + } + } + GRN_B_DEC(n, p); + /* confirm e->codes_size >= n */ + e->codes_curr = n; + for (i = 0, code = e->codes; i < n; i++, code++) { + GRN_B_DEC(code->op, p); + GRN_B_DEC(code->nargs, p); + GRN_B_DEC(type, p); + switch (type) { + case GRN_EXPR_PACK_TYPE_NULL : + code->value = NULL; + break; + case GRN_EXPR_PACK_TYPE_VARIABLE : + { + uint32_t offset; + GRN_B_DEC(offset, p); + code->value = &e->vars[i].value; + } + break; + case GRN_EXPR_PACK_TYPE_OTHERS : + { + uint32_t object_type; + GRN_B_DEC(object_type, p); + if (GRN_TYPE <= object_type && object_type <= GRN_COLUMN_INDEX) { + grn_id id; + GRN_B_DEC(id, p); + code->value = grn_ctx_at(ctx, id); + } else { + if (!(v = grn_expr_alloc_const(ctx, expr))) { return NULL; } + p = grn_obj_unpack(ctx, p, pe, object_type, GRN_OBJ_EXPRCONST, v); + code->value = v; + } + } + break; + } + if (pe < p) { + ERR(GRN_INVALID_FORMAT, "benced image is corrupt"); + return p; + } + } + return p; +} + +grn_obj * +grn_expr_open(grn_ctx *ctx, grn_obj_spec *spec, const uint8_t *p, const uint8_t *pe) +{ + grn_expr *expr = NULL; + if ((expr = GRN_MALLOCN(grn_expr, 1))) { + int size = GRN_STACK_SIZE; + expr->const_blks = NULL; + expr->nconsts = 0; + GRN_TEXT_INIT(&expr->name_buf, 0); + GRN_TEXT_INIT(&expr->dfi, 0); + GRN_PTR_INIT(&expr->objs, GRN_OBJ_VECTOR, GRN_ID_NIL); + expr->vars = NULL; + expr->nvars = 0; + GRN_DB_OBJ_SET_TYPE(expr, GRN_EXPR); + if ((expr->values = GRN_MALLOCN(grn_obj, size))) { + int i; + for (i = 0; i < size; i++) { + GRN_OBJ_INIT(&expr->values[i], GRN_BULK, GRN_OBJ_EXPRVALUE, GRN_ID_NIL); + } + expr->values_curr = 0; + expr->values_tail = 0; + expr->values_size = size; + if ((expr->codes = GRN_MALLOCN(grn_expr_code, size))) { + expr->codes_curr = 0; + expr->codes_size = size; + expr->obj.header = spec->header; + if (grn_expr_unpack(ctx, p, pe, (grn_obj *)expr) == pe) { + goto exit; + } else { + ERR(GRN_INVALID_FORMAT, "benced image is corrupt"); + } + GRN_FREE(expr->codes); + } + GRN_FREE(expr->values); + } + GRN_FREE(expr); + expr = NULL; + } +exit : + return (grn_obj *)expr; +} + +/* Pass ownership of `obj` to `expr`. */ +void +grn_expr_take_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj) +{ + grn_expr *e = (grn_expr *)expr; + GRN_PTR_PUT(ctx, &(e->objs), obj); +} + +/* data flow info */ +typedef struct { + grn_expr_code *code; + grn_id domain; + unsigned char type; +} grn_expr_dfi; + +static grn_expr_dfi * +grn_expr_dfi_pop(grn_expr *expr) +{ + if (GRN_BULK_VSIZE(&expr->dfi) >= sizeof(grn_expr_dfi)) { + grn_expr_dfi *dfi; + GRN_BULK_INCR_LEN(&expr->dfi, -((ssize_t)(sizeof(grn_expr_dfi)))); + dfi = (grn_expr_dfi *)GRN_BULK_CURR(&expr->dfi); + expr->code0 = dfi->code; + return dfi; + } else { + expr->code0 = NULL; + return NULL; + } +} + +static void +grn_expr_dfi_put(grn_ctx *ctx, grn_expr *expr, uint8_t type, grn_id domain, + grn_expr_code *code) +{ + grn_expr_dfi dfi; + dfi.type = type; + dfi.domain = domain; + dfi.code = code; + if (expr->code0) { + expr->code0->modify = code ? (code - expr->code0) : 0; + } + grn_bulk_write(ctx, &expr->dfi, (char *)&dfi, sizeof(grn_expr_dfi)); + expr->code0 = NULL; +} + +grn_obj * +grn_expr_create(grn_ctx *ctx, const char *name, unsigned int name_size) +{ + grn_id id; + grn_obj *db; + grn_expr *expr = NULL; + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "db not initialized"); + return NULL; + } + if (name_size) { + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "[expr][create] named expression isn't implemented yet"); + return NULL; + } + GRN_API_ENTER; + if (grn_db_check_name(ctx, name, name_size)) { + GRN_DB_CHECK_NAME_ERR("[expr][create]", name, name_size); + GRN_API_RETURN(NULL); + } + if (!GRN_DB_P(db)) { + ERR(GRN_INVALID_ARGUMENT, "named expr is not supported"); + GRN_API_RETURN(NULL); + } + id = grn_obj_register(ctx, db, name, name_size); + if (id && (expr = GRN_MALLOCN(grn_expr, 1))) { + int size = GRN_STACK_SIZE; + expr->const_blks = NULL; + expr->nconsts = 0; + GRN_TEXT_INIT(&expr->name_buf, 0); + GRN_TEXT_INIT(&expr->dfi, 0); + GRN_PTR_INIT(&expr->objs, GRN_OBJ_VECTOR, GRN_ID_NIL); + expr->code0 = NULL; + expr->vars = NULL; + expr->nvars = 0; + expr->cacheable = 1; + expr->taintable = 0; + expr->values_curr = 0; + expr->values_tail = 0; + expr->values_size = size; + expr->codes_curr = 0; + expr->codes_size = size; + GRN_DB_OBJ_SET_TYPE(expr, GRN_EXPR); + expr->obj.header.domain = GRN_ID_NIL; + expr->obj.range = GRN_ID_NIL; + if (!grn_db_obj_init(ctx, db, id, DB_OBJ(expr))) { + if ((expr->values = GRN_MALLOCN(grn_obj, size))) { + int i; + for (i = 0; i < size; i++) { + GRN_OBJ_INIT(&expr->values[i], GRN_BULK, GRN_OBJ_EXPRVALUE, GRN_ID_NIL); + } + if ((expr->codes = GRN_MALLOCN(grn_expr_code, size))) { + goto exit; + } + GRN_FREE(expr->values); + } + } + GRN_FREE(expr); + expr = NULL; + } +exit : + GRN_API_RETURN((grn_obj *)expr); +} + +grn_rc +grn_expr_close(grn_ctx *ctx, grn_obj *expr) +{ + uint32_t i, j; + grn_expr *e = (grn_expr *)expr; + GRN_API_ENTER; + /* + if (e->obj.header.domain) { + grn_hash_delete(ctx, ctx->impl->qe, &e->obj.header.domain, sizeof(grn_id), NULL); + } + */ + grn_expr_clear_vars(ctx, expr); + if (e->const_blks) { + uint32_t nblks = e->nconsts + GRN_EXPR_CONST_BLK_SIZE - 1; + nblks /= GRN_EXPR_CONST_BLK_SIZE; + for (i = 0; i < nblks; i++) { + uint32_t end; + if (i < nblks - 1) { + end = GRN_EXPR_CONST_BLK_SIZE; + } else { + end = ((e->nconsts - 1) % GRN_EXPR_CONST_BLK_SIZE) + 1; + } + for (j = 0; j < end; j++) { + grn_obj *const_obj = &e->const_blks[i][j]; + grn_obj_close(ctx, const_obj); + } + GRN_FREE(e->const_blks[i]); + } + GRN_FREE(e->const_blks); + } + grn_obj_close(ctx, &e->name_buf); + grn_obj_close(ctx, &e->dfi); + for (;;) { + grn_obj *obj; + GRN_PTR_POP(&e->objs, obj); + if (obj) { +#ifdef USE_MEMORY_DEBUG + grn_obj_unlink(ctx, obj); +#else + if (obj->header.type) { + if (obj->header.type == GRN_TABLE_HASH_KEY && + ((grn_hash *)obj)->value_size == sizeof(grn_obj)) { + grn_obj *value; + GRN_HASH_EACH(ctx, (grn_hash *)obj, id, NULL, NULL, (void **)&value, { + GRN_OBJ_FIN(ctx, value); + }); + } + grn_obj_unlink(ctx, obj); + } else { + GRN_LOG(ctx, GRN_LOG_WARNING, "GRN_VOID object is tried to be unlinked"); + } +#endif + } else { break; } + } + grn_obj_close(ctx, &e->objs); + for (i = 0; i < e->nvars; i++) { + grn_obj_close(ctx, &e->vars[i].value); + } + if (e->vars) { GRN_FREE(e->vars); } + for (i = 0; i < e->values_tail; i++) { + grn_obj_close(ctx, &e->values[i]); + } + GRN_FREE(e->values); + GRN_FREE(e->codes); + GRN_FREE(e); + GRN_API_RETURN(ctx->rc); +} + +grn_obj * +grn_expr_add_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size) +{ + uint32_t i; + char *p; + grn_expr_var *v; + grn_obj *res = NULL; + grn_expr *e = (grn_expr *)expr; + GRN_API_ENTER; + if (DB_OBJ(expr)->id & GRN_OBJ_TMP_OBJECT) { + res = grn_expr_get_or_add_var(ctx, expr, name, name_size); + } else { + if (!e->vars) { + if (!(e->vars = GRN_MALLOCN(grn_expr_var, GRN_STACK_SIZE))) { + ERR(GRN_NO_MEMORY_AVAILABLE, "malloc failed"); + } + } + if (e->vars && e->nvars < GRN_STACK_SIZE) { + v = e->vars + e->nvars++; + if (name_size) { + GRN_TEXT_PUT(ctx, &e->name_buf, name, name_size); + } else { + uint32_t ol = GRN_TEXT_LEN(&e->name_buf); + GRN_TEXT_PUTC(ctx, &e->name_buf, '$'); + grn_text_itoa(ctx, &e->name_buf, e->nvars); + name_size = GRN_TEXT_LEN(&e->name_buf) - ol; + } + v->name_size = name_size; + res = &v->value; + GRN_VOID_INIT(res); + for (i = e->nvars, p = GRN_TEXT_VALUE(&e->name_buf), v = e->vars; i; i--, v++) { + v->name = p; + p += v->name_size; + } + } + } + GRN_API_RETURN(res); +} + +grn_obj * +grn_expr_get_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size) +{ + uint32_t n; + grn_obj *res = NULL; + grn_hash *vars = grn_expr_get_vars(ctx, expr, &n); + if (vars) { grn_hash_get(ctx, vars, name, name_size, (void **)&res); } + return res; +} + +grn_obj * +grn_expr_get_or_add_var(grn_ctx *ctx, grn_obj *expr, const char *name, unsigned int name_size) +{ + uint32_t n; + grn_obj *res = NULL; + grn_hash *vars = grn_expr_get_vars(ctx, expr, &n); + if (vars) { + int added = 0; + char name_buf[16]; + if (!name_size) { + char *rest; + name_buf[0] = '$'; + grn_itoa((int)GRN_HASH_SIZE(vars) + 1, name_buf + 1, name_buf + 16, &rest); + name_size = rest - name_buf; + name = name_buf; + } + grn_hash_add(ctx, vars, name, name_size, (void **)&res, &added); + if (added) { GRN_TEXT_INIT(res, 0); } + } + return res; +} + +grn_obj * +grn_expr_get_var_by_offset(grn_ctx *ctx, grn_obj *expr, unsigned int offset) +{ + uint32_t n; + grn_obj *res = NULL; + grn_hash *vars = grn_expr_get_vars(ctx, expr, &n); + if (vars) { res = (grn_obj *)grn_hash_get_value_(ctx, vars, offset + 1, NULL); } + return res; +} + +#define EXPRVP(x) ((x)->header.impl_flags & GRN_OBJ_EXPRVALUE) + +#define CONSTP(obj) ((obj) && ((obj)->header.impl_flags & GRN_OBJ_EXPRCONST)) + +#define PUSH_CODE(e,o,v,n,c) do {\ + (c) = &(e)->codes[e->codes_curr++];\ + (c)->value = (v);\ + (c)->nargs = (n);\ + (c)->op = (o);\ + (c)->flags = 0;\ + (c)->modify = 0;\ +} while (0) + +#define APPEND_UNARY_MINUS_OP(e) do { \ + grn_expr_code *code_; \ + grn_id domain; \ + unsigned char type; \ + grn_obj *x; \ + dfi = grn_expr_dfi_pop(e); \ + code_ = dfi->code; \ + domain = dfi->domain; \ + type = dfi->type; \ + x = code_->value; \ + if (CONSTP(x)) { \ + switch (domain) { \ + case GRN_DB_INT32: \ + { \ + int value; \ + value = GRN_INT32_VALUE(x); \ + if (value == (int)0x80000000) { \ + domain = GRN_DB_INT64; \ + x->header.domain = domain; \ + GRN_INT64_SET(ctx, x, -((long long int)value)); \ + } else { \ + GRN_INT32_SET(ctx, x, -value); \ + } \ + } \ + break; \ + case GRN_DB_UINT32: \ + { \ + unsigned int value; \ + value = GRN_UINT32_VALUE(x); \ + if (value > (unsigned int)0x80000000) { \ + domain = GRN_DB_INT64; \ + x->header.domain = domain; \ + GRN_INT64_SET(ctx, x, -((long long int)value)); \ + } else { \ + domain = GRN_DB_INT32; \ + x->header.domain = domain; \ + GRN_INT32_SET(ctx, x, -((int)value)); \ + } \ + } \ + break; \ + case GRN_DB_INT64: \ + GRN_INT64_SET(ctx, x, -GRN_INT64_VALUE(x)); \ + break; \ + case GRN_DB_FLOAT: \ + GRN_FLOAT_SET(ctx, x, -GRN_FLOAT_VALUE(x)); \ + break; \ + default: \ + PUSH_CODE(e, op, obj, nargs, code); \ + break; \ + } \ + } else { \ + PUSH_CODE(e, op, obj, nargs, code); \ + } \ + grn_expr_dfi_put(ctx, e, type, domain, code_); \ +} while (0) + +#define PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code) do { \ + PUSH_CODE(e, op, obj, nargs, code); \ + { \ + int i = nargs; \ + while (i--) { \ + dfi = grn_expr_dfi_pop(e); \ + } \ + } \ + grn_expr_dfi_put(ctx, e, type, domain, code); \ +} while (0) + +static void +grn_expr_append_obj_resolve_const(grn_ctx *ctx, + grn_obj *obj, + grn_id to_domain) +{ + grn_obj dest; + + GRN_OBJ_INIT(&dest, GRN_BULK, 0, to_domain); + if (!grn_obj_cast(ctx, obj, &dest, GRN_FALSE)) { + grn_obj_reinit(ctx, obj, to_domain, 0); + grn_bulk_write(ctx, obj, GRN_BULK_HEAD(&dest), GRN_BULK_VSIZE(&dest)); + } + GRN_OBJ_FIN(ctx, &dest); +} + +grn_obj * +grn_expr_append_obj(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, grn_operator op, int nargs) +{ + uint8_t type = GRN_VOID; + grn_id domain = GRN_ID_NIL; + grn_expr_dfi *dfi; + grn_expr_code *code; + grn_obj *res = NULL; + grn_expr *e = (grn_expr *)expr; + GRN_API_ENTER; + if (e->codes_curr >= e->codes_size) { + grn_expr_dfi *dfis = (grn_expr_dfi *)GRN_BULK_HEAD(&e->dfi); + size_t i, n_dfis = GRN_BULK_VSIZE(&e->dfi) / sizeof(grn_expr_dfi); + uint32_t new_codes_size = e->codes_size * 2; + size_t n_bytes = sizeof(grn_expr_code) * new_codes_size; + grn_expr_code *new_codes = (grn_expr_code *)GRN_MALLOC(n_bytes); + if (!new_codes) { + ERR(GRN_NO_MEMORY_AVAILABLE, "stack is full"); + goto exit; + } + grn_memcpy(new_codes, e->codes, sizeof(grn_expr_code) * e->codes_size); + if (e->code0 >= e->codes && e->code0 < e->codes + e->codes_size) { + e->code0 = new_codes + (e->code0 - e->codes); + } + for (i = 0; i < n_dfis; i++) { + if (dfis[i].code >= e->codes && dfis[i].code < e->codes + e->codes_size) { + dfis[i].code = new_codes + (dfis[i].code - e->codes); + } + } + GRN_FREE(e->codes); + e->codes = new_codes; + e->codes_size = new_codes_size; + } + { + switch (op) { + case GRN_OP_PUSH : + if (obj) { + PUSH_CODE(e, op, obj, nargs, code); + grn_expr_dfi_put(ctx, e, obj->header.type, GRN_OBJ_GET_DOMAIN(obj), + code); + } else { + ERR(GRN_INVALID_ARGUMENT, "obj not assigned for GRN_OP_PUSH"); + goto exit; + } + break; + case GRN_OP_NOP : + /* nop */ + break; + case GRN_OP_POP : + if (obj) { + ERR(GRN_INVALID_ARGUMENT, "obj assigned for GRN_OP_POP"); + goto exit; + } else { + PUSH_CODE(e, op, obj, nargs, code); + dfi = grn_expr_dfi_pop(e); + } + break; + case GRN_OP_CALL : + { + grn_obj *proc = NULL; + /* + * This is for keeping backward compatibility. We want to + * handle all "nargs" means that "N items on stack are used (N + * items are popped)" but "nargs" for OP_CALL is used as "N + * arguments" not "N items on stack are used" historically. It + * means that called function isn't included in "nargs". + * + * We adjust "nargs" here to handle "code->nargs" more easily. + * If we don't adjust "nargs" here, we need to care + * "code->nargs" at all locations that use "code->nargs". We + * need to use "code->nargs + 1" for OP_CALL and "code->nargs" + * for not OP_CALL to compute N items should be popped. It's + * wired. So we adjust "nargs" here. + */ + nargs++; + if (e->codes_curr - (nargs - 1) > 0) { + int i; + grn_expr_code *code; + code = &(e->codes[e->codes_curr - 1]); + for (i = 0; i < nargs - 1; i++) { + int rest_n_codes = 1; + while (rest_n_codes > 0) { + rest_n_codes += code->nargs; + if (code->value) { + rest_n_codes--; + } + rest_n_codes--; + code--; + } + } + proc = code->value; + } + if (!proc) { + ERR(GRN_INVALID_ARGUMENT, "invalid function call expression"); + goto exit; + } + if (!(grn_obj_is_function_proc(ctx, proc) || + grn_obj_is_scorer_proc(ctx, proc) || + grn_obj_is_window_function_proc(ctx, proc))) { + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + switch (proc->header.type) { + case GRN_TABLE_HASH_KEY: + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_NO_KEY: + case GRN_COLUMN_FIX_SIZE: + case GRN_COLUMN_VAR_SIZE: + case GRN_COLUMN_INDEX: + grn_inspect_name(ctx, &buffer, proc); + break; + default: + grn_inspect(ctx, &buffer, proc); + break; + } + ERR(GRN_INVALID_ARGUMENT, "invalid function: <%.*s>", + (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + goto exit; + } + + PUSH_CODE(e, op, obj, nargs, code); + { + int i = nargs - 1; + while (i--) { dfi = grn_expr_dfi_pop(e); } + } + if (!obj) { dfi = grn_expr_dfi_pop(e); } + // todo : increment e->values_tail. + /* cannot identify type of return value */ + grn_expr_dfi_put(ctx, e, type, domain, code); + if (!grn_proc_is_stable(ctx, proc)) { + e->cacheable = 0; + } + } + break; + case GRN_OP_INTERN : + if (obj && CONSTP(obj)) { + grn_obj *value; + value = grn_expr_get_var(ctx, expr, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj)); + if (!value) { value = grn_ctx_get(ctx, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj)); } + if (value) { + obj = value; + op = GRN_OP_PUSH; + type = obj->header.type; + domain = GRN_OBJ_GET_DOMAIN(obj); + } + } + PUSH_CODE(e, op, obj, nargs, code); + grn_expr_dfi_put(ctx, e, type, domain, code); + break; + case GRN_OP_EQUAL : + PUSH_CODE(e, op, obj, nargs, code); + if (nargs) { + grn_id xd, yd = GRN_ID_NIL; + grn_obj *x, *y = NULL; + int i = nargs - 1; + if (obj) { + xd = GRN_OBJ_GET_DOMAIN(obj); + x = obj; + } else { + dfi = grn_expr_dfi_pop(e); + x = dfi->code->value; + xd = dfi->domain; + } + while (i--) { + dfi = grn_expr_dfi_pop(e); + y = dfi->code->value; + yd = dfi->domain; + } + if (CONSTP(x)) { + if (CONSTP(y)) { + /* todo */ + } else { + if (xd != yd) { + grn_expr_append_obj_resolve_const(ctx, x, yd); + } + } + } else { + if (CONSTP(y)) { + if (xd != yd) { + grn_expr_append_obj_resolve_const(ctx, y, xd); + } + } + } + } + grn_expr_dfi_put(ctx, e, type, domain, code); + break; + case GRN_OP_TABLE_CREATE : + case GRN_OP_EXPR_GET_VAR : + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + case GRN_OP_SIMILAR : + case GRN_OP_PREFIX : + case GRN_OP_SUFFIX : + case GRN_OP_NOT_EQUAL : + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + case GRN_OP_GEO_DISTANCE1 : + case GRN_OP_GEO_DISTANCE2 : + case GRN_OP_GEO_DISTANCE3 : + case GRN_OP_GEO_DISTANCE4 : + case GRN_OP_GEO_WITHINP5 : + case GRN_OP_GEO_WITHINP6 : + case GRN_OP_GEO_WITHINP8 : + case GRN_OP_OBJ_SEARCH : + case GRN_OP_TABLE_SELECT : + case GRN_OP_TABLE_SORT : + case GRN_OP_TABLE_GROUP : + case GRN_OP_JSON_PUT : + case GRN_OP_GET_REF : + case GRN_OP_ADJUST : + case GRN_OP_TERM_EXTRACT : + case GRN_OP_REGEXP : + PUSH_CODE(e, op, obj, nargs, code); + if (nargs) { + int i = nargs - 1; + if (!obj) { dfi = grn_expr_dfi_pop(e); } + while (i--) { dfi = grn_expr_dfi_pop(e); } + } + grn_expr_dfi_put(ctx, e, type, domain, code); + break; + case GRN_OP_AND : + case GRN_OP_OR : + case GRN_OP_AND_NOT : + PUSH_CODE(e, op, obj, nargs, code); + if (nargs != 2) { + GRN_LOG(ctx, GRN_LOG_WARNING, "nargs(%d) != 2 in relative op", nargs); + } + if (obj) { + GRN_LOG(ctx, GRN_LOG_WARNING, "obj assigned to relative op"); + } + { + int i = nargs; + while (i--) { + dfi = grn_expr_dfi_pop(e); + if (dfi) { + dfi->code->flags |= GRN_EXPR_CODE_RELATIONAL_EXPRESSION; + } else { + ERR(GRN_SYNTAX_ERROR, "stack under flow in relative op"); + } + } + } + grn_expr_dfi_put(ctx, e, type, domain, code); + break; + case GRN_OP_NOT : + if (nargs == 1) { + PUSH_CODE(e, op, obj, nargs, code); + } + break; + case GRN_OP_PLUS : + if (nargs > 1) { + PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code); + } + break; + case GRN_OP_MINUS : + if (nargs == 1) { + APPEND_UNARY_MINUS_OP(e); + } else { + PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code); + } + break; + case GRN_OP_BITWISE_NOT : + dfi = grn_expr_dfi_pop(e); + if (dfi) { + type = dfi->type; + domain = dfi->domain; + switch (domain) { + case GRN_DB_UINT8 : + domain = GRN_DB_INT16; + break; + case GRN_DB_UINT16 : + domain = GRN_DB_INT32; + break; + case GRN_DB_UINT32 : + case GRN_DB_UINT64 : + domain = GRN_DB_INT64; + break; + } + } + PUSH_CODE(e, op, obj, nargs, code); + grn_expr_dfi_put(ctx, e, type, domain, code); + break; + case GRN_OP_STAR : + case GRN_OP_SLASH : + case GRN_OP_MOD : + case GRN_OP_SHIFTL : + case GRN_OP_SHIFTR : + case GRN_OP_SHIFTRR : + case GRN_OP_BITWISE_OR : + case GRN_OP_BITWISE_XOR : + case GRN_OP_BITWISE_AND : + PUSH_N_ARGS_ARITHMETIC_OP(e, op, obj, nargs, code); + break; + case GRN_OP_INCR : + case GRN_OP_DECR : + case GRN_OP_INCR_POST : + case GRN_OP_DECR_POST : + { + dfi = grn_expr_dfi_pop(e); + if (dfi) { + type = dfi->type; + domain = dfi->domain; + if (dfi->code) { + if (dfi->code->op == GRN_OP_GET_VALUE) { + dfi->code->op = GRN_OP_GET_REF; + } + if (dfi->code->value && grn_obj_is_persistent(ctx, dfi->code->value)) { + e->cacheable = 0; + e->taintable = 1; + } + } + } + PUSH_CODE(e, op, obj, nargs, code); + } + grn_expr_dfi_put(ctx, e, type, domain, code); + break; + case GRN_OP_GET_VALUE : + { + grn_id vdomain = GRN_ID_NIL; + if (obj) { + if (nargs == 1) { + grn_obj *v = grn_expr_get_var_by_offset(ctx, expr, 0); + if (v) { vdomain = GRN_OBJ_GET_DOMAIN(v); } + } else { + dfi = grn_expr_dfi_pop(e); + vdomain = dfi->domain; + } + if (vdomain && CONSTP(obj) && obj->header.type == GRN_BULK) { + grn_obj *table = grn_ctx_at(ctx, vdomain); + grn_obj *col = grn_obj_column(ctx, table, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj)); + if (col) { + obj = col; + type = col->header.type; + domain = grn_obj_get_range(ctx, col); + grn_expr_take_obj(ctx, (grn_obj *)e, col); + } + } else { + domain = grn_obj_get_range(ctx, obj); + } + PUSH_CODE(e, op, obj, nargs, code); + } else { + grn_expr_dfi *dfi0; + dfi0 = grn_expr_dfi_pop(e); + if (nargs == 1) { + grn_obj *v = grn_expr_get_var_by_offset(ctx, expr, 0); + if (v) { vdomain = GRN_OBJ_GET_DOMAIN(v); } + } else { + dfi = grn_expr_dfi_pop(e); + vdomain = dfi->domain; + } + if (dfi0->code->op == GRN_OP_PUSH) { + dfi0->code->op = op; + dfi0->code->nargs = nargs; + obj = dfi0->code->value; + if (vdomain && obj && CONSTP(obj) && obj->header.type == GRN_BULK) { + grn_obj *table = grn_ctx_at(ctx, vdomain); + grn_obj *col = grn_obj_column(ctx, table, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj)); + if (col) { + dfi0->code->value = col; + type = col->header.type; + domain = grn_obj_get_range(ctx, col); + grn_obj_unlink(ctx, col); + } + } else { + domain = grn_obj_get_range(ctx, obj); + } + code = dfi0->code; + } else { + PUSH_CODE(e, op, obj, nargs, code); + } + } + } + grn_expr_dfi_put(ctx, e, type, domain, code); + break; + case GRN_OP_ASSIGN : + case GRN_OP_STAR_ASSIGN : + case GRN_OP_SLASH_ASSIGN : + case GRN_OP_MOD_ASSIGN : + case GRN_OP_PLUS_ASSIGN : + case GRN_OP_MINUS_ASSIGN : + case GRN_OP_SHIFTL_ASSIGN : + case GRN_OP_SHIFTR_ASSIGN : + case GRN_OP_SHIFTRR_ASSIGN : + case GRN_OP_AND_ASSIGN : + case GRN_OP_OR_ASSIGN : + case GRN_OP_XOR_ASSIGN : + { + if (obj) { + type = obj->header.type; + domain = GRN_OBJ_GET_DOMAIN(obj); + } else { + dfi = grn_expr_dfi_pop(e); + if (dfi) { + type = dfi->type; + domain = dfi->domain; + } + } + dfi = grn_expr_dfi_pop(e); + if (dfi && (dfi->code)) { + if (dfi->code->op == GRN_OP_GET_VALUE) { + dfi->code->op = GRN_OP_GET_REF; + } + if (dfi->code->value && grn_obj_is_persistent(ctx, dfi->code->value)) { + e->cacheable = 0; + e->taintable = 1; + } + } + PUSH_CODE(e, op, obj, nargs, code); + } + grn_expr_dfi_put(ctx, e, type, domain, code); + break; + case GRN_OP_JUMP : + dfi = grn_expr_dfi_pop(e); + PUSH_CODE(e, op, obj, nargs, code); + break; + case GRN_OP_CJUMP : + dfi = grn_expr_dfi_pop(e); + PUSH_CODE(e, op, obj, nargs, code); + break; + case GRN_OP_COMMA : + PUSH_CODE(e, op, obj, nargs, code); + break; + case GRN_OP_GET_MEMBER : + dfi = grn_expr_dfi_pop(e); + dfi = grn_expr_dfi_pop(e); + if (dfi) { + type = dfi->type; + domain = dfi->domain; + if (dfi->code) { + if (dfi->code->op == GRN_OP_GET_VALUE) { + dfi->code->op = GRN_OP_GET_REF; + } + } + } + PUSH_CODE(e, op, obj, nargs, code); + grn_expr_dfi_put(ctx, e, type, domain, code); + break; + default : + break; + } + } +exit : + if (!ctx->rc) { res = obj; } + GRN_API_RETURN(res); +} +#undef PUSH_N_ARGS_ARITHMETIC_OP +#undef APPEND_UNARY_MINUS_OP + +grn_obj * +grn_expr_append_const(grn_ctx *ctx, grn_obj *expr, grn_obj *obj, + grn_operator op, int nargs) +{ + grn_obj *res = NULL; + GRN_API_ENTER; + if (!obj) { + ERR(GRN_SYNTAX_ERROR, "constant is null"); + goto exit; + } + if (GRN_DB_OBJP(obj) || GRN_ACCESSORP(obj)) { + res = obj; + } else { + if ((res = grn_expr_alloc_const(ctx, expr))) { + switch (obj->header.type) { + case GRN_VOID : + case GRN_BULK : + case GRN_UVECTOR : + GRN_OBJ_INIT(res, obj->header.type, 0, obj->header.domain); + grn_bulk_write(ctx, res, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj)); + break; + default : + res = NULL; + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "unsupported type"); + goto exit; + } + res->header.impl_flags |= GRN_OBJ_EXPRCONST; + } + } + grn_expr_append_obj(ctx, expr, res, op, nargs); /* constant */ +exit : + GRN_API_RETURN(res); +} + +static grn_obj * +grn_expr_add_str(grn_ctx *ctx, grn_obj *expr, const char *str, unsigned int str_size) +{ + grn_obj *res = NULL; + if ((res = grn_expr_alloc_const(ctx, expr))) { + GRN_TEXT_INIT(res, 0); + grn_bulk_write(ctx, res, str, str_size); + res->header.impl_flags |= GRN_OBJ_EXPRCONST; + } + return res; +} + +grn_obj * +grn_expr_append_const_str(grn_ctx *ctx, grn_obj *expr, const char *str, unsigned int str_size, + grn_operator op, int nargs) +{ + grn_obj *res; + GRN_API_ENTER; + res = grn_expr_add_str(ctx, expr, str, str_size); + grn_expr_append_obj(ctx, expr, res, op, nargs); /* constant */ + GRN_API_RETURN(res); +} + +grn_obj * +grn_expr_append_const_int(grn_ctx *ctx, grn_obj *expr, int i, + grn_operator op, int nargs) +{ + grn_obj *res = NULL; + GRN_API_ENTER; + if ((res = grn_expr_alloc_const(ctx, expr))) { + GRN_INT32_INIT(res, 0); + GRN_INT32_SET(ctx, res, i); + res->header.impl_flags |= GRN_OBJ_EXPRCONST; + } + grn_expr_append_obj(ctx, expr, res, op, nargs); /* constant */ + GRN_API_RETURN(res); +} + +grn_rc +grn_expr_append_op(grn_ctx *ctx, grn_obj *expr, grn_operator op, int nargs) +{ + grn_expr_append_obj(ctx, expr, NULL, op, nargs); + return ctx->rc; +} + +grn_rc +grn_expr_compile(grn_ctx *ctx, grn_obj *expr) +{ + grn_obj_spec_save(ctx, DB_OBJ(expr)); + return ctx->rc; +} + +grn_obj * +grn_expr_rewrite(grn_ctx *ctx, grn_obj *expr) +{ + grn_obj *rewritten = NULL; + + GRN_API_ENTER; + +#ifdef GRN_WITH_MRUBY + grn_ctx_impl_mrb_ensure_init(ctx); + if (ctx->rc != GRN_SUCCESS) { + GRN_API_RETURN(NULL); + } + if (ctx->impl->mrb.state) { + rewritten = grn_mrb_expr_rewrite(ctx, expr); + } +#endif + + GRN_API_RETURN(rewritten); +} + +#define WITH_SPSAVE(block) do {\ + ctx->impl->stack_curr = sp - ctx->impl->stack;\ + e->values_curr = vp - e->values;\ + block\ + vp = e->values + e->values_curr;\ + sp = ctx->impl->stack + ctx->impl->stack_curr;\ + s0 = sp[-1];\ + s1 = sp[-2];\ +} while (0) + +#define GEO_RESOLUTION 3600000 +#define GEO_RADIOUS 6357303 +#define GEO_BES_C1 6334834 +#define GEO_BES_C2 6377397 +#define GEO_BES_C3 0.006674 +#define GEO_GRS_C1 6335439 +#define GEO_GRS_C2 6378137 +#define GEO_GRS_C3 0.006694 +#define GEO_INT2RAD(x) ((M_PI * x) / (GEO_RESOLUTION * 180)) + +#define VAR_SET_VALUE(ctx,var,value) do {\ + if (GRN_DB_OBJP(value)) {\ + (var)->header.type = GRN_PTR;\ + (var)->header.domain = DB_OBJ(value)->id;\ + GRN_PTR_SET(ctx, (var), (value));\ + } else {\ + (var)->header.type = (value)->header.type;\ + (var)->header.domain = (value)->header.domain;\ + GRN_TEXT_SET(ctx, (var), GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value));\ + }\ +} while (0) + +grn_rc +grn_proc_call(grn_ctx *ctx, grn_obj *proc, int nargs, grn_obj *caller) +{ + grn_proc_ctx pctx; + grn_obj *obj = NULL, **args; + grn_proc *p = (grn_proc *)proc; + if (nargs > ctx->impl->stack_curr) { return GRN_INVALID_ARGUMENT; } + GRN_API_ENTER; + if (grn_obj_is_selector_only_proc(ctx, proc)) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_obj_name(ctx, proc, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "selector only proc can't be called: <%.*s>", + name_size, name); + GRN_API_RETURN(ctx->rc); + } + args = ctx->impl->stack + ctx->impl->stack_curr - nargs; + pctx.proc = p; + pctx.caller = caller; + pctx.user_data.ptr = NULL; + if (p->funcs[PROC_INIT]) { + grn_obj *sub_obj; + sub_obj = p->funcs[PROC_INIT](ctx, nargs, args, &pctx.user_data); + if (sub_obj) { + obj = sub_obj; + } + } + pctx.phase = PROC_NEXT; + if (p->funcs[PROC_NEXT]) { + grn_obj *sub_obj; + sub_obj = p->funcs[PROC_NEXT](ctx, nargs, args, &pctx.user_data); + if (sub_obj) { + obj = sub_obj; + } + } + pctx.phase = PROC_FIN; + if (p->funcs[PROC_FIN]) { + grn_obj *sub_obj; + sub_obj = p->funcs[PROC_FIN](ctx, nargs, args, &pctx.user_data); + if (sub_obj) { + obj = sub_obj; + } + } + ctx->impl->stack_curr -= nargs; + grn_ctx_push(ctx, obj); + GRN_API_RETURN(ctx->rc); +} + +#define PUSH1(v) do {\ + if (EXPRVP(v)) {\ + vp++;\ + if (vp - e->values > e->values_tail) { e->values_tail = vp - e->values; }\ + }\ + s1 = s0;\ + *sp++ = s0 = v;\ +} while (0) + +#define POP1(v) do {\ + if (EXPRVP(s0)) { vp--; }\ + v = s0;\ + s0 = s1;\ + sp--;\ + if (sp < s_) { ERR(GRN_INVALID_ARGUMENT, "stack underflow"); goto exit; }\ + s1 = sp[-2];\ +} while (0) + +#define ALLOC1(value) do {\ + s1 = s0;\ + *sp++ = s0 = value = vp++;\ + if (vp - e->values > e->values_tail) { e->values_tail = vp - e->values; }\ +} while (0) + +#define POP1ALLOC1(arg,value) do {\ + arg = s0;\ + if (EXPRVP(s0)) {\ + value = s0;\ + } else {\ + if (sp < s_ + 1) { ERR(GRN_INVALID_ARGUMENT, "stack underflow"); goto exit; }\ + sp[-1] = s0 = value = vp++;\ + if (vp - e->values > e->values_tail) { e->values_tail = vp - e->values; }\ + s0->header.impl_flags |= GRN_OBJ_EXPRVALUE;\ + }\ +} while (0) + +#define POP2ALLOC1(arg1,arg2,value) do {\ + if (EXPRVP(s0)) { vp--; }\ + if (EXPRVP(s1)) { vp--; }\ + arg2 = s0;\ + arg1 = s1;\ + sp--;\ + if (sp < s_ + 1) { ERR(GRN_INVALID_ARGUMENT, "stack underflow"); goto exit; }\ + s1 = sp[-2];\ + sp[-1] = s0 = value = vp++;\ + if (vp - e->values > e->values_tail) { e->values_tail = vp - e->values; }\ + s0->header.impl_flags |= GRN_OBJ_EXPRVALUE;\ +} while (0) + +#define INTEGER_ARITHMETIC_OPERATION_PLUS(x, y) ((x) + (y)) +#define FLOAT_ARITHMETIC_OPERATION_PLUS(x, y) ((double)(x) + (double)(y)) +#define INTEGER_ARITHMETIC_OPERATION_MINUS(x, y) ((x) - (y)) +#define FLOAT_ARITHMETIC_OPERATION_MINUS(x, y) ((double)(x) - (double)(y)) +#define INTEGER_ARITHMETIC_OPERATION_STAR(x, y) ((x) * (y)) +#define FLOAT_ARITHMETIC_OPERATION_STAR(x, y) ((double)(x) * (double)(y)) +#define INTEGER_ARITHMETIC_OPERATION_SLASH(x, y) ((x) / (y)) +#define FLOAT_ARITHMETIC_OPERATION_SLASH(x, y) ((double)(x) / (double)(y)) +#define INTEGER_ARITHMETIC_OPERATION_MOD(x, y) ((x) % (y)) +#define FLOAT_ARITHMETIC_OPERATION_MOD(x, y) (fmod((x), (y))) +#define INTEGER_ARITHMETIC_OPERATION_SHIFTL(x, y) ((x) << (y)) +#define FLOAT_ARITHMETIC_OPERATION_SHIFTL(x, y) \ + ((long long int)(x) << (long long int)(y)) +#define INTEGER_ARITHMETIC_OPERATION_SHIFTR(x, y) ((x) >> (y)) +#define FLOAT_ARITHMETIC_OPERATION_SHIFTR(x, y) \ + ((long long int)(x) >> (long long int)(y)) +#define INTEGER8_ARITHMETIC_OPERATION_SHIFTRR(x, y) \ + ((uint8_t)(x) >> (y)) +#define INTEGER16_ARITHMETIC_OPERATION_SHIFTRR(x, y) \ + ((uint16_t)(x) >> (y)) +#define INTEGER32_ARITHMETIC_OPERATION_SHIFTRR(x, y) \ + ((unsigned int)(x) >> (y)) +#define INTEGER64_ARITHMETIC_OPERATION_SHIFTRR(x, y) \ + ((long long unsigned int)(x) >> (y)) +#define FLOAT_ARITHMETIC_OPERATION_SHIFTRR(x, y) \ + ((long long unsigned int)(x) >> (long long unsigned int)(y)) + +#define INTEGER_ARITHMETIC_OPERATION_BITWISE_OR(x, y) ((x) | (y)) +#define FLOAT_ARITHMETIC_OPERATION_BITWISE_OR(x, y) \ + ((long long int)(x) | (long long int)(y)) +#define INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR(x, y) ((x) ^ (y)) +#define FLOAT_ARITHMETIC_OPERATION_BITWISE_XOR(x, y) \ + ((long long int)(x) ^ (long long int)(y)) +#define INTEGER_ARITHMETIC_OPERATION_BITWISE_AND(x, y) ((x) & (y)) +#define FLOAT_ARITHMETIC_OPERATION_BITWISE_AND(x, y) \ + ((long long int)(x) & (long long int)(y)) + +#define INTEGER_UNARY_ARITHMETIC_OPERATION_MINUS(x) (-(x)) +#define FLOAT_UNARY_ARITHMETIC_OPERATION_MINUS(x) (-(x)) +#define INTEGER_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT(x) (~(x)) +#define FLOAT_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT(x) \ + (~((long long int)(x))) + +#define TEXT_ARITHMETIC_OPERATION(operator) do { \ + long long int x_; \ + long long int y_; \ + \ + res->header.domain = GRN_DB_INT64; \ + \ + GRN_INT64_SET(ctx, res, 0); \ + grn_obj_cast(ctx, x, res, GRN_FALSE); \ + x_ = GRN_INT64_VALUE(res); \ + \ + GRN_INT64_SET(ctx, res, 0); \ + grn_obj_cast(ctx, y, res, GRN_FALSE); \ + y_ = GRN_INT64_VALUE(res); \ + \ + GRN_INT64_SET(ctx, res, x_ operator y_); \ +} while (0) + +#define TEXT_UNARY_ARITHMETIC_OPERATION(unary_operator) do { \ + long long int x_; \ + \ + res->header.domain = GRN_DB_INT64; \ + \ + GRN_INT64_SET(ctx, res, 0); \ + grn_obj_cast(ctx, x, res, GRN_FALSE); \ + x_ = GRN_INT64_VALUE(res); \ + \ + GRN_INT64_SET(ctx, res, unary_operator x_); \ +} while (0) + +#define ARITHMETIC_OPERATION_NO_CHECK(y) do {} while (0) +#define ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y) do { \ + if ((long long int)y == 0) { \ + ERR(GRN_INVALID_ARGUMENT, "divisor should not be 0"); \ + goto exit; \ + } \ +} while (0) + + +#define NUMERIC_ARITHMETIC_OPERATION_DISPATCH(set, get, x_, y, res, \ + integer_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error) do { \ + switch (y->header.domain) { \ + case GRN_DB_INT8 : \ + { \ + int8_t y_; \ + y_ = GRN_INT8_VALUE(y); \ + right_expression_check(y_); \ + set(ctx, res, integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_UINT8 : \ + { \ + uint8_t y_; \ + y_ = GRN_UINT8_VALUE(y); \ + right_expression_check(y_); \ + set(ctx, res, integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_INT16 : \ + { \ + int16_t y_; \ + y_ = GRN_INT16_VALUE(y); \ + right_expression_check(y_); \ + set(ctx, res, integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_UINT16 : \ + { \ + uint16_t y_; \ + y_ = GRN_UINT16_VALUE(y); \ + right_expression_check(y_); \ + set(ctx, res, integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_INT32 : \ + { \ + int y_; \ + y_ = GRN_INT32_VALUE(y); \ + right_expression_check(y_); \ + set(ctx, res, integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_UINT32 : \ + { \ + unsigned int y_; \ + y_ = GRN_UINT32_VALUE(y); \ + right_expression_check(y_); \ + set(ctx, res, integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_TIME : \ + { \ + long long int y_; \ + y_ = GRN_TIME_VALUE(y); \ + right_expression_check(y_); \ + set(ctx, res, integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_INT64 : \ + { \ + long long int y_; \ + y_ = GRN_INT64_VALUE(y); \ + right_expression_check(y_); \ + set(ctx, res, integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_UINT64 : \ + { \ + long long unsigned int y_; \ + y_ = GRN_UINT64_VALUE(y); \ + right_expression_check(y_); \ + set(ctx, res, integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_FLOAT : \ + { \ + double y_; \ + y_ = GRN_FLOAT_VALUE(y); \ + right_expression_check(y_); \ + res->header.domain = GRN_DB_FLOAT; \ + GRN_FLOAT_SET(ctx, res, float_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_SHORT_TEXT : \ + case GRN_DB_TEXT : \ + case GRN_DB_LONG_TEXT : \ + set(ctx, res, 0); \ + if (grn_obj_cast(ctx, y, res, GRN_FALSE)) { \ + ERR(GRN_INVALID_ARGUMENT, \ + "not a numerical format: <%.*s>", \ + (int)GRN_TEXT_LEN(y), GRN_TEXT_VALUE(y)); \ + goto exit; \ + } \ + set(ctx, res, integer_operation(x_, get(res))); \ + break; \ + default : \ + invalid_type_error; \ + break; \ + } \ +} while (0) + + +#define ARITHMETIC_OPERATION_DISPATCH(x, y, res, \ + integer8_operation, \ + integer16_operation, \ + integer32_operation, \ + integer64_operation, \ + float_operation, \ + left_expression_check, \ + right_expression_check, \ + text_operation, \ + invalid_type_error) do { \ + switch (x->header.domain) { \ + case GRN_DB_INT8 : \ + { \ + int8_t x_; \ + x_ = GRN_INT8_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT8_SET, \ + GRN_INT8_VALUE, \ + x_, y, res, \ + integer8_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_UINT8 : \ + { \ + uint8_t x_; \ + x_ = GRN_UINT8_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT8_SET, \ + GRN_UINT8_VALUE, \ + x_, y, res, \ + integer8_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_INT16 : \ + { \ + int16_t x_; \ + x_ = GRN_INT16_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT16_SET, \ + GRN_INT16_VALUE, \ + x_, y, res, \ + integer16_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_UINT16 : \ + { \ + uint16_t x_; \ + x_ = GRN_UINT16_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT16_SET, \ + GRN_UINT16_VALUE, \ + x_, y, res, \ + integer16_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_INT32 : \ + { \ + int x_; \ + x_ = GRN_INT32_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT32_SET, \ + GRN_INT32_VALUE, \ + x_, y, res, \ + integer32_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_UINT32 : \ + { \ + unsigned int x_; \ + x_ = GRN_UINT32_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT32_SET, \ + GRN_UINT32_VALUE, \ + x_, y, res, \ + integer32_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_INT64 : \ + { \ + long long int x_; \ + x_ = GRN_INT64_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_INT64_SET, \ + GRN_INT64_VALUE, \ + x_, y, res, \ + integer64_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_TIME : \ + { \ + long long int x_; \ + x_ = GRN_TIME_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_TIME_SET, \ + GRN_TIME_VALUE, \ + x_, y, res, \ + integer64_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_UINT64 : \ + { \ + long long unsigned int x_; \ + x_ = GRN_UINT64_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_UINT64_SET, \ + GRN_UINT64_VALUE, \ + x_, y, res, \ + integer64_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_FLOAT : \ + { \ + double x_; \ + x_ = GRN_FLOAT_VALUE(x); \ + left_expression_check(x_); \ + NUMERIC_ARITHMETIC_OPERATION_DISPATCH(GRN_FLOAT_SET, \ + GRN_FLOAT_VALUE, \ + x_, y, res, \ + float_operation, \ + float_operation, \ + right_expression_check, \ + invalid_type_error); \ + } \ + break; \ + case GRN_DB_SHORT_TEXT : \ + case GRN_DB_TEXT : \ + case GRN_DB_LONG_TEXT : \ + text_operation; \ + break; \ + default: \ + invalid_type_error; \ + break; \ + } \ + code++; \ +} while (0) + +#define ARITHMETIC_BINARY_OPERATION_DISPATCH(operator, \ + integer8_operation, \ + integer16_operation, \ + integer32_operation, \ + integer64_operation, \ + float_operation, \ + left_expression_check, \ + right_expression_check, \ + text_operation, \ + invalid_type_error) do { \ + grn_obj *x, *y; \ + \ + POP2ALLOC1(x, y, res); \ + if (x->header.type == GRN_VECTOR || y->header.type == GRN_VECTOR) { \ + grn_obj inspected_x; \ + grn_obj inspected_y; \ + GRN_TEXT_INIT(&inspected_x, 0); \ + GRN_TEXT_INIT(&inspected_y, 0); \ + grn_inspect(ctx, &inspected_x, x); \ + grn_inspect(ctx, &inspected_y, y); \ + ERR(GRN_INVALID_ARGUMENT, \ + "<%s> doesn't support vector: <%.*s> %s <%.*s>", \ + operator, \ + (int)GRN_TEXT_LEN(&inspected_x), GRN_TEXT_VALUE(&inspected_x), \ + operator, \ + (int)GRN_TEXT_LEN(&inspected_y), GRN_TEXT_VALUE(&inspected_y)); \ + GRN_OBJ_FIN(ctx, &inspected_x); \ + GRN_OBJ_FIN(ctx, &inspected_y); \ + goto exit; \ + } \ + if (y != res) { \ + res->header.domain = x->header.domain; \ + } \ + ARITHMETIC_OPERATION_DISPATCH(x, y, res, \ + integer8_operation, \ + integer16_operation, \ + integer32_operation, \ + integer64_operation, \ + float_operation, \ + left_expression_check, \ + right_expression_check, \ + text_operation, \ + invalid_type_error); \ + if (y == res) { \ + res->header.domain = x->header.domain; \ + } \ +} while (0) + +#define SIGNED_INTEGER_DIVISION_OPERATION_SLASH(x, y) \ + ((y == -1) ? -(x) : (x) / (y)) +#define UNSIGNED_INTEGER_DIVISION_OPERATION_SLASH(x, y) ((x) / (y)) +#define FLOAT_DIVISION_OPERATION_SLASH(x, y) ((double)(x) / (double)(y)) +#define SIGNED_INTEGER_DIVISION_OPERATION_MOD(x, y) ((y == -1) ? 0 : (x) % (y)) +#define UNSIGNED_INTEGER_DIVISION_OPERATION_MOD(x, y) ((x) % (y)) +#define FLOAT_DIVISION_OPERATION_MOD(x, y) (fmod((x), (y))) + +#define DIVISION_OPERATION_DISPATCH_RIGHT(set, get, x_, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation) do { \ + switch (y->header.domain) { \ + case GRN_DB_INT8 : \ + { \ + int y_; \ + y_ = GRN_INT8_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + set(ctx, res, signed_integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_UINT8 : \ + { \ + int y_; \ + y_ = GRN_UINT8_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + set(ctx, res, unsigned_integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_INT16 : \ + { \ + int y_; \ + y_ = GRN_INT16_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + set(ctx, res, signed_integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_UINT16 : \ + { \ + int y_; \ + y_ = GRN_UINT16_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + set(ctx, res, unsigned_integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_INT32 : \ + { \ + int y_; \ + y_ = GRN_INT32_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + set(ctx, res, signed_integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_UINT32 : \ + { \ + unsigned int y_; \ + y_ = GRN_UINT32_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + set(ctx, res, unsigned_integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_TIME : \ + { \ + long long int y_; \ + y_ = GRN_TIME_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + set(ctx, res, signed_integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_INT64 : \ + { \ + long long int y_; \ + y_ = GRN_INT64_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + set(ctx, res, signed_integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_UINT64 : \ + { \ + long long unsigned int y_; \ + y_ = GRN_UINT64_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + set(ctx, res, unsigned_integer_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_FLOAT : \ + { \ + double y_; \ + y_ = GRN_FLOAT_VALUE(y); \ + ARITHMETIC_OPERATION_ZERO_DIVISION_CHECK(y_); \ + res->header.domain = GRN_DB_FLOAT; \ + GRN_FLOAT_SET(ctx, res, float_operation(x_, y_)); \ + } \ + break; \ + case GRN_DB_SHORT_TEXT : \ + case GRN_DB_TEXT : \ + case GRN_DB_LONG_TEXT : \ + set(ctx, res, 0); \ + if (grn_obj_cast(ctx, y, res, GRN_FALSE)) { \ + ERR(GRN_INVALID_ARGUMENT, \ + "not a numerical format: <%.*s>", \ + (int)GRN_TEXT_LEN(y), GRN_TEXT_VALUE(y)); \ + goto exit; \ + } \ + /* The following "+ 0" is needed to suppress warnings that say */ \ + /* comparison is always false due to limited range of data type */ \ + set(ctx, res, signed_integer_operation(x_, (get(res) + 0))); \ + break; \ + default : \ + break; \ + } \ +} while (0) + +#define DIVISION_OPERATION_DISPATCH_LEFT(x, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation, \ + invalid_type_error) do { \ + switch (x->header.domain) { \ + case GRN_DB_INT8 : \ + { \ + int x_; \ + x_ = GRN_INT8_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_INT8_SET, \ + GRN_INT8_VALUE, \ + x_, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_UINT8 : \ + { \ + int x_; \ + x_ = GRN_UINT8_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_UINT8_SET, \ + (int)GRN_UINT8_VALUE, \ + x_, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_INT16 : \ + { \ + int x_; \ + x_ = GRN_INT16_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_INT16_SET, \ + GRN_INT16_VALUE, \ + x_, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_UINT16 : \ + { \ + int x_; \ + x_ = GRN_UINT16_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_UINT16_SET, \ + (int)GRN_UINT16_VALUE, \ + x_, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_INT32 : \ + { \ + int x_; \ + x_ = GRN_INT32_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_INT32_SET, \ + GRN_INT32_VALUE, \ + x_, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_UINT32 : \ + { \ + unsigned int x_; \ + x_ = GRN_UINT32_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_UINT32_SET, \ + GRN_UINT32_VALUE, \ + x_, y, res, \ + unsigned_integer_operation, \ + unsigned_integer_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_INT64 : \ + { \ + long long int x_; \ + x_ = GRN_INT64_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_INT64_SET, \ + GRN_INT64_VALUE, \ + x_, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_TIME : \ + { \ + long long int x_; \ + x_ = GRN_TIME_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_TIME_SET, \ + GRN_TIME_VALUE, \ + x_, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_UINT64 : \ + { \ + long long unsigned int x_; \ + x_ = GRN_UINT64_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_UINT64_SET, \ + GRN_UINT64_VALUE, \ + x_, y, res, \ + unsigned_integer_operation, \ + unsigned_integer_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_FLOAT : \ + { \ + double x_; \ + x_ = GRN_FLOAT_VALUE(x); \ + DIVISION_OPERATION_DISPATCH_RIGHT(GRN_FLOAT_SET, \ + GRN_FLOAT_VALUE, \ + x_, y, res, \ + float_operation, \ + float_operation, \ + float_operation); \ + } \ + break; \ + case GRN_DB_SHORT_TEXT : \ + case GRN_DB_TEXT : \ + case GRN_DB_LONG_TEXT : \ + invalid_type_error; \ + break; \ + default: \ + break; \ + } \ + code++; \ +} while (0) + +#define DIVISION_OPERATION_DISPATCH(signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation, \ + invalid_type_error) do { \ + grn_obj *x, *y; \ + \ + POP2ALLOC1(x, y, res); \ + if (y != res) { \ + res->header.domain = x->header.domain; \ + } \ + DIVISION_OPERATION_DISPATCH_LEFT(x, y, res, \ + signed_integer_operation, \ + unsigned_integer_operation, \ + float_operation, \ + invalid_type_error); \ + if (y == res) { \ + res->header.domain = x->header.domain; \ + } \ +} while (0) + +#define ARITHMETIC_UNARY_OPERATION_DISPATCH(integer_operation, \ + float_operation, \ + left_expression_check, \ + right_expression_check, \ + text_operation, \ + invalid_type_error) do { \ + grn_obj *x; \ + POP1ALLOC1(x, res); \ + res->header.domain = x->header.domain; \ + switch (x->header.domain) { \ + case GRN_DB_INT8 : \ + { \ + int8_t x_; \ + x_ = GRN_INT8_VALUE(x); \ + left_expression_check(x_); \ + GRN_INT8_SET(ctx, res, integer_operation(x_)); \ + } \ + break; \ + case GRN_DB_UINT8 : \ + { \ + int16_t x_; \ + x_ = GRN_UINT8_VALUE(x); \ + left_expression_check(x_); \ + GRN_INT16_SET(ctx, res, integer_operation(x_)); \ + res->header.domain = GRN_DB_INT16; \ + } \ + break; \ + case GRN_DB_INT16 : \ + { \ + int16_t x_; \ + x_ = GRN_INT16_VALUE(x); \ + left_expression_check(x_); \ + GRN_INT16_SET(ctx, res, integer_operation(x_)); \ + } \ + break; \ + case GRN_DB_UINT16 : \ + { \ + int x_; \ + x_ = GRN_UINT16_VALUE(x); \ + left_expression_check(x_); \ + GRN_INT32_SET(ctx, res, integer_operation(x_)); \ + res->header.domain = GRN_DB_INT32; \ + } \ + break; \ + case GRN_DB_INT32 : \ + { \ + int x_; \ + x_ = GRN_INT32_VALUE(x); \ + left_expression_check(x_); \ + GRN_INT32_SET(ctx, res, integer_operation(x_)); \ + } \ + break; \ + case GRN_DB_UINT32 : \ + { \ + long long int x_; \ + x_ = GRN_UINT32_VALUE(x); \ + left_expression_check(x_); \ + GRN_INT64_SET(ctx, res, integer_operation(x_)); \ + res->header.domain = GRN_DB_INT64; \ + } \ + break; \ + case GRN_DB_INT64 : \ + { \ + long long int x_; \ + x_ = GRN_INT64_VALUE(x); \ + left_expression_check(x_); \ + GRN_INT64_SET(ctx, res, integer_operation(x_)); \ + } \ + break; \ + case GRN_DB_TIME : \ + { \ + long long int x_; \ + x_ = GRN_TIME_VALUE(x); \ + left_expression_check(x_); \ + GRN_TIME_SET(ctx, res, integer_operation(x_)); \ + } \ + break; \ + case GRN_DB_UINT64 : \ + { \ + long long unsigned int x_; \ + x_ = GRN_UINT64_VALUE(x); \ + left_expression_check(x_); \ + if (x_ > (long long unsigned int)INT64_MAX) { \ + ERR(GRN_INVALID_ARGUMENT, \ + "too large UInt64 value to inverse sign: " \ + "<%" GRN_FMT_LLU ">", \ + x_); \ + goto exit; \ + } else { \ + long long int signed_x_; \ + signed_x_ = x_; \ + GRN_INT64_SET(ctx, res, integer_operation(signed_x_)); \ + res->header.domain = GRN_DB_INT64; \ + } \ + } \ + break; \ + case GRN_DB_FLOAT : \ + { \ + double x_; \ + x_ = GRN_FLOAT_VALUE(x); \ + left_expression_check(x_); \ + GRN_FLOAT_SET(ctx, res, float_operation(x_)); \ + } \ + break; \ + case GRN_DB_SHORT_TEXT : \ + case GRN_DB_TEXT : \ + case GRN_DB_LONG_TEXT : \ + text_operation; \ + break; \ + default: \ + invalid_type_error; \ + break; \ + } \ + code++; \ +} while (0) + +#define EXEC_OPERATE(operate_sentence, assign_sentence) \ + operate_sentence \ + assign_sentence + +#define EXEC_OPERATE_POST(operate_sentence, assign_sentence) \ + assign_sentence \ + operate_sentence + +#define UNARY_OPERATE_AND_ASSIGN_DISPATCH(exec_operate, delta, \ + set_flags) do { \ + grn_obj *var, *col, value; \ + grn_id rid; \ + \ + POP1ALLOC1(var, res); \ + if (var->header.type != GRN_PTR) { \ + ERR(GRN_INVALID_ARGUMENT, "invalid variable type: 0x%0x", \ + var->header.type); \ + goto exit; \ + } \ + if (GRN_BULK_VSIZE(var) != (sizeof(grn_obj *) + sizeof(grn_id))) { \ + ERR(GRN_INVALID_ARGUMENT, \ + "invalid variable size: " \ + "expected: %" GRN_FMT_SIZE \ + "actual: %" GRN_FMT_SIZE, \ + (sizeof(grn_obj *) + sizeof(grn_id)), GRN_BULK_VSIZE(var)); \ + goto exit; \ + } \ + col = GRN_PTR_VALUE(var); \ + rid = *(grn_id *)(GRN_BULK_HEAD(var) + sizeof(grn_obj *)); \ + res->header.type = GRN_VOID; \ + res->header.domain = DB_OBJ(col)->range; \ + switch (DB_OBJ(col)->range) { \ + case GRN_DB_INT32 : \ + GRN_INT32_INIT(&value, 0); \ + GRN_INT32_SET(ctx, &value, delta); \ + break; \ + case GRN_DB_UINT32 : \ + GRN_UINT32_INIT(&value, 0); \ + GRN_UINT32_SET(ctx, &value, delta); \ + break; \ + case GRN_DB_INT64 : \ + GRN_INT64_INIT(&value, 0); \ + GRN_INT64_SET(ctx, &value, delta); \ + break; \ + case GRN_DB_UINT64 : \ + GRN_UINT64_INIT(&value, 0); \ + GRN_UINT64_SET(ctx, &value, delta); \ + break; \ + case GRN_DB_FLOAT : \ + GRN_FLOAT_INIT(&value, 0); \ + GRN_FLOAT_SET(ctx, &value, delta); \ + break; \ + case GRN_DB_TIME : \ + GRN_TIME_INIT(&value, 0); \ + GRN_TIME_SET(ctx, &value, GRN_TIME_PACK(delta, 0)); \ + break; \ + default: \ + ERR(GRN_INVALID_ARGUMENT, \ + "invalid increment target type: %d " \ + "(FIXME: type name is needed)", DB_OBJ(col)->range); \ + goto exit; \ + break; \ + } \ + exec_operate(grn_obj_set_value(ctx, col, rid, &value, set_flags);, \ + grn_obj_get_value(ctx, col, rid, res);); \ + code++; \ +} while (0) + +#define ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH(integer8_operation, \ + integer16_operation, \ + integer32_operation, \ + integer64_operation, \ + float_operation, \ + left_expression_check, \ + right_expression_check,\ + text_operation) do { \ + grn_obj *value, *var, *res; \ + if (code->value) { \ + value = code->value; \ + POP1ALLOC1(var, res); \ + } else { \ + POP2ALLOC1(var, value, res); \ + } \ + if (var->header.type == GRN_PTR && \ + GRN_BULK_VSIZE(var) == (sizeof(grn_obj *) + sizeof(grn_id))) { \ + grn_obj *col = GRN_PTR_VALUE(var); \ + grn_id rid = *(grn_id *)(GRN_BULK_HEAD(var) + sizeof(grn_obj *)); \ + grn_obj variable_value, casted_value; \ + grn_id domain; \ + \ + value = GRN_OBJ_RESOLVE(ctx, value); \ + \ + domain = grn_obj_get_range(ctx, col); \ + GRN_OBJ_INIT(&variable_value, GRN_BULK, 0, domain); \ + grn_obj_get_value(ctx, col, rid, &variable_value); \ + \ + GRN_OBJ_INIT(&casted_value, GRN_BULK, 0, domain); \ + if (grn_obj_cast(ctx, value, &casted_value, GRN_FALSE)) { \ + ERR(GRN_INVALID_ARGUMENT, "invalid value: string"); \ + GRN_OBJ_FIN(ctx, &variable_value); \ + GRN_OBJ_FIN(ctx, &casted_value); \ + POP1(res); \ + goto exit; \ + } \ + grn_obj_reinit(ctx, res, domain, 0); \ + ARITHMETIC_OPERATION_DISPATCH((&variable_value), (&casted_value), \ + res, \ + integer8_operation, \ + integer16_operation, \ + integer32_operation, \ + integer64_operation, \ + float_operation, \ + left_expression_check, \ + right_expression_check, \ + text_operation,); \ + grn_obj_set_value(ctx, col, rid, res, GRN_OBJ_SET); \ + GRN_OBJ_FIN(ctx, (&variable_value)); \ + GRN_OBJ_FIN(ctx, (&casted_value)); \ + } else { \ + ERR(GRN_INVALID_ARGUMENT, "left hand expression isn't column."); \ + POP1(res); \ + } \ +} while (0) + +inline static void +grn_expr_exec_get_member_vector(grn_ctx *ctx, + grn_obj *expr, + grn_obj *column_and_record_id, + grn_obj *index, + grn_obj *result) +{ + grn_obj *column; + grn_id record_id; + grn_obj values; + int i; + + column = GRN_PTR_VALUE(column_and_record_id); + record_id = *((grn_id *)(&(GRN_PTR_VALUE_AT(column_and_record_id, 1)))); + GRN_TEXT_INIT(&values, 0); + grn_obj_get_value(ctx, column, record_id, &values); + + i = GRN_UINT32_VALUE(index); + if (values.header.type == GRN_UVECTOR) { + int n_elements = 0; + grn_obj *range; + grn_id range_id = DB_OBJ(column)->range; + + grn_obj_reinit(ctx, result, range_id, 0); + range = grn_ctx_at(ctx, range_id); + if (range) { + switch (range->header.type) { + case GRN_TYPE : + n_elements = GRN_BULK_VSIZE(&values) / grn_type_size(ctx, range); + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + n_elements = GRN_BULK_VSIZE(&values) / sizeof(grn_id); + break; + } + } + if (n_elements > i) { +#define GET_UVECTOR_ELEMENT_AS(type) do { \ + GRN_ ## type ## _SET(ctx, \ + result, \ + GRN_ ## type ## _VALUE_AT(&values, i)); \ + } while (GRN_FALSE) + switch (values.header.domain) { + case GRN_DB_BOOL : + GET_UVECTOR_ELEMENT_AS(BOOL); + break; + case GRN_DB_INT8 : + GET_UVECTOR_ELEMENT_AS(INT8); + break; + case GRN_DB_UINT8 : + GET_UVECTOR_ELEMENT_AS(UINT8); + break; + case GRN_DB_INT16 : + GET_UVECTOR_ELEMENT_AS(INT16); + break; + case GRN_DB_UINT16 : + GET_UVECTOR_ELEMENT_AS(UINT16); + break; + case GRN_DB_INT32 : + GET_UVECTOR_ELEMENT_AS(INT32); + break; + case GRN_DB_UINT32 : + GET_UVECTOR_ELEMENT_AS(UINT32); + break; + case GRN_DB_INT64 : + GET_UVECTOR_ELEMENT_AS(INT64); + break; + case GRN_DB_UINT64 : + GET_UVECTOR_ELEMENT_AS(UINT64); + break; + case GRN_DB_FLOAT : + GET_UVECTOR_ELEMENT_AS(FLOAT); + break; + case GRN_DB_TIME : + GET_UVECTOR_ELEMENT_AS(TIME); + break; + default : + GET_UVECTOR_ELEMENT_AS(RECORD); + break; + } +#undef GET_UVECTOR_ELEMENT_AS + } + } else { + if (values.u.v.n_sections > i) { + const char *content; + unsigned int content_length; + grn_id domain; + + content_length = grn_vector_get_element(ctx, &values, i, + &content, NULL, &domain); + grn_obj_reinit(ctx, result, domain, 0); + grn_bulk_write(ctx, result, content, content_length); + } + } + + GRN_OBJ_FIN(ctx, &values); +} + +inline static void +grn_expr_exec_get_member_table(grn_ctx *ctx, + grn_obj *expr, + grn_obj *table, + grn_obj *key, + grn_obj *result) +{ + grn_id id; + + if (table->header.domain == key->header.domain) { + id = grn_table_get(ctx, table, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key)); + } else { + grn_obj casted_key; + GRN_OBJ_INIT(&casted_key, GRN_BULK, 0, table->header.domain); + if (grn_obj_cast(ctx, key, &casted_key, GRN_FALSE) == GRN_SUCCESS) { + id = grn_table_get(ctx, table, + GRN_BULK_HEAD(&casted_key), + GRN_BULK_VSIZE(&casted_key)); + } else { + id = GRN_ID_NIL; + } + GRN_OBJ_FIN(ctx, &casted_key); + } + + grn_obj_reinit(ctx, result, DB_OBJ(table)->id, 0); + GRN_RECORD_SET(ctx, result, id); +} + +static inline grn_bool +grn_expr_exec_is_simple_expr(grn_ctx *ctx, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + + if (expr->header.type != GRN_EXPR) { + return GRN_FALSE; + } + + if (e->codes_curr != 1) { + return GRN_FALSE; + } + + switch (e->codes[0].op) { + case GRN_OP_PUSH : + return GRN_TRUE; + default : + return GRN_FALSE; + } +} + +static inline grn_obj * +grn_expr_exec_simple(grn_ctx *ctx, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + + return e->codes[0].value; +} + +grn_obj * +grn_expr_exec(grn_ctx *ctx, grn_obj *expr, int nargs) +{ + grn_obj *val = NULL; + uint32_t stack_curr = ctx->impl->stack_curr; + GRN_API_ENTER; + if (grn_expr_exec_is_simple_expr(ctx, expr)) { + val = grn_expr_exec_simple(ctx, expr); + GRN_API_RETURN(val); + } + if (expr->header.type == GRN_PROC) { + grn_proc *proc = (grn_proc *)expr; + if (proc->type == GRN_PROC_COMMAND) { + grn_command_input *input; + input = grn_command_input_open(ctx, expr); + grn_command_run(ctx, expr, input); + grn_command_input_close(ctx, input); + GRN_API_RETURN(NULL); + } else { + grn_proc_call(ctx, expr, nargs, expr); + } + } else { + grn_expr *e = (grn_expr *)expr; + register grn_obj **s_ = ctx->impl->stack; + register grn_obj *s0 = NULL; + register grn_obj *s1 = NULL; + register grn_obj **sp; + register grn_obj *vp = e->values; + grn_obj *res = NULL, *v0 = grn_expr_get_var_by_offset(ctx, expr, 0); + grn_expr_code *code = e->codes, *ce = &e->codes[e->codes_curr]; + sp = s_ + stack_curr; + while (code < ce) { + switch (code->op) { + case GRN_OP_NOP : + code++; + break; + case GRN_OP_PUSH : + PUSH1(code->value); + code++; + break; + case GRN_OP_POP : + { + grn_obj *obj; + POP1(obj); + code++; + } + break; + case GRN_OP_GET_REF : + { + grn_obj *col, *rec; + if (code->nargs == 1) { + rec = v0; + if (code->value) { + col = code->value; + ALLOC1(res); + } else { + POP1ALLOC1(col, res); + } + } else { + if (code->value) { + col = code->value; + POP1ALLOC1(rec, res); + } else { + POP2ALLOC1(rec, col, res); + } + } + if (col->header.type == GRN_BULK) { + grn_obj *table = grn_ctx_at(ctx, GRN_OBJ_GET_DOMAIN(rec)); + col = grn_obj_column(ctx, table, GRN_BULK_HEAD(col), GRN_BULK_VSIZE(col)); + if (col) { grn_expr_take_obj(ctx, (grn_obj *)e, col); } + } + if (col) { + res->header.type = GRN_PTR; + res->header.domain = GRN_ID_NIL; + GRN_PTR_SET(ctx, res, col); + GRN_UINT32_PUT(ctx, res, GRN_RECORD_VALUE(rec)); + } else { + ERR(GRN_INVALID_ARGUMENT, "col resolve failed"); + goto exit; + } + code++; + } + break; + case GRN_OP_CALL : + { + grn_obj *proc; + if (code->value) { + if (sp < s_ + code->nargs - 1) { + ERR(GRN_INVALID_ARGUMENT, "stack error"); + goto exit; + } + proc = code->value; + WITH_SPSAVE({ + grn_proc_call(ctx, proc, code->nargs - 1, expr); + }); + } else { + int offset = code->nargs; + if (sp < s_ + offset) { + ERR(GRN_INVALID_ARGUMENT, "stack error"); + goto exit; + } + proc = sp[-offset]; + if (grn_obj_is_window_function_proc(ctx, proc)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, proc); + ERR(GRN_INVALID_ARGUMENT, + "window function can't be executed for each record: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + goto exit; + } else { + WITH_SPSAVE({ + grn_proc_call(ctx, proc, code->nargs - 1, expr); + }); + } + if (ctx->rc) { + goto exit; + } + POP1(res); + { + grn_obj *proc_; + POP1(proc_); + if (proc != proc_) { + GRN_LOG(ctx, GRN_LOG_WARNING, "stack may be corrupt"); + } + } + PUSH1(res); + } + } + code++; + break; + case GRN_OP_INTERN : + { + grn_obj *obj; + POP1(obj); + obj = GRN_OBJ_RESOLVE(ctx, obj); + res = grn_expr_get_var(ctx, expr, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj)); + if (!res) { res = grn_ctx_get(ctx, GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj)); } + if (!res) { + ERR(GRN_INVALID_ARGUMENT, "intern failed"); + goto exit; + } + PUSH1(res); + } + code++; + break; + case GRN_OP_TABLE_CREATE : + { + grn_obj *value_type, *key_type, *flags, *name; + POP1(value_type); + value_type = GRN_OBJ_RESOLVE(ctx, value_type); + POP1(key_type); + key_type = GRN_OBJ_RESOLVE(ctx, key_type); + POP1(flags); + flags = GRN_OBJ_RESOLVE(ctx, flags); + POP1(name); + name = GRN_OBJ_RESOLVE(ctx, name); + res = grn_table_create(ctx, GRN_TEXT_VALUE(name), GRN_TEXT_LEN(name), + NULL, GRN_UINT32_VALUE(flags), + key_type, value_type); + PUSH1(res); + } + code++; + break; + case GRN_OP_EXPR_GET_VAR : + { + grn_obj *name, *expr; + POP1(name); + name = GRN_OBJ_RESOLVE(ctx, name); + POP1(expr); + expr = GRN_OBJ_RESOLVE(ctx, expr); + switch (name->header.domain) { + case GRN_DB_INT32 : + res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_INT32_VALUE(name)); + break; + case GRN_DB_UINT32 : + res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_UINT32_VALUE(name)); + break; + case GRN_DB_INT64 : + res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_INT64_VALUE(name)); + break; + case GRN_DB_UINT64 : + res = grn_expr_get_var_by_offset(ctx, expr, (unsigned int) GRN_UINT64_VALUE(name)); + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + res = grn_expr_get_var(ctx, expr, GRN_TEXT_VALUE(name), GRN_TEXT_LEN(name)); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "invalid type"); + goto exit; + } + PUSH1(res); + } + code++; + break; + case GRN_OP_ASSIGN : + { + grn_obj *value, *var; + if (code->value) { + value = code->value; + } else { + POP1(value); + } + value = GRN_OBJ_RESOLVE(ctx, value); + POP1(var); + // var = GRN_OBJ_RESOLVE(ctx, var); + if (var->header.type == GRN_PTR && + GRN_BULK_VSIZE(var) == (sizeof(grn_obj *) + sizeof(grn_id))) { + grn_obj *col = GRN_PTR_VALUE(var); + grn_id rid = *(grn_id *)(GRN_BULK_HEAD(var) + sizeof(grn_obj *)); + grn_obj_set_value(ctx, col, rid, value, GRN_OBJ_SET); + } else { + VAR_SET_VALUE(ctx, var, value); + } + PUSH1(value); + } + code++; + break; + case GRN_OP_STAR_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_STAR, + INTEGER_ARITHMETIC_OPERATION_STAR, + INTEGER_ARITHMETIC_OPERATION_STAR, + INTEGER_ARITHMETIC_OPERATION_STAR, + FLOAT_ARITHMETIC_OPERATION_STAR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable *= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_SLASH_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_SLASH, + INTEGER_ARITHMETIC_OPERATION_SLASH, + INTEGER_ARITHMETIC_OPERATION_SLASH, + INTEGER_ARITHMETIC_OPERATION_SLASH, + FLOAT_ARITHMETIC_OPERATION_SLASH, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable /= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_MOD_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_MOD, + INTEGER_ARITHMETIC_OPERATION_MOD, + INTEGER_ARITHMETIC_OPERATION_MOD, + INTEGER_ARITHMETIC_OPERATION_MOD, + FLOAT_ARITHMETIC_OPERATION_MOD, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable %%= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_PLUS_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_PLUS, + INTEGER_ARITHMETIC_OPERATION_PLUS, + INTEGER_ARITHMETIC_OPERATION_PLUS, + INTEGER_ARITHMETIC_OPERATION_PLUS, + FLOAT_ARITHMETIC_OPERATION_PLUS, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable += \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_MINUS_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_MINUS, + INTEGER_ARITHMETIC_OPERATION_MINUS, + INTEGER_ARITHMETIC_OPERATION_MINUS, + INTEGER_ARITHMETIC_OPERATION_MINUS, + FLOAT_ARITHMETIC_OPERATION_MINUS, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable -= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_SHIFTL_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_SHIFTL, + INTEGER_ARITHMETIC_OPERATION_SHIFTL, + INTEGER_ARITHMETIC_OPERATION_SHIFTL, + INTEGER_ARITHMETIC_OPERATION_SHIFTL, + FLOAT_ARITHMETIC_OPERATION_SHIFTL, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable <<= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_SHIFTR_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_SHIFTR, + INTEGER_ARITHMETIC_OPERATION_SHIFTR, + INTEGER_ARITHMETIC_OPERATION_SHIFTR, + INTEGER_ARITHMETIC_OPERATION_SHIFTR, + FLOAT_ARITHMETIC_OPERATION_SHIFTR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable >>= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_SHIFTRR_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER8_ARITHMETIC_OPERATION_SHIFTRR, + INTEGER16_ARITHMETIC_OPERATION_SHIFTRR, + INTEGER32_ARITHMETIC_OPERATION_SHIFTRR, + INTEGER64_ARITHMETIC_OPERATION_SHIFTRR, + FLOAT_ARITHMETIC_OPERATION_SHIFTRR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, + "variable >>>= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_AND_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, + INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, + INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, + INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, + FLOAT_ARITHMETIC_OPERATION_BITWISE_AND, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable &= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_OR_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, + FLOAT_ARITHMETIC_OPERATION_BITWISE_OR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable |= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_XOR_ASSIGN : + ARITHMETIC_OPERATION_AND_ASSIGN_DISPATCH( + INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, + FLOAT_ARITHMETIC_OPERATION_BITWISE_XOR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, "variable ^= \"string\" isn't supported"); + goto exit; + }); + break; + case GRN_OP_JUMP : + code += code->nargs + 1; + break; + case GRN_OP_CJUMP : + { + grn_obj *v; + POP1(v); + if (!grn_obj_is_true(ctx, v)) { + code += code->nargs; + } + } + code++; + break; + case GRN_OP_GET_VALUE : + { + grn_obj *col, *rec; + do { + if (code->nargs == 1) { + rec = v0; + if (code->value) { + col = code->value; + ALLOC1(res); + } else { + POP1ALLOC1(col, res); + } + } else { + if (code->value) { + col = code->value; + POP1ALLOC1(rec, res); + } else { + POP2ALLOC1(rec, col, res); + } + } + if (col->header.type == GRN_BULK) { + grn_obj *table = grn_ctx_at(ctx, GRN_OBJ_GET_DOMAIN(rec)); + col = grn_obj_column(ctx, table, GRN_BULK_HEAD(col), GRN_BULK_VSIZE(col)); + if (col) { grn_expr_take_obj(ctx, (grn_obj *)expr, col); } + } + if (!col) { + ERR(GRN_INVALID_ARGUMENT, "col resolve failed"); + goto exit; + } + grn_obj_reinit_for(ctx, res, col); + grn_obj_get_value(ctx, col, GRN_RECORD_VALUE(rec), res); + code++; + } while (code < ce && code->op == GRN_OP_GET_VALUE); + } + break; + case GRN_OP_OBJ_SEARCH : + { + grn_obj *op, *query, *index; + // todo : grn_search_optarg optarg; + POP1(op); + op = GRN_OBJ_RESOLVE(ctx, op); + POP1(res); + res = GRN_OBJ_RESOLVE(ctx, res); + POP1(query); + query = GRN_OBJ_RESOLVE(ctx, query); + POP1(index); + index = GRN_OBJ_RESOLVE(ctx, index); + grn_obj_search(ctx, index, query, res, + (grn_operator)GRN_UINT32_VALUE(op), NULL); + } + code++; + break; + case GRN_OP_TABLE_SELECT : + { + grn_obj *op, *res, *expr, *table; + POP1(op); + op = GRN_OBJ_RESOLVE(ctx, op); + POP1(res); + res = GRN_OBJ_RESOLVE(ctx, res); + POP1(expr); + expr = GRN_OBJ_RESOLVE(ctx, expr); + POP1(table); + table = GRN_OBJ_RESOLVE(ctx, table); + WITH_SPSAVE({ + grn_table_select(ctx, table, expr, res, (grn_operator)GRN_UINT32_VALUE(op)); + }); + PUSH1(res); + } + code++; + break; + case GRN_OP_TABLE_SORT : + { + grn_obj *keys_, *res, *limit, *table; + POP1(keys_); + keys_ = GRN_OBJ_RESOLVE(ctx, keys_); + POP1(res); + res = GRN_OBJ_RESOLVE(ctx, res); + POP1(limit); + limit = GRN_OBJ_RESOLVE(ctx, limit); + POP1(table); + table = GRN_OBJ_RESOLVE(ctx, table); + { + grn_table_sort_key *keys; + const char *p = GRN_BULK_HEAD(keys_), *tokbuf[256]; + int n = grn_str_tok(p, GRN_BULK_VSIZE(keys_), ' ', tokbuf, 256, NULL); + if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) { + int i, n_keys = 0; + for (i = 0; i < n; i++) { + uint32_t len = (uint32_t) (tokbuf[i] - p); + grn_obj *col = grn_obj_column(ctx, table, p, len); + if (col) { + keys[n_keys].key = col; + keys[n_keys].flags = GRN_TABLE_SORT_ASC; + keys[n_keys].offset = 0; + n_keys++; + } else { + if (p[0] == ':' && p[1] == 'd' && len == 2 && n_keys) { + keys[n_keys - 1].flags |= GRN_TABLE_SORT_DESC; + } + } + p = tokbuf[i] + 1; + } + WITH_SPSAVE({ + grn_table_sort(ctx, table, 0, GRN_INT32_VALUE(limit), res, keys, n_keys); + }); + for (i = 0; i < n_keys; i++) { + grn_obj_unlink(ctx, keys[i].key); + } + GRN_FREE(keys); + } + } + } + code++; + break; + case GRN_OP_TABLE_GROUP : + { + grn_obj *res, *keys_, *table; + POP1(res); + res = GRN_OBJ_RESOLVE(ctx, res); + POP1(keys_); + keys_ = GRN_OBJ_RESOLVE(ctx, keys_); + POP1(table); + table = GRN_OBJ_RESOLVE(ctx, table); + { + grn_table_sort_key *keys; + grn_table_group_result results; + const char *p = GRN_BULK_HEAD(keys_), *tokbuf[256]; + int n = grn_str_tok(p, GRN_BULK_VSIZE(keys_), ' ', tokbuf, 256, NULL); + if ((keys = GRN_MALLOCN(grn_table_sort_key, n))) { + int i, n_keys = 0; + for (i = 0; i < n; i++) { + uint32_t len = (uint32_t) (tokbuf[i] - p); + grn_obj *col = grn_obj_column(ctx, table, p, len); + if (col) { + keys[n_keys].key = col; + keys[n_keys].flags = GRN_TABLE_SORT_ASC; + keys[n_keys].offset = 0; + n_keys++; + } else if (n_keys) { + if (p[0] == ':' && p[1] == 'd' && len == 2) { + keys[n_keys - 1].flags |= GRN_TABLE_SORT_DESC; + } else { + keys[n_keys - 1].offset = grn_atoi(p, p + len, NULL); + } + } + p = tokbuf[i] + 1; + } + /* todo : support multi-results */ + results.table = res; + results.key_begin = 0; + results.key_end = 0; + results.limit = 0; + results.flags = 0; + results.op = GRN_OP_OR; + WITH_SPSAVE({ + grn_table_group(ctx, table, keys, n_keys, &results, 1); + }); + for (i = 0; i < n_keys; i++) { + grn_obj_unlink(ctx, keys[i].key); + } + GRN_FREE(keys); + } + } + } + code++; + break; + case GRN_OP_JSON_PUT : + { + grn_obj_format format; + grn_obj *str, *table, *res; + POP1(res); + res = GRN_OBJ_RESOLVE(ctx, res); + POP1(str); + str = GRN_OBJ_RESOLVE(ctx, str); + POP1(table); + table = GRN_OBJ_RESOLVE(ctx, table); + GRN_OBJ_FORMAT_INIT(&format, grn_table_size(ctx, table), 0, -1, 0); + format.flags = 0; + grn_obj_columns(ctx, table, + GRN_TEXT_VALUE(str), GRN_TEXT_LEN(str), &format.columns); + grn_text_otoj(ctx, res, table, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + } + code++; + break; + case GRN_OP_AND : + { + grn_obj *x, *y; + grn_obj *result = NULL; + POP2ALLOC1(x, y, res); + if (grn_obj_is_true(ctx, x)) { + if (grn_obj_is_true(ctx, y)) { + result = y; + } + } + if (result) { + if (res != result) { + grn_obj_reinit(ctx, res, result->header.domain, 0); + grn_obj_cast(ctx, result, res, GRN_FALSE); + } + } else { + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, GRN_FALSE); + } + } + code++; + break; + case GRN_OP_OR : + { + grn_obj *x, *y; + grn_obj *result; + POP2ALLOC1(x, y, res); + if (grn_obj_is_true(ctx, x)) { + result = x; + } else { + if (grn_obj_is_true(ctx, y)) { + result = y; + } else { + result = NULL; + } + } + if (result) { + if (res != result) { + grn_obj_reinit(ctx, res, result->header.domain, 0); + grn_obj_cast(ctx, result, res, GRN_FALSE); + } + } else { + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, GRN_FALSE); + } + } + code++; + break; + case GRN_OP_AND_NOT : + { + grn_obj *x, *y; + grn_bool is_true; + POP2ALLOC1(x, y, res); + if (!grn_obj_is_true(ctx, x) || grn_obj_is_true(ctx, y)) { + is_true = GRN_FALSE; + } else { + is_true = GRN_TRUE; + } + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, is_true); + } + code++; + break; + case GRN_OP_ADJUST : + { + /* todo */ + } + code++; + break; + case GRN_OP_MATCH : + { + grn_obj *x, *y; + grn_bool matched; + POP1(y); + POP1(x); + WITH_SPSAVE({ + matched = grn_operator_exec_match(ctx, x, y); + }); + ALLOC1(res); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, matched); + } + code++; + break; + case GRN_OP_EQUAL : + { + grn_bool is_equal; + grn_obj *x, *y; + POP2ALLOC1(x, y, res); + is_equal = grn_operator_exec_equal(ctx, x, y); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, is_equal); + } + code++; + break; + case GRN_OP_NOT_EQUAL : + { + grn_bool is_not_equal; + grn_obj *x, *y; + POP2ALLOC1(x, y, res); + is_not_equal = grn_operator_exec_not_equal(ctx, x, y); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, is_not_equal); + } + code++; + break; + case GRN_OP_PREFIX : + { + grn_obj *x, *y; + grn_bool matched; + POP1(y); + POP1(x); + WITH_SPSAVE({ + matched = grn_operator_exec_prefix(ctx, x, y); + }); + ALLOC1(res); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, matched); + } + code++; + break; + case GRN_OP_SUFFIX : + { + grn_obj *x, *y; + grn_bool matched = GRN_FALSE; + POP2ALLOC1(x, y, res); + if (GRN_TEXT_LEN(x) >= GRN_TEXT_LEN(y) && + !memcmp(GRN_TEXT_VALUE(x) + GRN_TEXT_LEN(x) - GRN_TEXT_LEN(y), + GRN_TEXT_VALUE(y), GRN_TEXT_LEN(y))) { + matched = GRN_TRUE; + } + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, matched); + } + code++; + break; + case GRN_OP_LESS : + { + grn_bool r; + grn_obj *x, *y; + POP2ALLOC1(x, y, res); + r = grn_operator_exec_less(ctx, x, y); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, r); + } + code++; + break; + case GRN_OP_GREATER : + { + grn_bool r; + grn_obj *x, *y; + POP2ALLOC1(x, y, res); + r = grn_operator_exec_greater(ctx, x, y); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, r); + } + code++; + break; + case GRN_OP_LESS_EQUAL : + { + grn_bool r; + grn_obj *x, *y; + POP2ALLOC1(x, y, res); + r = grn_operator_exec_less_equal(ctx, x, y); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, r); + } + code++; + break; + case GRN_OP_GREATER_EQUAL : + { + grn_bool r; + grn_obj *x, *y; + POP2ALLOC1(x, y, res); + r = grn_operator_exec_greater_equal(ctx, x, y); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, r); + } + code++; + break; + case GRN_OP_GEO_DISTANCE1 : + { + grn_obj *value; + double lng1, lat1, lng2, lat2, x, y, d; + POP1(value); + lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1ALLOC1(value, res); + lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5); + y = (lat2 - lat1); + d = sqrt((x * x) + (y * y)) * GEO_RADIOUS; + res->header.type = GRN_BULK; + res->header.domain = GRN_DB_FLOAT; + GRN_FLOAT_SET(ctx, res, d); + } + code++; + break; + case GRN_OP_GEO_DISTANCE2 : + { + grn_obj *value; + double lng1, lat1, lng2, lat2, x, y, d; + POP1(value); + lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1ALLOC1(value, res); + lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + x = sin(fabs(lng2 - lng1) * 0.5); + y = sin(fabs(lat2 - lat1) * 0.5); + d = asin(sqrt((y * y) + cos(lat1) * cos(lat2) * x * x)) * 2 * GEO_RADIOUS; + res->header.type = GRN_BULK; + res->header.domain = GRN_DB_FLOAT; + GRN_FLOAT_SET(ctx, res, d); + } + code++; + break; + case GRN_OP_GEO_DISTANCE3 : + { + grn_obj *value; + double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d; + POP1(value); + lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1ALLOC1(value, res); + lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + p = (lat1 + lat2) * 0.5; + q = (1 - GEO_BES_C3 * sin(p) * sin(p)); + m = GEO_BES_C1 / sqrt(q * q * q); + n = GEO_BES_C2 / sqrt(q); + x = n * cos(p) * fabs(lng1 - lng2); + y = m * fabs(lat1 - lat2); + d = sqrt((x * x) + (y * y)); + res->header.type = GRN_BULK; + res->header.domain = GRN_DB_FLOAT; + GRN_FLOAT_SET(ctx, res, d); + } + code++; + break; + case GRN_OP_GEO_DISTANCE4 : + { + grn_obj *value; + double lng1, lat1, lng2, lat2, p, q, m, n, x, y, d; + POP1(value); + lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1ALLOC1(value, res); + lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + p = (lat1 + lat2) * 0.5; + q = (1 - GEO_GRS_C3 * sin(p) * sin(p)); + m = GEO_GRS_C1 / sqrt(q * q * q); + n = GEO_GRS_C2 / sqrt(q); + x = n * cos(p) * fabs(lng1 - lng2); + y = m * fabs(lat1 - lat2); + d = sqrt((x * x) + (y * y)); + res->header.type = GRN_BULK; + res->header.domain = GRN_DB_FLOAT; + GRN_FLOAT_SET(ctx, res, d); + } + code++; + break; + case GRN_OP_GEO_WITHINP5 : + { + int r; + grn_obj *value; + double lng0, lat0, lng1, lat1, x, y, d; + POP1(value); + lng0 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lat0 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1ALLOC1(value, res); + x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5); + y = (lat1 - lat0); + d = sqrt((x * x) + (y * y)) * GEO_RADIOUS; + switch (value->header.domain) { + case GRN_DB_INT32 : + r = d <= GRN_INT32_VALUE(value); + break; + case GRN_DB_FLOAT : + r = d <= GRN_FLOAT_VALUE(value); + break; + default : + r = 0; + break; + } + GRN_INT32_SET(ctx, res, r); + res->header.type = GRN_BULK; + res->header.domain = GRN_DB_INT32; + } + code++; + break; + case GRN_OP_GEO_WITHINP6 : + { + int r; + grn_obj *value; + double lng0, lat0, lng1, lat1, lng2, lat2, x, y, d; + POP1(value); + lng0 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lat0 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lng1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lat1 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1(value); + lng2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + POP1ALLOC1(value, res); + lat2 = GEO_INT2RAD(GRN_INT32_VALUE(value)); + x = (lng1 - lng0) * cos((lat0 + lat1) * 0.5); + y = (lat1 - lat0); + d = (x * x) + (y * y); + x = (lng2 - lng1) * cos((lat1 + lat2) * 0.5); + y = (lat2 - lat1); + r = d <= (x * x) + (y * y); + GRN_INT32_SET(ctx, res, r); + res->header.type = GRN_BULK; + res->header.domain = GRN_DB_INT32; + } + code++; + break; + case GRN_OP_GEO_WITHINP8 : + { + int r; + grn_obj *value; + int64_t ln0, la0, ln1, la1, ln2, la2, ln3, la3; + POP1(value); + ln0 = GRN_INT32_VALUE(value); + POP1(value); + la0 = GRN_INT32_VALUE(value); + POP1(value); + ln1 = GRN_INT32_VALUE(value); + POP1(value); + la1 = GRN_INT32_VALUE(value); + POP1(value); + ln2 = GRN_INT32_VALUE(value); + POP1(value); + la2 = GRN_INT32_VALUE(value); + POP1(value); + ln3 = GRN_INT32_VALUE(value); + POP1ALLOC1(value, res); + la3 = GRN_INT32_VALUE(value); + r = ((ln2 <= ln0) && (ln0 <= ln3) && (la2 <= la0) && (la0 <= la3)); + GRN_INT32_SET(ctx, res, r); + res->header.type = GRN_BULK; + res->header.domain = GRN_DB_INT32; + } + code++; + break; + case GRN_OP_PLUS : + ARITHMETIC_BINARY_OPERATION_DISPATCH( + "+", + INTEGER_ARITHMETIC_OPERATION_PLUS, + INTEGER_ARITHMETIC_OPERATION_PLUS, + INTEGER_ARITHMETIC_OPERATION_PLUS, + INTEGER_ARITHMETIC_OPERATION_PLUS, + FLOAT_ARITHMETIC_OPERATION_PLUS, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + if (x == res) { + grn_obj_cast(ctx, y, res, GRN_FALSE); + } else if (y == res) { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_obj_cast(ctx, x, &buffer, GRN_FALSE); + grn_obj_cast(ctx, y, &buffer, GRN_FALSE); + GRN_BULK_REWIND(res); + grn_obj_cast(ctx, &buffer, res, GRN_FALSE); + GRN_OBJ_FIN(ctx, &buffer); + } else { + GRN_BULK_REWIND(res); + grn_obj_cast(ctx, x, res, GRN_FALSE); + grn_obj_cast(ctx, y, res, GRN_FALSE); + } + } + ,); + break; + case GRN_OP_MINUS : + if (code->nargs == 1) { + ARITHMETIC_UNARY_OPERATION_DISPATCH( + INTEGER_UNARY_ARITHMETIC_OPERATION_MINUS, + FLOAT_UNARY_ARITHMETIC_OPERATION_MINUS, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + long long int x_; + + res->header.type = GRN_BULK; + res->header.domain = GRN_DB_INT64; + + GRN_INT64_SET(ctx, res, 0); + grn_obj_cast(ctx, x, res, GRN_FALSE); + x_ = GRN_INT64_VALUE(res); + + GRN_INT64_SET(ctx, res, -x_); + } + ,); + } else { + ARITHMETIC_BINARY_OPERATION_DISPATCH( + "-", + INTEGER_ARITHMETIC_OPERATION_MINUS, + INTEGER_ARITHMETIC_OPERATION_MINUS, + INTEGER_ARITHMETIC_OPERATION_MINUS, + INTEGER_ARITHMETIC_OPERATION_MINUS, + FLOAT_ARITHMETIC_OPERATION_MINUS, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, + "\"string\" - \"string\" " + "isn't supported"); + goto exit; + } + ,); + } + break; + case GRN_OP_STAR : + ARITHMETIC_BINARY_OPERATION_DISPATCH( + "*", + INTEGER_ARITHMETIC_OPERATION_STAR, + INTEGER_ARITHMETIC_OPERATION_STAR, + INTEGER_ARITHMETIC_OPERATION_STAR, + INTEGER_ARITHMETIC_OPERATION_STAR, + FLOAT_ARITHMETIC_OPERATION_STAR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + ERR(GRN_INVALID_ARGUMENT, + "\"string\" * \"string\" " + "isn't supported"); + goto exit; + } + ,); + break; + case GRN_OP_SLASH : + DIVISION_OPERATION_DISPATCH( + SIGNED_INTEGER_DIVISION_OPERATION_SLASH, + UNSIGNED_INTEGER_DIVISION_OPERATION_SLASH, + FLOAT_DIVISION_OPERATION_SLASH, + { + ERR(GRN_INVALID_ARGUMENT, + "\"string\" / \"string\" " + "isn't supported"); + goto exit; + }); + break; + case GRN_OP_MOD : + DIVISION_OPERATION_DISPATCH( + SIGNED_INTEGER_DIVISION_OPERATION_MOD, + UNSIGNED_INTEGER_DIVISION_OPERATION_MOD, + FLOAT_DIVISION_OPERATION_MOD, + { + ERR(GRN_INVALID_ARGUMENT, + "\"string\" %% \"string\" " + "isn't supported"); + goto exit; + }); + break; + case GRN_OP_BITWISE_NOT : + ARITHMETIC_UNARY_OPERATION_DISPATCH( + INTEGER_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT, + FLOAT_UNARY_ARITHMETIC_OPERATION_BITWISE_NOT, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + TEXT_UNARY_ARITHMETIC_OPERATION(~),); + break; + case GRN_OP_BITWISE_OR : + ARITHMETIC_BINARY_OPERATION_DISPATCH( + "|", + INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_OR, + FLOAT_ARITHMETIC_OPERATION_BITWISE_OR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + TEXT_ARITHMETIC_OPERATION(|),); + break; + case GRN_OP_BITWISE_XOR : + ARITHMETIC_BINARY_OPERATION_DISPATCH( + "^", + INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, + INTEGER_ARITHMETIC_OPERATION_BITWISE_XOR, + FLOAT_ARITHMETIC_OPERATION_BITWISE_XOR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + TEXT_ARITHMETIC_OPERATION(^),); + break; + case GRN_OP_BITWISE_AND : + ARITHMETIC_BINARY_OPERATION_DISPATCH( + "&", + INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, + INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, + INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, + INTEGER_ARITHMETIC_OPERATION_BITWISE_AND, + FLOAT_ARITHMETIC_OPERATION_BITWISE_AND, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + TEXT_ARITHMETIC_OPERATION(&),); + break; + case GRN_OP_SHIFTL : + ARITHMETIC_BINARY_OPERATION_DISPATCH( + "<<", + INTEGER_ARITHMETIC_OPERATION_SHIFTL, + INTEGER_ARITHMETIC_OPERATION_SHIFTL, + INTEGER_ARITHMETIC_OPERATION_SHIFTL, + INTEGER_ARITHMETIC_OPERATION_SHIFTL, + FLOAT_ARITHMETIC_OPERATION_SHIFTL, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + TEXT_ARITHMETIC_OPERATION(<<),); + break; + case GRN_OP_SHIFTR : + ARITHMETIC_BINARY_OPERATION_DISPATCH( + ">>", + INTEGER_ARITHMETIC_OPERATION_SHIFTR, + INTEGER_ARITHMETIC_OPERATION_SHIFTR, + INTEGER_ARITHMETIC_OPERATION_SHIFTR, + INTEGER_ARITHMETIC_OPERATION_SHIFTR, + FLOAT_ARITHMETIC_OPERATION_SHIFTR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + TEXT_ARITHMETIC_OPERATION(>>),); + break; + case GRN_OP_SHIFTRR : + ARITHMETIC_BINARY_OPERATION_DISPATCH( + ">>>", + INTEGER8_ARITHMETIC_OPERATION_SHIFTRR, + INTEGER16_ARITHMETIC_OPERATION_SHIFTRR, + INTEGER32_ARITHMETIC_OPERATION_SHIFTRR, + INTEGER64_ARITHMETIC_OPERATION_SHIFTRR, + FLOAT_ARITHMETIC_OPERATION_SHIFTRR, + ARITHMETIC_OPERATION_NO_CHECK, + ARITHMETIC_OPERATION_NO_CHECK, + { + long long unsigned int x_; + long long unsigned int y_; + + res->header.type = GRN_BULK; + res->header.domain = GRN_DB_INT64; + + GRN_INT64_SET(ctx, res, 0); + grn_obj_cast(ctx, x, res, GRN_FALSE); + x_ = GRN_INT64_VALUE(res); + + GRN_INT64_SET(ctx, res, 0); + grn_obj_cast(ctx, y, res, GRN_FALSE); + y_ = GRN_INT64_VALUE(res); + + GRN_INT64_SET(ctx, res, x_ >> y_); + } + ,); + break; + case GRN_OP_INCR : + UNARY_OPERATE_AND_ASSIGN_DISPATCH(EXEC_OPERATE, 1, GRN_OBJ_INCR); + break; + case GRN_OP_DECR : + UNARY_OPERATE_AND_ASSIGN_DISPATCH(EXEC_OPERATE, 1, GRN_OBJ_DECR); + break; + case GRN_OP_INCR_POST : + UNARY_OPERATE_AND_ASSIGN_DISPATCH(EXEC_OPERATE_POST, 1, GRN_OBJ_INCR); + break; + case GRN_OP_DECR_POST : + UNARY_OPERATE_AND_ASSIGN_DISPATCH(EXEC_OPERATE_POST, 1, GRN_OBJ_DECR); + break; + case GRN_OP_NOT : + { + grn_obj *value; + grn_bool value_boolean; + POP1ALLOC1(value, res); + GRN_OBJ_IS_TRUE(ctx, value, value_boolean); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, !value_boolean); + } + code++; + break; + case GRN_OP_GET_MEMBER : + { + grn_obj *receiver, *index_or_key; + POP2ALLOC1(receiver, index_or_key, res); + if (receiver->header.type == GRN_PTR) { + grn_obj *index = index_or_key; + grn_expr_exec_get_member_vector(ctx, expr, receiver, index, res); + } else { + grn_obj *key = index_or_key; + grn_expr_exec_get_member_table(ctx, expr, receiver, key, res); + } + code++; + } + break; + case GRN_OP_REGEXP : + { + grn_obj *target, *pattern; + grn_bool matched; + POP1(pattern); + POP1(target); + WITH_SPSAVE({ + matched = grn_operator_exec_regexp(ctx, target, pattern); + }); + ALLOC1(res); + grn_obj_reinit(ctx, res, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, res, matched); + } + code++; + break; + default : + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "not implemented operator assigned"); + goto exit; + break; + } + } + ctx->impl->stack_curr = sp - s_; + } + if (ctx->impl->stack_curr + nargs > stack_curr) { + val = grn_ctx_pop(ctx); + } +exit : + if (ctx->impl->stack_curr + nargs > stack_curr) { + /* + GRN_LOG(ctx, GRN_LOG_WARNING, "nargs=%d stack balance=%d", + nargs, stack_curr - ctx->impl->stack_curr); + */ + ctx->impl->stack_curr = stack_curr - nargs; + } + GRN_API_RETURN(val); +} + +grn_obj * +grn_expr_get_value(grn_ctx *ctx, grn_obj *expr, int offset) +{ + grn_obj *res = NULL; + grn_expr *e = (grn_expr *)expr; + GRN_API_ENTER; + if (0 <= offset && offset < e->values_size) { + res = &e->values[offset]; + } + GRN_API_RETURN(res); +} + +#define DEFAULT_WEIGHT 5 +#define DEFAULT_DECAYSTEP 2 +#define DEFAULT_MAX_INTERVAL 10 +#define DEFAULT_SIMILARITY_THRESHOLD 0 +#define DEFAULT_TERM_EXTRACT_POLICY 0 +#define DEFAULT_WEIGHT_VECTOR_SIZE 4096 + +#define GRN_SCAN_INFO_MAX_N_ARGS 128 + +struct _grn_scan_info { + uint32_t start; + uint32_t end; + int32_t nargs; + int flags; + grn_operator op; + grn_operator logical_op; + grn_obj wv; + grn_obj index; + grn_obj *query; + grn_obj *args[GRN_SCAN_INFO_MAX_N_ARGS]; + int max_interval; + int similarity_threshold; + grn_obj scorers; + grn_obj scorer_args_exprs; + grn_obj scorer_args_expr_offsets; + struct { + grn_bool specified; + int start; + } position; +}; + +#define SI_FREE(si) do {\ + GRN_OBJ_FIN(ctx, &(si)->wv);\ + GRN_OBJ_FIN(ctx, &(si)->index);\ + GRN_OBJ_FIN(ctx, &(si)->scorers);\ + GRN_OBJ_FIN(ctx, &(si)->scorer_args_exprs);\ + GRN_OBJ_FIN(ctx, &(si)->scorer_args_expr_offsets);\ + GRN_FREE(si);\ +} while (0) + +#define SI_ALLOC_RAW(si, st) do {\ + if (((si) = GRN_MALLOCN(scan_info, 1))) {\ + GRN_INT32_INIT(&(si)->wv, GRN_OBJ_VECTOR);\ + GRN_PTR_INIT(&(si)->index, GRN_OBJ_VECTOR, GRN_ID_NIL);\ + (si)->logical_op = GRN_OP_OR;\ + (si)->flags = SCAN_PUSH;\ + (si)->nargs = 0;\ + (si)->max_interval = DEFAULT_MAX_INTERVAL;\ + (si)->similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD;\ + (si)->start = (st);\ + (si)->query = NULL;\ + GRN_PTR_INIT(&(si)->scorers, GRN_OBJ_VECTOR, GRN_ID_NIL);\ + GRN_PTR_INIT(&(si)->scorer_args_exprs, GRN_OBJ_VECTOR, GRN_ID_NIL);\ + GRN_UINT32_INIT(&(si)->scorer_args_expr_offsets, GRN_OBJ_VECTOR);\ + (si)->position.specified = GRN_FALSE;\ + (si)->position.start = 0;\ + }\ +} while (0) + +#define SI_ALLOC(si, i, st) do {\ + SI_ALLOC_RAW(si, st);\ + if (!(si)) {\ + int j;\ + for (j = 0; j < i; j++) { SI_FREE(sis[j]); }\ + GRN_FREE(sis);\ + return NULL;\ + }\ +} while (0) + +static scan_info ** +put_logical_op(grn_ctx *ctx, scan_info **sis, int *ip, grn_operator op, int start) +{ + int nparens = 1, ndifops = 0, i = *ip, j = i, r = 0; + while (j--) { + scan_info *s_ = sis[j]; + if (s_->flags & SCAN_POP) { + ndifops++; + nparens++; + } else { + if (s_->flags & SCAN_PUSH) { + if (!(--nparens)) { + if (!r) { + if (ndifops) { + if (j && op != GRN_OP_AND_NOT) { + nparens = 1; + ndifops = 0; + r = j; + } else { + SI_ALLOC(s_, i, start); + s_->flags = SCAN_POP; + s_->logical_op = op; + sis[i++] = s_; + *ip = i; + break; + } + } else { + s_->flags &= ~SCAN_PUSH; + s_->logical_op = op; + break; + } + } else { + if (ndifops) { + SI_ALLOC(s_, i, start); + s_->flags = SCAN_POP; + s_->logical_op = op; + sis[i++] = s_; + *ip = i; + } else { + s_->flags &= ~SCAN_PUSH; + s_->logical_op = op; + grn_memcpy(&sis[i], &sis[j], sizeof(scan_info *) * (r - j)); + grn_memmove(&sis[j], &sis[r], sizeof(scan_info *) * (i - r)); + grn_memcpy(&sis[i + j - r], &sis[i], sizeof(scan_info *) * (r - j)); + } + break; + } + } + } else { + if ((op == GRN_OP_AND_NOT) || (op != s_->logical_op)) { + ndifops++; + } + } + } + } + if (j < 0) { + ERR(GRN_INVALID_ARGUMENT, "unmatched nesting level"); + for (j = 0; j < i; j++) { SI_FREE(sis[j]); } + GRN_FREE(sis); + return NULL; + } + return sis; +} + +/* TODO: Remove me if nobody doesn't want to reuse the implementation again. */ +#if 0 +static const char *opstrs[] = { + "PUSH", + "POP", + "NOP", + "CALL", + "INTERN", + "GET_REF", + "GET_VALUE", + "AND", + "AND_NOT", + "OR", + "ASSIGN", + "STAR_ASSIGN", + "SLASH_ASSIGN", + "MOD_ASSIGN", + "PLUS_ASSIGN", + "MINUS_ASSIGN", + "SHIFTL_ASSIGN", + "SHIFTR_ASSIGN", + "SHIFTRR_ASSIGN", + "AND_ASSIGN", + "XOR_ASSIGN", + "OR_ASSIGN", + "JUMP", + "CJUMP", + "COMMA", + "BITWISE_OR", + "BITWISE_XOR", + "BITWISE_AND", + "BITWISE_NOT", + "EQUAL", + "NOT_EQUAL", + "LESS", + "GREATER", + "LESS_EQUAL", + "GREATER_EQUAL", + "IN", + "MATCH", + "NEAR", + "NEAR2", + "SIMILAR", + "TERM_EXTRACT", + "SHIFTL", + "SHIFTR", + "SHIFTRR", + "PLUS", + "MINUS", + "STAR", + "SLASH", + "MOD", + "DELETE", + "INCR", + "DECR", + "INCR_POST", + "DECR_POST", + "NOT", + "ADJUST", + "EXACT", + "LCP", + "PARTIAL", + "UNSPLIT", + "PREFIX", + "SUFFIX", + "GEO_DISTANCE1", + "GEO_DISTANCE2", + "GEO_DISTANCE3", + "GEO_DISTANCE4", + "GEO_WITHINP5", + "GEO_WITHINP6", + "GEO_WITHINP8", + "OBJ_SEARCH", + "EXPR_GET_VAR", + "TABLE_CREATE", + "TABLE_SELECT", + "TABLE_SORT", + "TABLE_GROUP", + "JSON_PUT" +}; + +static void +put_value(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + int len; + char namebuf[GRN_TABLE_MAX_KEY_SIZE]; + if ((len = grn_column_name(ctx, obj, namebuf, GRN_TABLE_MAX_KEY_SIZE))) { + GRN_TEXT_PUT(ctx, buf, namebuf, len); + } else { + grn_text_otoj(ctx, buf, obj, NULL); + } +} + +static grn_rc +grn_expr_inspect_internal(grn_ctx *ctx, grn_obj *buf, grn_obj *expr) +{ + uint32_t i, j; + grn_expr_var *var; + grn_expr_code *code; + grn_expr *e = (grn_expr *)expr; + grn_hash *vars = grn_expr_get_vars(ctx, expr, &i); + GRN_TEXT_PUTS(ctx, buf, "noname"); + GRN_TEXT_PUTC(ctx, buf, '('); + { + int i = 0; + grn_obj *value; + const char *name; + uint32_t name_len; + GRN_HASH_EACH(ctx, vars, id, &name, &name_len, &value, { + if (i++) { GRN_TEXT_PUTC(ctx, buf, ','); } + GRN_TEXT_PUT(ctx, buf, name, name_len); + GRN_TEXT_PUTC(ctx, buf, ':'); + put_value(ctx, buf, value); + }); + } + GRN_TEXT_PUTC(ctx, buf, ')'); + GRN_TEXT_PUTC(ctx, buf, '{'); + for (j = 0, code = e->codes; j < e->codes_curr; j++, code++) { + if (j) { GRN_TEXT_PUTC(ctx, buf, ','); } + grn_text_itoa(ctx, buf, code->modify); + if (code->op == GRN_OP_PUSH) { + for (i = 0, var = e->vars; i < e->nvars; i++, var++) { + if (&var->value == code->value) { + GRN_TEXT_PUTC(ctx, buf, '?'); + if (var->name_size) { + GRN_TEXT_PUT(ctx, buf, var->name, var->name_size); + } else { + grn_text_itoa(ctx, buf, (int)i); + } + break; + } + } + if (i == e->nvars) { + put_value(ctx, buf, code->value); + } + } else { + if (code->value) { + put_value(ctx, buf, code->value); + GRN_TEXT_PUTC(ctx, buf, ' '); + } + GRN_TEXT_PUTS(ctx, buf, opstrs[code->op]); + } + } + GRN_TEXT_PUTC(ctx, buf, '}'); + return GRN_SUCCESS; +} + +#define EXPRLOG(name,expr) do {\ + grn_obj strbuf;\ + GRN_TEXT_INIT(&strbuf, 0);\ + grn_expr_inspect_internal(ctx, &strbuf, (expr));\ + GRN_TEXT_PUTC(ctx, &strbuf, '\0');\ + GRN_LOG(ctx, GRN_LOG_NOTICE, "%s=(%s)", (name), GRN_TEXT_VALUE(&strbuf));\ + GRN_OBJ_FIN(ctx, &strbuf);\ +} while (0) +#endif + + +static void +scan_info_put_index(grn_ctx *ctx, scan_info *si, + grn_obj *index, uint32_t sid, int32_t weight, + grn_obj *scorer, + grn_obj *scorer_args_expr, + uint32_t scorer_args_expr_offset) +{ + GRN_PTR_PUT(ctx, &si->index, index); + GRN_UINT32_PUT(ctx, &si->wv, sid); + GRN_INT32_PUT(ctx, &si->wv, weight); + GRN_PTR_PUT(ctx, &si->scorers, scorer); + GRN_PTR_PUT(ctx, &si->scorer_args_exprs, scorer_args_expr); + GRN_UINT32_PUT(ctx, &si->scorer_args_expr_offsets, scorer_args_expr_offset); + { + int i, ni = (GRN_BULK_VSIZE(&si->index) / sizeof(grn_obj *)) - 1; + grn_obj **pi = &GRN_PTR_VALUE_AT(&si->index, ni); + for (i = 0; i < ni; i++, pi--) { + if (index == pi[-1]) { + if (i) { + int32_t *pw = &GRN_INT32_VALUE_AT(&si->wv, (ni - i) * 2); + grn_memmove(pw + 2, pw, sizeof(int32_t) * 2 * i); + pw[0] = (int32_t) sid; + pw[1] = weight; + grn_memmove(pi + 1, pi, sizeof(grn_obj *) * i); + pi[0] = index; + } + return; + } + } + } +} + +static int32_t +get_weight(grn_ctx *ctx, grn_expr_code *ec, uint32_t *offset) +{ + if (ec->modify == 2 && ec[2].op == GRN_OP_STAR && + ec[1].value && ec[1].value->header.type == GRN_BULK) { + if (offset) { + *offset = 2; + } + if (ec[1].value->header.domain == GRN_DB_INT32 || + ec[1].value->header.domain == GRN_DB_UINT32) { + return GRN_INT32_VALUE(ec[1].value); + } else { + int32_t weight = 1; + grn_obj weight_buffer; + GRN_INT32_INIT(&weight_buffer, 0); + if (!grn_obj_cast(ctx, ec[1].value, &weight_buffer, GRN_FALSE)) { + weight = GRN_INT32_VALUE(&weight_buffer); + } + grn_obj_unlink(ctx, &weight_buffer); + return weight; + } + } else { + if (offset) { + *offset = 0; + } + return 1; + } +} + +scan_info * +grn_scan_info_open(grn_ctx *ctx, int start) +{ + scan_info *si = GRN_MALLOCN(scan_info, 1); + + if (!si) { + return NULL; + } + + GRN_INT32_INIT(&si->wv, GRN_OBJ_VECTOR); + GRN_PTR_INIT(&si->index, GRN_OBJ_VECTOR, GRN_ID_NIL); + si->logical_op = GRN_OP_OR; + si->flags = SCAN_PUSH; + si->nargs = 0; + si->max_interval = DEFAULT_MAX_INTERVAL; + si->similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD; + si->start = start; + GRN_PTR_INIT(&si->scorers, GRN_OBJ_VECTOR, GRN_ID_NIL); + GRN_PTR_INIT(&si->scorer_args_exprs, GRN_OBJ_VECTOR, GRN_ID_NIL); + GRN_UINT32_INIT(&si->scorer_args_expr_offsets, GRN_OBJ_VECTOR); + si->position.specified = GRN_FALSE; + si->position.start = 0; + + return si; +} + +void +grn_scan_info_close(grn_ctx *ctx, scan_info *si) +{ + SI_FREE(si); +} + +void +grn_scan_info_put_index(grn_ctx *ctx, scan_info *si, + grn_obj *index, uint32_t sid, int32_t weight, + grn_obj *scorer, + grn_obj *scorer_args_expr, + uint32_t scorer_args_expr_offset) +{ + scan_info_put_index(ctx, si, index, sid, weight, + scorer, + scorer_args_expr, + scorer_args_expr_offset); +} + +scan_info ** +grn_scan_info_put_logical_op(grn_ctx *ctx, scan_info **sis, int *ip, + grn_operator op, int start) +{ + return put_logical_op(ctx, sis, ip, op, start); +} + +int32_t +grn_expr_code_get_weight(grn_ctx *ctx, grn_expr_code *ec, uint32_t *offset) +{ + return get_weight(ctx, ec, offset); +} + +int +grn_scan_info_get_flags(scan_info *si) +{ + return si->flags; +} + +void +grn_scan_info_set_flags(scan_info *si, int flags) +{ + si->flags = flags; +} + +grn_operator +grn_scan_info_get_logical_op(scan_info *si) +{ + return si->logical_op; +} + +void +grn_scan_info_set_logical_op(scan_info *si, grn_operator logical_op) +{ + si->logical_op = logical_op; +} + +grn_operator +grn_scan_info_get_op(scan_info *si) +{ + return si->op; +} + +void +grn_scan_info_set_op(scan_info *si, grn_operator op) +{ + si->op = op; +} + +void +grn_scan_info_set_end(scan_info *si, uint32_t end) +{ + si->end = end; +} + +void +grn_scan_info_set_query(scan_info *si, grn_obj *query) +{ + si->query = query; +} + +int +grn_scan_info_get_max_interval(scan_info *si) +{ + return si->max_interval; +} + +void +grn_scan_info_set_max_interval(scan_info *si, int max_interval) +{ + si->max_interval = max_interval; +} + +int +grn_scan_info_get_similarity_threshold(scan_info *si) +{ + return si->similarity_threshold; +} + +void +grn_scan_info_set_similarity_threshold(scan_info *si, int similarity_threshold) +{ + si->similarity_threshold = similarity_threshold; +} + +grn_bool +grn_scan_info_push_arg(scan_info *si, grn_obj *arg) +{ + if (si->nargs >= GRN_SCAN_INFO_MAX_N_ARGS) { + return GRN_FALSE; + } + + si->args[si->nargs++] = arg; + return GRN_TRUE; +} + +grn_obj * +grn_scan_info_get_arg(grn_ctx *ctx, scan_info *si, int i) +{ + if (i >= si->nargs) { + return NULL; + } + return si->args[i]; +} + +int +grn_scan_info_get_start_position(scan_info *si) +{ + return si->position.start; +} + +void +grn_scan_info_set_start_position(scan_info *si, int start) +{ + si->position.specified = GRN_TRUE; + si->position.start = start; +} + +void +grn_scan_info_reset_position(scan_info *si) +{ + si->position.specified = GRN_FALSE; +} + +static uint32_t +scan_info_build_match_expr_codes_find_index(grn_ctx *ctx, scan_info *si, + grn_expr *expr, uint32_t i, + grn_obj **index, + int *sid) +{ + grn_expr_code *ec; + uint32_t offset = 1; + grn_index_datum index_datum; + unsigned int n_index_data = 0; + + ec = &(expr->codes[i]); + switch (ec->value->header.type) { + case GRN_ACCESSOR : + n_index_data = grn_column_find_index_data(ctx, ec->value, si->op, + &index_datum, 1); + if (n_index_data > 0) { + grn_accessor *a = (grn_accessor *)(ec->value); + *sid = index_datum.section; + if (a->next && a->obj != index_datum.index) { + *index = ec->value; + } else { + *index = index_datum.index; + } + } + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + n_index_data = grn_column_find_index_data(ctx, ec->value, si->op, + &index_datum, 1); + if (n_index_data > 0) { + *index = index_datum.index; + *sid = index_datum.section; + } + break; + case GRN_COLUMN_INDEX : + { + uint32_t n_rest_codes; + + *index = ec->value; + + n_rest_codes = expr->codes_curr - i; + if (n_rest_codes >= 2 && + ec[1].value && + (ec[1].value->header.domain == GRN_DB_INT32 || + ec[1].value->header.domain == GRN_DB_UINT32) && + ec[2].op == GRN_OP_GET_MEMBER) { + if (ec[1].value->header.domain == GRN_DB_INT32) { + *sid = GRN_INT32_VALUE(ec[1].value) + 1; + } else { + *sid = GRN_UINT32_VALUE(ec[1].value) + 1; + } + offset += 2; + } + } + break; + default : + break; + } + + return offset; +} + +static uint32_t +scan_info_build_match_expr_codes(grn_ctx *ctx, + scan_info *si, + grn_expr *expr, + uint32_t i, + int32_t weight) +{ + grn_expr_code *ec; + grn_obj *index = NULL; + int sid = 0; + uint32_t offset = 0; + + ec = &(expr->codes[i]); + if (!ec->value) { + return i + 1; + } + + switch (ec->value->header.type) { + case GRN_ACCESSOR : + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + offset = scan_info_build_match_expr_codes_find_index(ctx, si, expr, i, + &index, &sid); + i += offset - 1; + if (index) { + if (ec->value->header.type == GRN_ACCESSOR) { + si->flags |= SCAN_ACCESSOR; + } + scan_info_put_index(ctx, si, index, sid, + get_weight(ctx, &(expr->codes[i]), &offset) + weight, + NULL, NULL, 0); + i += offset; + } + break; + case GRN_PROC : + if (!grn_obj_is_scorer_proc(ctx, ec->value)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, ec->value); + ERR(GRN_INVALID_ARGUMENT, + "procedure must be scorer: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return expr->codes_curr; + } + i++; + offset = scan_info_build_match_expr_codes_find_index(ctx, si, expr, i, + &index, &sid); + i += offset; + if (index) { + uint32_t scorer_args_expr_offset = 0; + if (expr->codes[i].op != GRN_OP_CALL) { + scorer_args_expr_offset = i; + } + while (i < expr->codes_curr && expr->codes[i].op != GRN_OP_CALL) { + i++; + } + scan_info_put_index(ctx, si, index, sid, + get_weight(ctx, &(expr->codes[i]), &offset) + weight, + ec->value, + (grn_obj *)expr, + scorer_args_expr_offset); + i += offset; + } + break; + default : + { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_obj_name(ctx, ec->value, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "invalid match target: <%.*s>", + name_size, name); + return expr->codes_curr; + } + break; + } + + return i + 1; +} + +static void +scan_info_build_match_expr(grn_ctx *ctx, + scan_info *si, + grn_expr *expr, + int32_t weight) +{ + uint32_t i; + i = 0; + while (i < expr->codes_curr) { + i = scan_info_build_match_expr_codes(ctx, si, expr, i, weight); + } +} + +static grn_bool +is_index_searchable_regexp(grn_ctx *ctx, grn_obj *regexp) +{ + const char *regexp_raw; + const char *regexp_raw_end; + grn_bool escaping = GRN_FALSE; + grn_bool dot = GRN_FALSE; + + if (!(regexp->header.domain == GRN_DB_SHORT_TEXT || + regexp->header.domain == GRN_DB_TEXT || + regexp->header.domain == GRN_DB_LONG_TEXT)) { + return GRN_FALSE; + } + + regexp_raw = GRN_TEXT_VALUE(regexp); + regexp_raw_end = regexp_raw + GRN_TEXT_LEN(regexp); + + while (regexp_raw < regexp_raw_end) { + unsigned int char_len; + + char_len = grn_charlen(ctx, regexp_raw, regexp_raw_end); + if (char_len == 0) { + return GRN_FALSE; + } + + if (char_len == 1) { + if (escaping) { + escaping = GRN_FALSE; + switch (regexp_raw[0]) { + case 'Z' : + case 'b' : + case 'B' : + case 'd' : + case 'D' : + case 'h' : + case 'H' : + case 'p' : + case 's' : + case 'S' : + case 'w' : + case 'W' : + case 'X' : + case 'k' : + case 'g' : + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : + return GRN_FALSE; + default : + break; + } + } else { + switch (regexp_raw[0]) { + case '.' : + escaping = GRN_FALSE; + if (dot) { + return GRN_FALSE; + } + dot = GRN_TRUE; + break; + case '*' : + escaping = GRN_FALSE; + if (!dot) { + return GRN_FALSE; + } + if (!grn_scan_info_regexp_dot_asterisk_enable) { + return GRN_FALSE; + } + dot = GRN_FALSE; + break; + case '[' : + case ']' : + case '|' : + case '?' : + case '+' : + case '{' : + case '}' : + case '^' : + case '$' : + case '(' : + case ')' : + escaping = GRN_FALSE; + return GRN_FALSE; + case '\\' : + if (dot) { + return GRN_FALSE; + } + escaping = GRN_TRUE; + break; + default : + if (dot) { + return GRN_FALSE; + } + escaping = GRN_FALSE; + break; + } + } + } else { + escaping = GRN_FALSE; + } + + regexp_raw += char_len; + } + + return GRN_TRUE; +} + +static void +scan_info_build_match(grn_ctx *ctx, scan_info *si, int32_t weight) +{ + grn_obj **p, **pe; + + if (si->op == GRN_OP_REGEXP) { + p = si->args; + pe = si->args + si->nargs; + for (; p < pe; p++) { + if ((*p)->header.type == GRN_BULK && + !is_index_searchable_regexp(ctx, *p)) { + return; + } + } + } + + p = si->args; + pe = si->args + si->nargs; + for (; p < pe; p++) { + if ((*p)->header.type == GRN_EXPR) { + scan_info_build_match_expr(ctx, si, (grn_expr *)(*p), weight); + } else if ((*p)->header.type == GRN_COLUMN_INDEX) { + scan_info_put_index(ctx, si, *p, 0, 1 + weight, NULL, NULL, 0); + } else if (grn_obj_is_proc(ctx, *p)) { + break; + } else if (GRN_DB_OBJP(*p)) { + grn_index_datum index_datum; + unsigned int n_index_data; + n_index_data = grn_column_find_index_data(ctx, *p, si->op, + &index_datum, 1); + if (n_index_data > 0) { + scan_info_put_index(ctx, si, + index_datum.index, index_datum.section, 1 + weight, + NULL, NULL, 0); + } + } else if (GRN_ACCESSORP(*p)) { + grn_index_datum index_datum; + unsigned int n_index_data; + si->flags |= SCAN_ACCESSOR; + n_index_data = grn_column_find_index_data(ctx, *p, si->op, + &index_datum, 1); + if (n_index_data > 0) { + grn_obj *index; + if (((grn_accessor *)(*p))->next) { + index = *p; + } else { + index = index_datum.index; + } + scan_info_put_index(ctx, si, + index, index_datum.section, 1 + weight, + NULL, NULL, 0); + } + } else { + switch (si->op) { + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + if (si->nargs == 3 && + *p == si->args[2] && + (*p)->header.domain == GRN_DB_INT32) { + si->max_interval = GRN_INT32_VALUE(*p); + } else { + si->query = *p; + } + break; + case GRN_OP_SIMILAR : + if (si->nargs == 3 && + *p == si->args[2] && + (*p)->header.domain == GRN_DB_INT32) { + si->similarity_threshold = GRN_INT32_VALUE(*p); + } else { + si->query = *p; + } + break; + default : + si->query = *p; + break; + } + } + } +} + +static grn_bool +grn_scan_info_build_full_not(grn_ctx *ctx, + scan_info **sis, + int *i, + grn_expr_code *codes, + grn_expr_code *code, + grn_expr_code *code_end, + grn_operator *next_code_op) +{ + scan_info *last_si; + + if (*i == 0) { + return GRN_TRUE; + } + + last_si = sis[*i - 1]; + switch (last_si->op) { + case GRN_OP_LESS : + last_si->op = GRN_OP_GREATER_EQUAL; + last_si->end++; + break; + case GRN_OP_LESS_EQUAL : + last_si->op = GRN_OP_GREATER; + last_si->end++; + break; + case GRN_OP_GREATER : + last_si->op = GRN_OP_LESS_EQUAL; + last_si->end++; + break; + case GRN_OP_GREATER_EQUAL : + last_si->op = GRN_OP_LESS; + last_si->end++; + break; + case GRN_OP_NOT_EQUAL : + last_si->op = GRN_OP_EQUAL; + last_si->end++; + break; + default : + if (*i == 1) { + if (GRN_BULK_VSIZE(&(last_si->index)) > 0) { + scan_info *all_records_si = NULL; + SI_ALLOC_RAW(all_records_si, 0); + if (!all_records_si) { + return GRN_FALSE; + } + all_records_si->op = GRN_OP_CALL; + all_records_si->args[all_records_si->nargs++] = + grn_ctx_get(ctx, "all_records", -1); + last_si->logical_op = GRN_OP_AND_NOT; + last_si->flags &= ~SCAN_PUSH; + sis[*i] = sis[*i - 1]; + sis[*i - 1] = all_records_si; + (*i)++; + } else { + if (last_si->op == GRN_OP_EQUAL) { + last_si->op = GRN_OP_NOT_EQUAL; + last_si->end++; + } else { + return GRN_FALSE; + } + } + } else { + grn_expr_code *next_code = code + 1; + + if (next_code >= code_end) { + return GRN_FALSE; + } + + switch (next_code->op) { + case GRN_OP_AND : + *next_code_op = GRN_OP_AND_NOT; + break; + case GRN_OP_AND_NOT : + *next_code_op = GRN_OP_AND; + break; + case GRN_OP_OR : + { + scan_info *all_records_si = NULL; + SI_ALLOC_RAW(all_records_si, 0); + if (!all_records_si) { + return GRN_FALSE; + } + all_records_si->op = GRN_OP_CALL; + all_records_si->args[all_records_si->nargs++] = + grn_ctx_get(ctx, "all_records", -1); + sis[*i] = sis[*i - 1]; + sis[*i - 1] = all_records_si; + (*i)++; + put_logical_op(ctx, sis, i, GRN_OP_AND_NOT, code - codes); + } + break; + default : + return GRN_FALSE; + break; + } + } + } + + return GRN_TRUE; +} + +static scan_info ** +grn_scan_info_build_full(grn_ctx *ctx, grn_obj *expr, int *n, + grn_operator op, grn_bool record_exist) +{ + grn_obj *var; + scan_stat stat; + int i, m = 0, o = 0; + int n_nots = 0; + scan_info **sis, *si = NULL; + grn_expr_code *c, *ce; + grn_expr *e = (grn_expr *)expr; + grn_operator next_code_op; + + if (!(var = grn_expr_get_var_by_offset(ctx, expr, 0))) { return NULL; } + for (stat = SCAN_START, c = e->codes, ce = &e->codes[e->codes_curr]; c < ce; c++) { + switch (c->op) { + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + case GRN_OP_SIMILAR : + case GRN_OP_PREFIX : + case GRN_OP_SUFFIX : + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + case GRN_OP_GEO_WITHINP5 : + case GRN_OP_GEO_WITHINP6 : + case GRN_OP_GEO_WITHINP8 : + case GRN_OP_TERM_EXTRACT : + case GRN_OP_REGEXP : + if (stat < SCAN_COL1 || SCAN_CONST < stat) { return NULL; } + stat = SCAN_START; + m++; + break; + case GRN_OP_BITWISE_OR : + case GRN_OP_BITWISE_XOR : + case GRN_OP_BITWISE_AND : + case GRN_OP_BITWISE_NOT : + case GRN_OP_SHIFTL : + case GRN_OP_SHIFTR : + case GRN_OP_SHIFTRR : + case GRN_OP_PLUS : + case GRN_OP_MINUS : + case GRN_OP_STAR : + case GRN_OP_MOD : + if (stat < SCAN_COL1 || SCAN_CONST < stat) { return NULL; } + stat = SCAN_START; + if (m != o + 1) { return NULL; } + break; + case GRN_OP_AND : + case GRN_OP_OR : + case GRN_OP_AND_NOT : + case GRN_OP_ADJUST : + switch (stat) { + case SCAN_START : + o++; + if (o >= m) { return NULL; } + break; + case SCAN_CONST : + o++; + m++; + if (o >= m) { return NULL; } + stat = SCAN_START; + break; + default : + return NULL; + break; + } + break; + case GRN_OP_PUSH : + { + grn_bool is_completed_term = GRN_FALSE; + if (c->modify > 0) { + switch ((c + c->modify)->op) { + case GRN_OP_AND : + case GRN_OP_OR : + case GRN_OP_AND_NOT : + case GRN_OP_ADJUST : + is_completed_term = GRN_TRUE; + break; + default : + is_completed_term = GRN_FALSE; + break; + } + } + if (is_completed_term) { + m++; + stat = SCAN_START; + } else { + stat = (c->value == var) ? SCAN_VAR : SCAN_CONST; + } + } + break; + case GRN_OP_GET_VALUE : + switch (stat) { + case SCAN_START : + case SCAN_CONST : + case SCAN_VAR : + stat = SCAN_COL1; + break; + case SCAN_COL1 : + stat = SCAN_COL2; + break; + case SCAN_COL2 : + break; + default : + return NULL; + break; + } + break; + case GRN_OP_CALL : + if ((c->flags & GRN_EXPR_CODE_RELATIONAL_EXPRESSION) || c + 1 == ce) { + stat = SCAN_START; + m++; + } else { + stat = SCAN_COL2; + } + break; + case GRN_OP_GET_REF : + switch (stat) { + case SCAN_START : + stat = SCAN_COL1; + break; + default : + return NULL; + break; + } + break; + case GRN_OP_GET_MEMBER : + switch (stat) { + case SCAN_CONST : + { + grn_expr_code *prev_c = c - 1; + if (prev_c->value->header.domain < GRN_DB_INT8 || + prev_c->value->header.domain > GRN_DB_UINT64) { + return NULL; + } + } + stat = SCAN_COL1; + break; + default : + return NULL; + break; + } + break; + case GRN_OP_NOT : + n_nots++; + break; + default : + return NULL; + break; + } + } + if (stat || m != o + 1) { return NULL; } + if (!(sis = GRN_MALLOCN(scan_info *, m + m + o + n_nots))) { return NULL; } + + next_code_op = -1; + for (i = 0, stat = SCAN_START, c = e->codes, ce = &e->codes[e->codes_curr]; c < ce; c++) { + grn_operator code_op; + if (next_code_op == (grn_operator)-1) { + code_op = c->op; + } else { + code_op = next_code_op; + next_code_op = -1; + } + switch (code_op) { + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + case GRN_OP_SIMILAR : + case GRN_OP_PREFIX : + case GRN_OP_SUFFIX : + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + case GRN_OP_GEO_WITHINP5 : + case GRN_OP_GEO_WITHINP6 : + case GRN_OP_GEO_WITHINP8 : + case GRN_OP_TERM_EXTRACT : + case GRN_OP_REGEXP : + stat = SCAN_START; + si->op = code_op; + si->end = c - e->codes; + sis[i++] = si; + { + int32_t weight = 0; + if (c->value && c->value->header.domain == GRN_DB_INT32) { + weight = GRN_INT32_VALUE(c->value); + } + scan_info_build_match(ctx, si, weight); + } + if (ctx->rc != GRN_SUCCESS) { + int j; + for (j = 0; j < i; j++) { SI_FREE(sis[j]); } + GRN_FREE(sis); + return NULL; + } + si = NULL; + break; + case GRN_OP_AND : + case GRN_OP_OR : + case GRN_OP_AND_NOT : + case GRN_OP_ADJUST : + if (stat == SCAN_CONST) { + si->op = GRN_OP_PUSH; + si->end = si->start; + sis[i++] = si; + si = NULL; + } + if (!put_logical_op(ctx, sis, &i, code_op, c - e->codes)) { return NULL; } + stat = SCAN_START; + break; + case GRN_OP_PUSH : + if (!si) { SI_ALLOC(si, i, c - e->codes); } + if (c->value == var) { + stat = SCAN_VAR; + } else { + if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) { + si->args[si->nargs++] = c->value; + } + if (stat == SCAN_START) { si->flags |= SCAN_PRE_CONST; } + stat = SCAN_CONST; + } + if (c->modify > 0) { + grn_bool is_completed_term = GRN_FALSE; + switch ((c + c->modify)->op) { + case GRN_OP_AND : + case GRN_OP_OR : + case GRN_OP_AND_NOT : + case GRN_OP_ADJUST : + is_completed_term = GRN_TRUE; + break; + default : + is_completed_term = GRN_FALSE; + break; + } + if (is_completed_term) { + si->op = GRN_OP_PUSH; + si->end = si->start; + sis[i++] = si; + si = NULL; + stat = SCAN_START; + } + } + break; + case GRN_OP_GET_VALUE : + switch (stat) { + case SCAN_START : + if (!si) { SI_ALLOC(si, i, c - e->codes); } + // fallthru + case SCAN_CONST : + case SCAN_VAR : + stat = SCAN_COL1; + if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) { + si->args[si->nargs++] = c->value; + } + break; + case SCAN_COL1 : + { + int j; + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + GRN_TEXT_PUTS(ctx, &inspected, "<"); + grn_inspect_name(ctx, &inspected, c->value); + GRN_TEXT_PUTS(ctx, &inspected, ">: <"); + grn_inspect(ctx, &inspected, expr); + GRN_TEXT_PUTS(ctx, &inspected, ">"); + ERR(GRN_INVALID_ARGUMENT, + "invalid expression: can't use column as a value: %.*s", + (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + SI_FREE(si); + for (j = 0; j < i; j++) { SI_FREE(sis[j]); } + GRN_FREE(sis); + return NULL; + } + stat = SCAN_COL2; + break; + case SCAN_COL2 : + break; + default : + break; + } + break; + case GRN_OP_CALL : + if (!si) { SI_ALLOC(si, i, c - e->codes); } + if ((c->flags & GRN_EXPR_CODE_RELATIONAL_EXPRESSION) || c + 1 == ce) { + stat = SCAN_START; + si->op = code_op; + si->end = c - e->codes; + sis[i++] = si; + /* better index resolving framework for functions should be implemented */ + if (grn_obj_is_selector_proc(ctx, si->args[0])) { + grn_obj *selector; + grn_obj **p; + grn_obj **pe; + grn_operator selector_op; + + selector = si->args[0]; + p = si->args + 1; + pe = si->args + si->nargs; + selector_op = grn_proc_get_selector_operator(ctx, selector); + for (; p < pe; p++) { + if (GRN_DB_OBJP(*p)) { + grn_index_datum index_datum; + unsigned int n_index_data; + n_index_data = grn_column_find_index_data(ctx, *p, selector_op, + &index_datum, 1); + if (n_index_data > 0) { + scan_info_put_index(ctx, si, + index_datum.index, index_datum.section, 1, + NULL, NULL, 0); + } + } else if (GRN_ACCESSORP(*p)) { + grn_index_datum index_datum; + unsigned int n_index_data; + si->flags |= SCAN_ACCESSOR; + n_index_data = grn_column_find_index_data(ctx, *p, selector_op, + &index_datum, 1); + if (n_index_data > 0) { + scan_info_put_index(ctx, si, + index_datum.index, index_datum.section, 1, + NULL, NULL, 0); + } + } else { + si->query = *p; + } + } + } + si = NULL; + } else { + stat = SCAN_COL2; + } + break; + case GRN_OP_GET_REF : + switch (stat) { + case SCAN_START : + if (!si) { SI_ALLOC(si, i, c - e->codes); } + stat = SCAN_COL1; + if (si->nargs < GRN_SCAN_INFO_MAX_N_ARGS) { + si->args[si->nargs++] = c->value; + } + break; + default : + break; + } + break; + case GRN_OP_GET_MEMBER : + { + grn_obj *start_position; + grn_obj buffer; + start_position = si->args[--si->nargs]; + GRN_INT32_INIT(&buffer, 0); + grn_obj_cast(ctx, start_position, &buffer, GRN_FALSE); + grn_scan_info_set_start_position(si, GRN_INT32_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + } + stat = SCAN_COL1; + break; + case GRN_OP_NOT : + { + grn_bool valid; + valid = grn_scan_info_build_full_not(ctx, + sis, + &i, + e->codes, + c, + ce, + &next_code_op); + if (!valid) { + int j; + for (j = 0; j < i; j++) { + SI_FREE(sis[j]); + } + GRN_FREE(sis); + return NULL; + } + } + break; + default : + break; + } + } + if (op == GRN_OP_OR && !record_exist) { + // for debug + if (!(sis[0]->flags & SCAN_PUSH) || (sis[0]->logical_op != op)) { + int j; + ERR(GRN_INVALID_ARGUMENT, "invalid expr"); + for (j = 0; j < i; j++) { SI_FREE(sis[j]); } + GRN_FREE(sis); + return NULL; + } else { + sis[0]->flags &= ~SCAN_PUSH; + sis[0]->logical_op = op; + } + } else { + if (!put_logical_op(ctx, sis, &i, op, c - e->codes)) { return NULL; } + } + *n = i; + return sis; +} + +static scan_info ** +grn_scan_info_build_simple_open(grn_ctx *ctx, int *n, grn_operator logical_op) +{ + scan_info **sis; + scan_info *si; + + sis = GRN_MALLOCN(scan_info *, 1); + if (!sis) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[scan_info][build] failed to allocate memory for scan_info **"); + return NULL; + } + + si = grn_scan_info_open(ctx, 0); + if (!si) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[scan_info][build] failed to allocate memory for scan_info *"); + GRN_FREE(sis); + return NULL; + } + + si->flags &= ~SCAN_PUSH; + si->logical_op = logical_op; + + sis[0] = si; + *n = 1; + + return sis; +} + +static scan_info ** +grn_scan_info_build_simple_value(grn_ctx *ctx, + grn_obj *expr, + int *n, + grn_operator logical_op, + grn_bool record_exist) +{ + grn_expr *e = (grn_expr *)expr; + scan_info **sis; + scan_info *si; + grn_expr_code *target = e->codes; + + switch (target->op) { + case GRN_OP_PUSH : + case GRN_OP_GET_VALUE : + break; + default : + return NULL; + break; + } + + sis = grn_scan_info_build_simple_open(ctx, n, logical_op); + if (!sis) { + return NULL; + } + + si = sis[0]; + si->end = 0; + si->op = target->op; + return sis; +} + +static scan_info ** +grn_scan_info_build_simple_operation(grn_ctx *ctx, + grn_obj *expr, + int *n, + grn_operator logical_op, + grn_bool record_exist) +{ + grn_expr *e = (grn_expr *)expr; + grn_expr_code *target; + grn_expr_code *constant; + grn_expr_code *operator; + scan_info **sis; + scan_info *si; + + target = e->codes + 0; + constant = e->codes + 1; + operator = e->codes + 2; + + if (target->op != GRN_OP_GET_VALUE) { + return NULL; + } + if (target->nargs != 1) { + return NULL; + } + if (!target->value) { + return NULL; + } + + if (constant->op != GRN_OP_PUSH) { + return NULL; + } + if (constant->nargs != 1) { + return NULL; + } + if (!constant->value) { + return NULL; + } + + if (operator->nargs != 2) { + return NULL; + } + switch (operator->op) { + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_SIMILAR : + case GRN_OP_PREFIX : + case GRN_OP_SUFFIX : + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + case GRN_OP_TERM_EXTRACT : + case GRN_OP_REGEXP : + break; + default : + return NULL; + break; + } + + sis = grn_scan_info_build_simple_open(ctx, n, logical_op); + if (!sis) { + return NULL; + } + + si = sis[0]; + si->end = 2; + si->op = operator->op; + si->args[si->nargs++] = target->value; + si->args[si->nargs++] = constant->value; + { + int32_t weight = 0; + if (operator->value && operator->value->header.domain == GRN_DB_INT32) { + weight = GRN_INT32_VALUE(operator->value); + } + scan_info_build_match(ctx, si, weight); + } + return sis; +} + +static scan_info ** +grn_scan_info_build_simple_and_operations(grn_ctx *ctx, + grn_obj *expr, + int *n, + grn_operator logical_op, + grn_bool record_exist) +{ + grn_expr *e = (grn_expr *)expr; + scan_info **sis = NULL; + int n_sis = 0; + int i; + int nth_sis; + + for (i = 0, nth_sis = 0; i < e->codes_curr; i += 3, nth_sis++) { + grn_expr_code *target = e->codes + i; + grn_expr_code *constant = e->codes + i + 1; + grn_expr_code *operator = e->codes + i + 2; + + if (target->op != GRN_OP_GET_VALUE) { + return NULL; + } + if (target->nargs != 1) { + return NULL; + } + if (!target->value) { + return NULL; + } + + if (constant->op != GRN_OP_PUSH) { + return NULL; + } + if (constant->nargs != 1) { + return NULL; + } + if (!constant->value) { + return NULL; + } + + if (operator->nargs != 2) { + return NULL; + } + switch (operator->op) { + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_SIMILAR : + case GRN_OP_PREFIX : + case GRN_OP_SUFFIX : + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + case GRN_OP_TERM_EXTRACT : + case GRN_OP_REGEXP : + break; + default : + return NULL; + break; + } + + if (nth_sis > 0) { + grn_expr_code *logical_operator = e->codes + i + 3; + + if (logical_operator->op != GRN_OP_AND) { + return NULL; + } + if (logical_operator->nargs != 2) { + return NULL; + } + + i++; + } + } + n_sis = nth_sis; + + sis = GRN_CALLOC(sizeof(scan_info *) * n_sis); + if (!sis) { + return NULL; + } + + for (i = 0, nth_sis = 0; i < e->codes_curr; i += 3, nth_sis++) { + grn_expr_code *target = e->codes + i; + grn_expr_code *constant = e->codes + i + 1; + grn_expr_code *operator = e->codes + i + 2; + scan_info *si; + + sis[nth_sis] = si = grn_scan_info_open(ctx, i); + if (!si) { + goto exit; + } + si->args[si->nargs++] = target->value; + si->args[si->nargs++] = constant->value; + si->op = operator->op; + si->end = i + 2; + si->flags &= ~SCAN_PUSH; + if (nth_sis == 0) { + si->logical_op = logical_op; + } else { + si->logical_op = GRN_OP_AND; + } + { + int32_t weight = 0; + if (operator->value && operator->value->header.domain == GRN_DB_INT32) { + weight = GRN_INT32_VALUE(operator->value); + } + scan_info_build_match(ctx, si, weight); + } + + if (nth_sis > 0) { + i++; + } + } + + *n = n_sis; + return sis; + +exit : + if (n_sis > 0) { + for (i = 0; i < n_sis; i++) { + scan_info *si = sis[i]; + if (si) { + grn_scan_info_close(ctx, si); + } + } + GRN_FREE(sis); + } + + return NULL; +} + +static scan_info ** +grn_scan_info_build_simple(grn_ctx *ctx, grn_obj *expr, int *n, + grn_operator logical_op, grn_bool record_exist) +{ + grn_expr *e = (grn_expr *)expr; + + if (e->codes_curr == 1) { + return grn_scan_info_build_simple_value(ctx, + expr, + n, + logical_op, + record_exist); + } else if (e->codes_curr == 3) { + return grn_scan_info_build_simple_operation(ctx, + expr, + n, + logical_op, + record_exist); + } else if (e->codes_curr % 4 == 3) { + return grn_scan_info_build_simple_and_operations(ctx, + expr, + n, + logical_op, + record_exist); + } + + return NULL; +} + +scan_info ** +grn_scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, + grn_operator op, grn_bool record_exist) +{ + scan_info **sis; + + sis = grn_scan_info_build_simple(ctx, expr, n, op, record_exist); +#ifdef GRN_WITH_MRUBY + if (!sis) { + grn_ctx_impl_mrb_ensure_init(ctx); + if (ctx->rc != GRN_SUCCESS) { + return NULL; + } + if (ctx->impl->mrb.state) { + return grn_mrb_scan_info_build(ctx, expr, n, op, record_exist); + } + } +#endif + if (!sis) { + sis = grn_scan_info_build_full(ctx, expr, n, op, record_exist); + } + return sis; +} + +void +grn_inspect_scan_info_list(grn_ctx *ctx, grn_obj *buffer, scan_info **sis, int n) +{ + int i; + + for (i = 0; i < n; i++) { + scan_info *si = sis[i]; + + grn_text_printf(ctx, buffer, "[%d]\n", i); + grn_text_printf(ctx, buffer, + " op: <%s>\n", + grn_operator_to_string(si->op)); + grn_text_printf(ctx, buffer, + " logical_op: <%s>\n", + grn_operator_to_string(si->logical_op)); + + if (si->op == GRN_OP_CALL) { + int i; + for (i = 0; i < si->nargs; i++) { + grn_text_printf(ctx, buffer, " args[%d]: <", i); + grn_inspect(ctx, buffer, si->args[i]); + GRN_TEXT_PUTS(ctx, buffer, ">\n"); + } + } else { + GRN_TEXT_PUTS(ctx, buffer, " index: <"); + grn_inspect(ctx, buffer, &(si->index)); + GRN_TEXT_PUTS(ctx, buffer, ">\n"); + + GRN_TEXT_PUTS(ctx, buffer, " query: <"); + grn_inspect(ctx, buffer, si->query); + GRN_TEXT_PUTS(ctx, buffer, ">\n"); + } + + grn_text_printf(ctx, buffer, + " expr: <%d..%d>\n", si->start, si->end); + } +} + +void +grn_p_scan_info_list(grn_ctx *ctx, scan_info **sis, int n) +{ + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect_scan_info_list(ctx, &inspected, sis, n); + printf("%.*s\n", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); +} + +inline static int32_t +exec_result_to_score(grn_ctx *ctx, grn_obj *result, grn_obj *score_buffer) +{ + if (!result) { + return 0; + } + + switch (result->header.type) { + case GRN_VOID : + return 0; + case GRN_BULK : + switch (result->header.domain) { + case GRN_DB_BOOL : + return GRN_BOOL_VALUE(result) ? 1 : 0; + case GRN_DB_INT32 : + return GRN_INT32_VALUE(result); + default : + GRN_BULK_REWIND(score_buffer); + if (grn_obj_cast(ctx, result, score_buffer, GRN_FALSE) != GRN_SUCCESS) { + return 1; + } + return GRN_INT32_VALUE(score_buffer); + } + case GRN_UVECTOR : + case GRN_PVECTOR : + case GRN_VECTOR : + return 1; + default : + return 1; /* TODO: 1 is reasonable? */ + } +} + +static void +grn_table_select_sequential(grn_ctx *ctx, grn_obj *table, grn_obj *expr, + grn_obj *v, grn_obj *res, grn_operator op) +{ + grn_obj *result; + grn_obj score_buffer; + int32_t score; + grn_id id, *idp; + grn_table_cursor *tc; + grn_hash_cursor *hc; + grn_hash *s = (grn_hash *)res; + grn_expr_executor *executor; + + executor = grn_expr_executor_open(ctx, expr); + if (!executor) { + return; + } + GRN_INT32_INIT(&score_buffer, 0); + switch (op) { + case GRN_OP_OR : + if ((tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, 0))) { + while ((id = grn_table_cursor_next(ctx, tc))) { + result = grn_expr_executor_exec(ctx, executor, id); + if (ctx->rc) { + break; + } + score = exec_result_to_score(ctx, result, &score_buffer); + if (score > 0) { + grn_rset_recinfo *ri; + if (grn_hash_add(ctx, s, &id, s->key_size, (void **)&ri, NULL)) { + grn_table_add_subrec(res, ri, score, (grn_rset_posinfo *)&id, 1); + } + } + } + grn_table_cursor_close(ctx, tc); + } + break; + case GRN_OP_AND : + if ((hc = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0))) { + while (grn_hash_cursor_next(ctx, hc)) { + grn_hash_cursor_get_key(ctx, hc, (void **) &idp); + result = grn_expr_executor_exec(ctx, executor, *idp); + if (ctx->rc) { + break; + } + score = exec_result_to_score(ctx, result, &score_buffer); + if (score > 0) { + grn_rset_recinfo *ri; + grn_hash_cursor_get_value(ctx, hc, (void **) &ri); + grn_table_add_subrec(res, ri, score, (grn_rset_posinfo *)idp, 1); + } else { + grn_hash_cursor_delete(ctx, hc, NULL); + } + } + grn_hash_cursor_close(ctx, hc); + } + break; + case GRN_OP_AND_NOT : + if ((hc = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0))) { + while (grn_hash_cursor_next(ctx, hc)) { + grn_hash_cursor_get_key(ctx, hc, (void **) &idp); + result = grn_expr_executor_exec(ctx, executor, *idp); + if (ctx->rc) { + break; + } + score = exec_result_to_score(ctx, result, &score_buffer); + if (score > 0) { + grn_hash_cursor_delete(ctx, hc, NULL); + } + } + grn_hash_cursor_close(ctx, hc); + } + break; + case GRN_OP_ADJUST : + if ((hc = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, 0, -1, 0))) { + while (grn_hash_cursor_next(ctx, hc)) { + grn_hash_cursor_get_key(ctx, hc, (void **) &idp); + result = grn_expr_executor_exec(ctx, executor, *idp); + if (ctx->rc) { + break; + } + score = exec_result_to_score(ctx, result, &score_buffer); + if (score > 0) { + grn_rset_recinfo *ri; + grn_hash_cursor_get_value(ctx, hc, (void **) &ri); + grn_table_add_subrec(res, ri, score, (grn_rset_posinfo *)idp, 1); + } + } + grn_hash_cursor_close(ctx, hc); + } + break; + default : + break; + } + GRN_OBJ_FIN(ctx, &score_buffer); + grn_expr_executor_close(ctx, executor); +} + +static inline void +grn_table_select_index_report(grn_ctx *ctx, const char *tag, grn_obj *index) +{ + grn_report_index(ctx, "[table][select]", tag, index); +} + +static inline void +grn_table_select_index_not_used_report(grn_ctx *ctx, + const char *tag, + grn_obj *index, + const char *reason) +{ + grn_report_index_not_used(ctx, "[table][select]", tag, index, reason); +} + +static inline grn_bool +grn_table_select_index_use_sequential_search(grn_ctx *ctx, + grn_obj *table, + grn_obj *res, + grn_operator logical_op, + const char *tag, + grn_obj *index) +{ + int n_records; + int n_filtered_records; + double filtered_ratio; + grn_obj reason; + + if (logical_op != GRN_OP_AND) { + return GRN_FALSE; + } + + n_records = grn_table_size(ctx, table); + n_filtered_records = grn_table_size(ctx, res); + if (n_records == 0) { + filtered_ratio = 1.0; + } else { + filtered_ratio = (double)n_filtered_records / (double)n_records; + } + + if (filtered_ratio >= grn_table_select_enough_filtered_ratio) { + return GRN_FALSE; + } + + if (n_filtered_records > grn_table_select_max_n_enough_filtered_records) { + return GRN_FALSE; + } + + GRN_TEXT_INIT(&reason, 0); + grn_text_printf(ctx, &reason, + "enough filtered: %.2f%%(%d/%d) < %.2f%% && %d <= %d", + filtered_ratio * 100, + n_filtered_records, + n_records, + grn_table_select_enough_filtered_ratio * 100, + n_filtered_records, + grn_table_select_max_n_enough_filtered_records); + GRN_TEXT_PUTC(ctx, &reason, '\0'); + grn_table_select_index_not_used_report(ctx, + tag, + index, + GRN_TEXT_VALUE(&reason)); + GRN_OBJ_FIN(ctx, &reason); + return GRN_TRUE; +} + +static inline grn_bool +grn_table_select_index_equal(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + scan_info *si, + grn_obj *res) +{ + grn_bool processed = GRN_FALSE; + + if (GRN_BULK_VSIZE(si->query) == 0) { + /* We can't use index for empty value. */ + return GRN_FALSE; + } + + if (si->flags & SCAN_ACCESSOR) { + if (index->header.type == GRN_ACCESSOR && !((grn_accessor *)index)->next) { + grn_obj dest; + grn_accessor *a = (grn_accessor *)index; + grn_posting posting; + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + grn_table_select_index_report(ctx, "[equal][accessor][id]", table); + GRN_UINT32_INIT(&dest, 0); + if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) { + posting.rid = GRN_UINT32_VALUE(&dest); + if (posting.rid) { + if (posting.rid == grn_table_at(ctx, table, posting.rid)) { + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, + si->logical_op); + } + } + processed = GRN_TRUE; + } + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op); + GRN_OBJ_FIN(ctx, &dest); + break; + case GRN_ACCESSOR_GET_KEY : + grn_table_select_index_report(ctx, "[equal][accessor][key]", table); + GRN_OBJ_INIT(&dest, GRN_BULK, 0, table->header.domain); + if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) { + if ((posting.rid = grn_table_get(ctx, table, + GRN_BULK_HEAD(&dest), + GRN_BULK_VSIZE(&dest)))) { + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, + si->logical_op); + } + processed = GRN_TRUE; + } + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op); + GRN_OBJ_FIN(ctx, &dest); + break; + } + } + } else { + const char *tag = "[equal]"; + grn_obj *domain = grn_ctx_at(ctx, index->header.domain); + + if (domain) { + grn_bool optimizable = GRN_FALSE; + + if (domain->header.domain == GRN_DB_SHORT_TEXT) { + grn_obj *normalizer = NULL; + grn_table_get_info(ctx, domain, NULL, NULL, NULL, &normalizer, NULL); + if (normalizer == grn_ctx_get(ctx, "NormalizerAuto", -1)) { + optimizable = GRN_TRUE; + } + } else { + optimizable = GRN_TRUE; + } + if (optimizable && + grn_table_select_index_use_sequential_search(ctx, + table, + res, + si->logical_op, + tag, + index)) { + domain = NULL; + } + } + + if (domain) { + grn_id tid; + + grn_table_select_index_report(ctx, tag, index); + + if (GRN_OBJ_GET_DOMAIN(si->query) == DB_OBJ(domain)->id) { + tid = GRN_RECORD_VALUE(si->query); + } else { + tid = grn_table_get(ctx, domain, + GRN_BULK_HEAD(si->query), + GRN_BULK_VSIZE(si->query)); + } + if (tid != GRN_ID_NIL) { + uint32_t sid; + int32_t weight; + grn_ii *ii = (grn_ii *)index; + grn_ii_cursor *ii_cursor; + + sid = GRN_UINT32_VALUE_AT(&(si->wv), 0); + weight = GRN_INT32_VALUE_AT(&(si->wv), 1); + ii_cursor = grn_ii_cursor_open(ctx, ii, tid, + GRN_ID_NIL, GRN_ID_MAX, + ii->n_elements, 0); + if (ii_cursor) { + grn_posting *posting; + while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) { + grn_posting new_posting; + + if (!(sid == 0 || posting->sid == sid)) { + continue; + } + + if (si->position.specified) { + while ((posting = grn_ii_cursor_next_pos(ctx, ii_cursor))) { + if (posting->pos == si->position.start) { + break; + } + } + if (!posting) { + continue; + } + } + + new_posting = *posting; + new_posting.weight *= weight; + grn_ii_posting_add(ctx, &new_posting, (grn_hash *)res, + si->logical_op); + } + grn_ii_cursor_close(ctx, ii_cursor); + } + } + processed = GRN_TRUE; + } + if (processed) { + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op); + } + } + + return processed; +} + +static inline grn_bool +grn_table_select_index_not_equal(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + scan_info *si, + grn_obj *res) +{ + grn_bool processed = GRN_FALSE; + + if (GRN_BULK_VSIZE(si->query) == 0) { + /* We can't use index for empty value. */ + return GRN_FALSE; + } + + if (si->logical_op != GRN_OP_AND) { + /* We can't use index for OR and AND_NOT. */ + return GRN_FALSE; + } + + if (si->flags & SCAN_ACCESSOR) { + if (index->header.type == GRN_ACCESSOR && !((grn_accessor *)index)->next) { + grn_obj dest; + grn_accessor *a = (grn_accessor *)index; + grn_id id; + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + grn_table_select_index_report(ctx, "[not-equal][accessor][id]", table); + GRN_UINT32_INIT(&dest, 0); + if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) { + id = GRN_UINT32_VALUE(&dest); + if (id != GRN_ID_NIL) { + if (id == grn_table_at(ctx, table, id)) { + grn_hash_delete(ctx, (grn_hash *)res, &id, sizeof(grn_id), NULL); + } + } + processed = GRN_TRUE; + } + GRN_OBJ_FIN(ctx, &dest); + break; + case GRN_ACCESSOR_GET_KEY : + grn_table_select_index_report(ctx, "[not-equal][accessor][key]", table); + GRN_OBJ_INIT(&dest, GRN_BULK, 0, table->header.domain); + if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) { + id = grn_table_get(ctx, table, + GRN_BULK_HEAD(&dest), + GRN_BULK_VSIZE(&dest)); + if (id != GRN_ID_NIL) { + grn_hash_delete(ctx, (grn_hash *)res, &id, sizeof(grn_id), NULL); + } + processed = GRN_TRUE; + } + GRN_OBJ_FIN(ctx, &dest); + break; + } + } + } else { + grn_obj *domain = grn_ctx_at(ctx, index->header.domain); + if (domain) { + grn_id tid; + if (GRN_OBJ_GET_DOMAIN(si->query) == DB_OBJ(domain)->id) { + tid = GRN_RECORD_VALUE(si->query); + } else { + tid = grn_table_get(ctx, domain, + GRN_BULK_HEAD(si->query), + GRN_BULK_VSIZE(si->query)); + } + if (tid == GRN_ID_NIL) { + processed = GRN_TRUE; + } else { + uint32_t sid; + int32_t weight; + grn_ii *ii = (grn_ii *)index; + grn_ii_cursor *ii_cursor; + + grn_table_select_index_report(ctx, "[not-equal]", index); + + sid = GRN_UINT32_VALUE_AT(&(si->wv), 0); + weight = GRN_INT32_VALUE_AT(&(si->wv), 1); + ii_cursor = grn_ii_cursor_open(ctx, ii, tid, + GRN_ID_NIL, GRN_ID_MAX, + ii->n_elements, 0); + if (ii_cursor) { + grn_posting *posting; + while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) { + if (!(sid == 0 || posting->sid == sid)) { + continue; + } + + if (si->position.specified) { + while ((posting = grn_ii_cursor_next_pos(ctx, ii_cursor))) { + if (posting->pos == si->position.start) { + break; + } + } + if (!posting) { + continue; + } + } + + grn_hash_delete(ctx, (grn_hash *)res, + &(posting->rid), sizeof(grn_id), + NULL); + } + grn_ii_cursor_close(ctx, ii_cursor); + processed = GRN_TRUE; + } + } + } + } + + return processed; +} + +static grn_bool +grn_table_select_index_prefix(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + scan_info *si, + grn_obj *res) +{ + grn_bool processed = GRN_FALSE; + if (si->flags & SCAN_ACCESSOR) { + if (index->header.type == GRN_ACCESSOR && + !((grn_accessor *)index)->next) { + grn_obj dest; + grn_accessor *a = (grn_accessor *)index; + grn_posting posting; + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + /* todo */ + break; + case GRN_ACCESSOR_GET_KEY : + if (si->op == GRN_OP_SUFFIX) { + grn_table_select_index_report(ctx, + "[suffix][accessor][key]", table); + } else { + grn_table_select_index_report(ctx, + "[prefix][accessor][key]", table); + } + GRN_OBJ_INIT(&dest, GRN_BULK, 0, table->header.domain); + if (!grn_obj_cast(ctx, si->query, &dest, GRN_FALSE)) { + grn_hash *pres; + if ((pres = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY))) { + grn_id *key; + grn_table_search(ctx, table, + GRN_BULK_HEAD(&dest), GRN_BULK_VSIZE(&dest), + si->op, (grn_obj *)pres, GRN_OP_OR); + GRN_HASH_EACH(ctx, pres, id, &key, NULL, NULL, { + posting.rid = *key; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, + si->logical_op); + }); + grn_hash_close(ctx, pres); + } + processed = GRN_TRUE; + } + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op); + GRN_OBJ_FIN(ctx, &dest); + } + } + } else { + grn_obj **indexes = &GRN_PTR_VALUE(&si->index); + int i, n_indexes = GRN_BULK_VSIZE(&si->index)/sizeof(grn_obj *); + for (i = 0; i < n_indexes; i++) { + grn_obj *index = indexes[i]; + grn_obj *lexicon = grn_ctx_at(ctx, index->header.domain); + if (lexicon) { + grn_hash *keys; + if ((keys = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY))) { + grn_id *key; + if (si->op == GRN_OP_SUFFIX) { + grn_table_select_index_report(ctx, "[suffix]", index); + } else { + grn_table_select_index_report(ctx, "[prefix]", index); + } + grn_table_search(ctx, lexicon, + GRN_BULK_HEAD(si->query), + GRN_BULK_VSIZE(si->query), + si->op, (grn_obj *)keys, GRN_OP_OR); + grn_obj_unlink(ctx, lexicon); + GRN_HASH_EACH(ctx, keys, id, &key, NULL, NULL, { + grn_ii_at(ctx, (grn_ii *)index, *key, (grn_hash *)res, si->logical_op); + }); + grn_hash_close(ctx, keys); + } + grn_obj_unlink(ctx, lexicon); + } + } + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, si->logical_op); + processed = GRN_TRUE; + } + return processed; +} + +static grn_bool +grn_table_select_index_suffix(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + scan_info *si, + grn_obj *res) +{ + grn_obj *domain; + if (si->flags & SCAN_ACCESSOR) { + domain = table; + } else { + domain = grn_ctx_at(ctx, index->header.domain); + } + if (domain->header.type != GRN_TABLE_PAT_KEY) { + return GRN_FALSE; + } + if (!(domain->header.flags & GRN_OBJ_KEY_WITH_SIS)) { + return GRN_FALSE; + } + return grn_table_select_index_prefix(ctx, table, index, si, res); +} + +static inline grn_bool +grn_table_select_index_match(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + scan_info *si, + grn_obj *res, + grn_id *min_id) +{ + grn_obj wv, **ip = &GRN_PTR_VALUE(&si->index); + int j; + int n_indexes = GRN_BULK_VSIZE(&si->index)/sizeof(grn_obj *); + int32_t *wp = &GRN_INT32_VALUE(&si->wv); + grn_search_optarg optarg; + grn_bool minimum_min_id_is_set = GRN_FALSE; + grn_id minimum_min_id = GRN_ID_NIL; + unsigned int previous_n_hits = grn_table_size(ctx, res); + + GRN_INT32_INIT(&wv, GRN_OBJ_VECTOR); + if (si->op == GRN_OP_MATCH) { + optarg.mode = GRN_OP_EXACT; + } else { + optarg.mode = si->op; + } + optarg.max_interval = 0; + optarg.similarity_threshold = 0; + switch (si->op) { + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + optarg.max_interval = si->max_interval; + break; + case GRN_OP_SIMILAR : + optarg.similarity_threshold = si->similarity_threshold; + break; + default : + break; + } + optarg.weight_vector = (int *)GRN_BULK_HEAD(&wv); + /* optarg.vector_size = GRN_BULK_VSIZE(&si->wv); */ + optarg.vector_size = 1; + optarg.proc = NULL; + optarg.max_size = 0; + optarg.match_info.flags |= GRN_MATCH_INFO_GET_MIN_RECORD_ID; + ctx->flags |= GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND; + for (j = 0; j < n_indexes; j++, ip++, wp += 2) { + uint32_t sid = (uint32_t) wp[0]; + int32_t weight = wp[1]; + if (grn_table_select_and_min_skip_enable) { + optarg.match_info.min = *min_id; + } else { + optarg.match_info.min = GRN_ID_NIL; + } + if (sid) { + int weight_index = sid - 1; + int current_vector_size; + current_vector_size = GRN_BULK_VSIZE(&wv)/sizeof(int32_t); + if (weight_index < current_vector_size) { + ((int *)GRN_BULK_HEAD(&wv))[weight_index] = weight; + } else { + GRN_INT32_SET_AT(ctx, &wv, weight_index, weight); + } + optarg.weight_vector = &GRN_INT32_VALUE(&wv); + optarg.vector_size = GRN_BULK_VSIZE(&wv)/sizeof(int32_t); + } else { + optarg.weight_vector = NULL; + optarg.vector_size = weight; + } + optarg.scorer = GRN_PTR_VALUE_AT(&(si->scorers), j); + optarg.scorer_args_expr = + GRN_PTR_VALUE_AT(&(si->scorer_args_exprs), j); + optarg.scorer_args_expr_offset = + GRN_UINT32_VALUE_AT(&(si->scorer_args_expr_offsets), j); + if (j < n_indexes - 1) { + if (sid && ip[0] == ip[1]) { continue; } + } else { + ctx->flags &= ~GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND; + } + grn_obj_search(ctx, ip[0], si->query, res, si->logical_op, &optarg); + if (optarg.weight_vector) { + int i; + for (i = 0; i < optarg.vector_size; i++) { + optarg.weight_vector[i] = 0; + } + } + GRN_BULK_REWIND(&wv); + if (!minimum_min_id_is_set || + optarg.match_info.min < minimum_min_id) { + minimum_min_id_is_set = GRN_TRUE; + minimum_min_id = optarg.match_info.min; + } + } + if ((si->logical_op == GRN_OP_AND) || + (si->logical_op == GRN_OP_OR && previous_n_hits == 0)) { + *min_id = minimum_min_id; + } else { + *min_id = GRN_ID_NIL; + } + GRN_OBJ_FIN(ctx, &wv); + + return GRN_TRUE; +} + +static inline grn_bool +grn_table_select_index_call_selector(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + scan_info *si, + grn_obj *selector, + grn_obj *res) +{ + grn_bool processed = GRN_FALSE; + grn_proc *proc = (grn_proc *)selector; + grn_rc rc; + + if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + char tag[GRN_TABLE_MAX_KEY_SIZE]; + name_size = grn_obj_name(ctx, + (grn_obj *)selector, + name, + GRN_TABLE_MAX_KEY_SIZE); + grn_snprintf(tag, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, + "[selector][%.*s]", + name_size, name); + grn_table_select_index_report(ctx, tag, index); + } + + if (index && index->header.type == GRN_ACCESSOR) { + grn_operator selector_op; + grn_obj *accessor = index; + grn_accessor *a = (grn_accessor *)accessor; + + selector_op = grn_proc_get_selector_operator(ctx, selector); + if (a->next) { + unsigned int accessor_deep = 0; + grn_obj *base_table = NULL; + grn_obj *base_index = NULL; + grn_obj *base_res = NULL; + + for (; a; a = a->next) { + if (a->next) { + accessor_deep++; + } else { + grn_index_datum index_data; + unsigned int n_index_datum; + + if (grn_obj_is_table(ctx, a->obj)) { + base_table = a->obj; + } else { + base_table = grn_ctx_at(ctx, a->obj->header.domain); + } + n_index_datum = grn_column_find_index_data(ctx, + a->obj, + selector_op, + &index_data, + 1); + if (n_index_datum > 0) { + base_index = index_data.index; + } + base_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + base_table, NULL); + } + } + rc = proc->callbacks.function.selector(ctx, + base_table, + base_index, + si->nargs, + si->args, + base_res, + GRN_OP_OR); + if (rc == GRN_SUCCESS) { + grn_accessor_resolve(ctx, + accessor, + accessor_deep, + base_res, + res, + si->logical_op); + } + grn_obj_close(ctx, base_res); + } else { + grn_index_datum index_data; + unsigned int n_index_datum; + grn_obj *target_index = NULL; + + n_index_datum = grn_column_find_index_data(ctx, + a->obj, + selector_op, + &index_data, + 1); + if (n_index_datum > 0) { + target_index = index_data.index; + } + rc = proc->callbacks.function.selector(ctx, + table, + target_index, + si->nargs, + si->args, + res, + si->logical_op); + } + } else { + rc = proc->callbacks.function.selector(ctx, + table, + index, + si->nargs, + si->args, + res, + si->logical_op); + } + + if (rc) { + /* TODO: report error */ + } else { + processed = GRN_TRUE; + } + + return processed; +} + +static inline grn_bool +grn_table_select_index_range_key(grn_ctx *ctx, + grn_obj *table, + scan_info *si, + grn_operator logical_op, + grn_obj *res) +{ + const char *tag = "[range][key]"; + grn_bool processed = GRN_FALSE; + grn_obj key; + + if (grn_table_select_index_use_sequential_search(ctx, + table, + res, + logical_op, + tag, + table)) { + return GRN_FALSE; + } + + GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain); + if (grn_obj_cast(ctx, si->query, &key, GRN_FALSE) == GRN_SUCCESS) { + grn_table_cursor *cursor; + const void *min = NULL, *max = NULL; + unsigned int min_size = 0, max_size = 0; + int offset = 0; + int limit = -1; + int flags = GRN_CURSOR_ASCENDING; + + grn_table_select_index_report(ctx, tag, table); + + switch (si->op) { + case GRN_OP_LESS : + flags |= GRN_CURSOR_LT; + max = GRN_BULK_HEAD(&key); + max_size = GRN_BULK_VSIZE(&key); + break; + case GRN_OP_GREATER : + flags |= GRN_CURSOR_GT; + min = GRN_BULK_HEAD(&key); + min_size = GRN_BULK_VSIZE(&key); + break; + case GRN_OP_LESS_EQUAL : + flags |= GRN_CURSOR_LE; + max = GRN_BULK_HEAD(&key); + max_size = GRN_BULK_VSIZE(&key); + break; + case GRN_OP_GREATER_EQUAL : + flags |= GRN_CURSOR_GE; + min = GRN_BULK_HEAD(&key); + min_size = GRN_BULK_VSIZE(&key); + break; + default : + break; + } + cursor = grn_table_cursor_open(ctx, table, + min, min_size, max, max_size, + offset, limit, flags); + if (cursor) { + uint32_t sid; + int32_t weight; + + sid = GRN_UINT32_VALUE_AT(&(si->wv), 0); + weight = GRN_INT32_VALUE_AT(&(si->wv), 1); + + if (sid == 0) { + grn_posting posting = {0}; + + posting.weight = weight - 1; + while ((posting.rid = grn_table_cursor_next(ctx, cursor))) { + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, logical_op); + } + } + processed = GRN_TRUE; + grn_table_cursor_close(ctx, cursor); + } + + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, logical_op); + } + GRN_OBJ_FIN(ctx, &key); + + return processed; +} + +static inline grn_bool +grn_table_select_index_range_column(grn_ctx *ctx, grn_obj *table, + grn_obj *index, + scan_info *si, grn_operator logical_op, + grn_obj *res) +{ + const char *tag = "[range]"; + grn_bool processed = GRN_FALSE; + grn_obj *index_table; + grn_obj range; + + index_table = grn_ctx_at(ctx, index->header.domain); + if (!index_table) { + return GRN_FALSE; + } + + if (grn_table_select_index_use_sequential_search(ctx, + table, + res, + logical_op, + tag, + index_table)) { + grn_obj_unlink(ctx, index_table); + return GRN_FALSE; + } + + GRN_OBJ_INIT(&range, GRN_BULK, 0, index_table->header.domain); + if (grn_obj_cast(ctx, si->query, &range, GRN_FALSE) == GRN_SUCCESS) { + grn_table_cursor *cursor; + const void *min = NULL, *max = NULL; + unsigned int min_size = 0, max_size = 0; + int offset = 0; + int limit = -1; + int flags = GRN_CURSOR_ASCENDING; + + grn_table_select_index_report(ctx, "[range]", index); + + switch (si->op) { + case GRN_OP_LESS : + flags |= GRN_CURSOR_LT; + max = GRN_BULK_HEAD(&range); + max_size = GRN_BULK_VSIZE(&range); + break; + case GRN_OP_GREATER : + flags |= GRN_CURSOR_GT; + min = GRN_BULK_HEAD(&range); + min_size = GRN_BULK_VSIZE(&range); + break; + case GRN_OP_LESS_EQUAL : + flags |= GRN_CURSOR_LE; + max = GRN_BULK_HEAD(&range); + max_size = GRN_BULK_VSIZE(&range); + break; + case GRN_OP_GREATER_EQUAL : + flags |= GRN_CURSOR_GE; + min = GRN_BULK_HEAD(&range); + min_size = GRN_BULK_VSIZE(&range); + break; + default : + break; + } + cursor = grn_table_cursor_open(ctx, index_table, + min, min_size, max, max_size, + offset, limit, flags); + if (cursor) { + grn_id tid; + uint32_t sid; + int32_t weight; + grn_ii *ii = (grn_ii *)index; + + sid = GRN_UINT32_VALUE_AT(&(si->wv), 0); + weight = GRN_INT32_VALUE_AT(&(si->wv), 1); + while ((tid = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_ii_cursor *ii_cursor; + + ii_cursor = grn_ii_cursor_open(ctx, ii, tid, + GRN_ID_NIL, GRN_ID_MAX, + ii->n_elements, 0); + if (ii_cursor) { + grn_posting *posting; + while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) { + grn_posting new_posting; + + if (!(sid == 0 || posting->sid == sid)) { + continue; + } + + if (si->position.specified) { + while ((posting = grn_ii_cursor_next_pos(ctx, ii_cursor))) { + if (posting->pos == si->position.start) { + break; + } + } + if (!posting) { + continue; + } + } + + new_posting = *posting; + new_posting.weight *= weight; + grn_ii_posting_add(ctx, &new_posting, (grn_hash *)res, logical_op); + } + } + grn_ii_cursor_close(ctx, ii_cursor); + } + processed = GRN_TRUE; + grn_table_cursor_close(ctx, cursor); + } + + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, logical_op); + } + GRN_OBJ_FIN(ctx, &range); + + grn_obj_unlink(ctx, index_table); + + return processed; +} + +static inline grn_bool +grn_table_select_index_range_accessor(grn_ctx *ctx, + grn_obj *table, + grn_obj *accessor, + scan_info *si, + grn_operator op, + grn_obj *res) +{ + grn_rc rc; + grn_accessor *a; + grn_obj *last_obj = NULL; + int n_accessors; + grn_bool have_resolver = GRN_FALSE; + grn_obj *base_res = NULL; + + for (a = (grn_accessor *)accessor; a; a = a->next) { + if (!a->next) { + last_obj = a->obj; + } + } + n_accessors = 0; + for (a = (grn_accessor *)accessor; a; a = a->next) { + n_accessors++; + if (GRN_OBJ_INDEX_COLUMNP(a->obj) || + grn_obj_is_table(ctx, a->obj)) { + have_resolver = GRN_TRUE; + break; + } + } + + { + grn_obj *index; + grn_obj *range; + + if (grn_obj_is_table(ctx, last_obj)) { + index = last_obj; + range = last_obj; + base_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + range, + NULL); + if (!base_res) { + return GRN_FALSE; + } + if (!grn_table_select_index_range_key(ctx, last_obj, si, GRN_OP_OR, + base_res)) { + grn_obj_unlink(ctx, base_res); + return GRN_FALSE; + } + } else { + if (grn_column_index(ctx, last_obj, si->op, &index, 1, NULL) == 0) { + return GRN_FALSE; + } + + range = grn_ctx_at(ctx, DB_OBJ(index)->range); + base_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + range, + NULL); + if (!base_res) { + return GRN_FALSE; + } + if (!grn_table_select_index_range_column(ctx, table, index, si, GRN_OP_OR, + base_res)) { + grn_obj_unlink(ctx, base_res); + return GRN_FALSE; + } + } + grn_table_select_index_report(ctx, "[range][accessor]", index); + } + + if (n_accessors == 1 && have_resolver) { + rc = grn_accessor_resolve(ctx, accessor, 1, base_res, res, op); + } else { + rc = grn_accessor_resolve(ctx, accessor, n_accessors - 1, base_res, res, op); + } + grn_obj_unlink(ctx, base_res); + + return rc == GRN_SUCCESS; +} + +static inline grn_bool +grn_table_select_index_range(grn_ctx *ctx, grn_obj *table, grn_obj *index, + scan_info *si, grn_obj *res) +{ + if (si->flags & SCAN_ACCESSOR) { + switch (index->header.type) { + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + /* table == index */ + return grn_table_select_index_range_key(ctx, table, si, + si->logical_op, res); + case GRN_ACCESSOR : + return grn_table_select_index_range_accessor(ctx, table, index, si, + si->logical_op, res); + default : + return GRN_FALSE; + } + } else { + return grn_table_select_index_range_column(ctx, table, index, si, + si->logical_op, res); + } +} + +static inline grn_bool +grn_table_select_index(grn_ctx *ctx, grn_obj *table, scan_info *si, + grn_obj *res, grn_id *min_id) +{ + grn_bool processed = GRN_FALSE; + if (!si->query) { + if (si->op != GRN_OP_CALL || !grn_obj_is_selector_proc(ctx, si->args[0])) { + return processed; + } + } + if (GRN_BULK_VSIZE(&si->index)) { + grn_obj *index = GRN_PTR_VALUE(&si->index); + switch (si->op) { + case GRN_OP_EQUAL : + processed = grn_table_select_index_equal(ctx, table, index, si, res); + break; + case GRN_OP_NOT_EQUAL : + processed = grn_table_select_index_not_equal(ctx, table, index, si, res); + break; + case GRN_OP_PREFIX : + processed = grn_table_select_index_prefix(ctx, table, index, si, res); + break; + case GRN_OP_SUFFIX : + processed = grn_table_select_index_suffix(ctx, table, index, si, res); + break; + case GRN_OP_MATCH : + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + case GRN_OP_SIMILAR : + case GRN_OP_REGEXP : + processed = grn_table_select_index_match(ctx, + table, + index, + si, + res, + min_id); + break; + case GRN_OP_TERM_EXTRACT : + if (si->flags & SCAN_ACCESSOR) { + if (index->header.type == GRN_ACCESSOR && + !((grn_accessor *)index)->next) { + grn_accessor *a = (grn_accessor *)index; + switch (a->action) { + case GRN_ACCESSOR_GET_KEY : + grn_table_select_index_report(ctx, "[term-extract][accessor][key]", + table); + grn_table_search(ctx, table, + GRN_TEXT_VALUE(si->query), GRN_TEXT_LEN(si->query), + GRN_OP_TERM_EXTRACT, res, si->logical_op); + processed = GRN_TRUE; + break; + } + } + } + break; + case GRN_OP_CALL : + if (grn_obj_is_selector_proc(ctx, si->args[0])) { + processed = grn_table_select_index_call_selector(ctx, + table, + index, + si, + si->args[0], + res); + } + break; + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + processed = grn_table_select_index_range(ctx, table, index, si, res); + break; + default : + /* todo : implement */ + /* todo : handle SCAN_PRE_CONST */ + break; + } + } else { + switch (si->op) { + case GRN_OP_CALL : + if (grn_obj_is_selector_proc(ctx, si->args[0])) { + grn_rc rc; + grn_proc *proc = (grn_proc *)(si->args[0]); + if (grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { + char proc_name[GRN_TABLE_MAX_KEY_SIZE]; + int proc_name_size; + char tag[GRN_TABLE_MAX_KEY_SIZE]; + proc_name_size = grn_obj_name(ctx, (grn_obj *)proc, + proc_name, GRN_TABLE_MAX_KEY_SIZE); + proc_name[proc_name_size] = '\0'; + grn_snprintf(tag, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, + "[selector][no-index][%s]", proc_name); + grn_table_select_index_report(ctx, tag, table); + } + rc = proc->callbacks.function.selector(ctx, + table, + NULL, + si->nargs, + si->args, + res, + si->logical_op); + if (rc) { + if (rc == GRN_FUNCTION_NOT_IMPLEMENTED) { + ERRCLR(ctx); + } else { + /* TODO: report error */ + } + } else { + processed = GRN_TRUE; + } + } + default : + break; + } + } + return processed; +} + +grn_obj * +grn_table_select(grn_ctx *ctx, grn_obj *table, grn_obj *expr, + grn_obj *res, grn_operator op) +{ + grn_obj *v; + unsigned int res_size; + grn_bool res_created = GRN_FALSE; + if (res) { + if (res->header.type != GRN_TABLE_HASH_KEY || + (res->header.domain != DB_OBJ(table)->id)) { + ERR(GRN_INVALID_ARGUMENT, "hash table required"); + return NULL; + } + } else { + if (!(res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL))) { + return NULL; + } + res_created = GRN_TRUE; + } + if (!(v = grn_expr_get_var_by_offset(ctx, expr, 0))) { + ERR(GRN_INVALID_ARGUMENT, "at least one variable must be defined"); + return NULL; + } + GRN_API_ENTER; + res_size = GRN_HASH_SIZE((grn_hash *)res); + if (op == GRN_OP_OR || res_size) { + int i; + grn_scanner *scanner; + scanner = grn_scanner_open(ctx, expr, op, res_size > 0); + if (scanner) { + grn_obj res_stack; + grn_expr *e = (grn_expr *)scanner->expr; + grn_expr_code *codes = e->codes; + uint32_t codes_curr = e->codes_curr; + grn_id min_id = GRN_ID_NIL; + v = grn_expr_get_var_by_offset(ctx, (grn_obj *)e, 0); + GRN_PTR_INIT(&res_stack, GRN_OBJ_VECTOR, GRN_ID_NIL); + for (i = 0; i < scanner->n_sis; i++) { + scan_info *si = scanner->sis[i]; + if (si->flags & SCAN_POP) { + grn_obj *res_; + GRN_PTR_POP(&res_stack, res_); + grn_table_setoperation(ctx, res_, res, res_, si->logical_op); + grn_obj_close(ctx, res); + res = res_; + min_id = GRN_ID_NIL; + } else { + grn_bool processed = GRN_FALSE; + if (si->flags & SCAN_PUSH) { + grn_obj *res_ = NULL; + res_ = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL); + if (!res_) { + break; + } + GRN_PTR_PUT(ctx, &res_stack, res); + res = res_; + min_id = GRN_ID_NIL; + } + if (si->logical_op != GRN_OP_AND) { + min_id = GRN_ID_NIL; + } + processed = grn_table_select_index(ctx, table, si, res, &min_id); + if (!processed) { + if (ctx->rc) { break; } + e->codes = codes + si->start; + e->codes_curr = si->end - si->start + 1; + grn_table_select_sequential(ctx, table, (grn_obj *)e, v, + res, si->logical_op); + min_id = GRN_ID_NIL; + } + } + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "filter(%d)", grn_table_size(ctx, res)); + if (ctx->rc) { + if (res_created) { + grn_obj_close(ctx, res); + } + res = NULL; + break; + } + } + + i = 0; + if (!res_created) { i++; } + for (; i < GRN_BULK_VSIZE(&res_stack) / sizeof(grn_obj *); i++) { + grn_obj *stacked_res; + stacked_res = *((grn_obj **)GRN_BULK_HEAD(&res_stack) + i); + grn_obj_close(ctx, stacked_res); + } + GRN_OBJ_FIN(ctx, &res_stack); + e->codes = codes; + e->codes_curr = codes_curr; + + grn_scanner_close(ctx, scanner); + } else { + if (!ctx->rc) { + grn_table_select_sequential(ctx, table, expr, v, res, op); + if (ctx->rc) { + if (res_created) { + grn_obj_close(ctx, res); + } + res = NULL; + } + } + } + } + GRN_API_RETURN(res); +} + +/* grn_expr_parse */ + +grn_obj * +grn_ptr_value_at(grn_obj *obj, int offset) +{ + int size = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *); + if (offset < 0) { offset = size + offset; } + return (0 <= offset && offset < size) + ? (((grn_obj **)GRN_BULK_HEAD(obj))[offset]) + : NULL; +} + +int32_t +grn_int32_value_at(grn_obj *obj, int offset) +{ + int size = GRN_BULK_VSIZE(obj) / sizeof(int32_t); + if (offset < 0) { offset = size + offset; } + return (0 <= offset && offset < size) + ? (((int32_t *)GRN_BULK_HEAD(obj))[offset]) + : 0; +} + +/* grn_expr_create_from_str */ + +#include "grn_snip.h" + +typedef struct { + grn_ctx *ctx; + grn_obj *e; + grn_obj *v; + const char *str; + const char *cur; + const char *str_end; + grn_obj *table; + grn_obj *default_column; + grn_obj buf; + grn_obj token_stack; + grn_obj column_stack; + grn_obj op_stack; + grn_obj mode_stack; + grn_obj max_interval_stack; + grn_obj similarity_threshold_stack; + grn_obj weight_stack; + grn_operator default_op; + grn_select_optarg opt; + grn_operator default_mode; + grn_expr_flags flags; + grn_expr_flags default_flags; + int escalation_threshold; + int escalation_decaystep; + int weight_offset; + grn_hash *weight_set; + snip_cond *snip_conds; + grn_hash *object_literal; + int paren_depth; + struct { + const char *string; + size_t string_length; + int token; + int weight; + } pending_token; +} efs_info; + +typedef struct { + grn_operator op; + int weight; +} efs_op; + +inline static void +skip_space(grn_ctx *ctx, efs_info *q) +{ + unsigned int len; + while (q->cur < q->str_end && grn_isspace(q->cur, ctx->encoding)) { + /* null check and length check */ + if (!(len = grn_charlen(ctx, q->cur, q->str_end))) { + q->cur = q->str_end; + break; + } + q->cur += len; + } +} + +static grn_bool +parse_query_op(efs_info *q, efs_op *op, grn_operator *mode, int *option) +{ + grn_bool found = GRN_TRUE; + const char *start, *end = q->cur; + switch (*end) { + case 'S' : + *mode = GRN_OP_SIMILAR; + start = ++end; + *option = grn_atoi(start, q->str_end, (const char **)&end); + if (start == end) { *option = DEFAULT_SIMILARITY_THRESHOLD; } + q->cur = end; + break; + case 'N' : + *mode = GRN_OP_NEAR; + start = ++end; + *option = grn_atoi(start, q->str_end, (const char **)&end); + if (start == end) { *option = DEFAULT_MAX_INTERVAL; } + q->cur = end; + break; + case 'n' : + *mode = GRN_OP_NEAR2; + start = ++end; + *option = grn_atoi(start, q->str_end, (const char **)&end); + if (start == end) { *option = DEFAULT_MAX_INTERVAL; } + q->cur = end; + break; + case 'T' : + *mode = GRN_OP_TERM_EXTRACT; + start = ++end; + *option = grn_atoi(start, q->str_end, (const char **)&end); + if (start == end) { *option = DEFAULT_TERM_EXTRACT_POLICY; } + q->cur = end; + break; + case 'X' : /* force exact mode */ + op->op = GRN_OP_AND; + *mode = GRN_OP_EXACT; + *option = 0; + start = ++end; + q->cur = end; + break; + default : + found = GRN_FALSE; + break; + } + return found; +} + +#define DISABLE_UNUSED_CODE 1 +#ifndef DISABLE_UNUSED_CODE +static const char * +get_weight_vector(grn_ctx *ctx, efs_info *query, const char *source) +{ + const char *p; + + if (!query->opt.weight_vector && + !query->weight_set && + !(query->opt.weight_vector = GRN_CALLOC(sizeof(int) * DEFAULT_WEIGHT_VECTOR_SIZE))) { + GRN_LOG(ctx, GRN_LOG_ALERT, "get_weight_vector malloc fail"); + return source; + } + for (p = source; p < query->str_end; ) { + unsigned int key; + int value; + + /* key, key is not zero */ + key = grn_atoui(p, query->str_end, &p); + if (!key || key > GRN_ID_MAX) { break; } + + /* value */ + if (*p == ':') { + p++; + value = grn_atoi(p, query->str_end, &p); + } else { + value = 1; + } + + if (query->weight_set) { + int *pval; + if (grn_hash_add(ctx, query->weight_set, &key, sizeof(unsigned int), (void **)&pval, NULL)) { + *pval = value; + } + } else if (key < DEFAULT_WEIGHT_VECTOR_SIZE) { + query->opt.weight_vector[key - 1] = value; + } else { + GRN_FREE(query->opt.weight_vector); + query->opt.weight_vector = NULL; + if (!(query->weight_set = grn_hash_create(ctx, NULL, sizeof(unsigned int), sizeof(int), + 0))) { + return source; + } + p = source; /* reparse */ + continue; + } + if (*p != ',') { break; } + p++; + } + return p; +} + +static void +get_pragma(grn_ctx *ctx, efs_info *q) +{ + const char *start, *end = q->cur; + while (end < q->str_end && *end == GRN_QUERY_PREFIX) { + if (++end >= q->str_end) { break; } + switch (*end) { + case 'E' : + start = ++end; + q->escalation_threshold = grn_atoi(start, q->str_end, (const char **)&end); + while (end < q->str_end && (('0' <= *end && *end <= '9') || *end == '-')) { end++; } + if (*end == ',') { + start = ++end; + q->escalation_decaystep = grn_atoi(start, q->str_end, (const char **)&end); + } + q->cur = end; + break; + case 'D' : + start = ++end; + while (end < q->str_end && *end != GRN_QUERY_PREFIX && !grn_isspace(end, ctx->encoding)) { + end++; + } + if (end > start) { + switch (*start) { + case 'O' : + q->default_op = GRN_OP_OR; + break; + case GRN_QUERY_AND : + q->default_op = GRN_OP_AND; + break; + case GRN_QUERY_AND_NOT : + q->default_op = GRN_OP_AND_NOT; + break; + case GRN_QUERY_ADJ_INC : + q->default_op = GRN_OP_ADJUST; + break; + } + } + q->cur = end; + break; + case 'W' : + start = ++end; + end = (char *)get_weight_vector(ctx, q, start); + q->cur = end; + break; + } + } +} + +static int +section_weight_cb(grn_ctx *ctx, grn_hash *r, const void *rid, int sid, void *arg) +{ + int *w; + grn_hash *s = (grn_hash *)arg; + if (s && grn_hash_get(ctx, s, &sid, sizeof(grn_id), (void **)&w)) { + return *w; + } else { + return 0; + } +} +#endif + +#include "grn_ecmascript.h" +#include "grn_ecmascript.c" + +static grn_rc +grn_expr_parser_open(grn_ctx *ctx) +{ + if (!ctx->impl->parser) { + ctx->impl->parser = grn_expr_parserAlloc(malloc); + } + return ctx->rc; +} + +#define PARSE(token) grn_expr_parser(ctx->impl->parser, (token), 0, q) + +static void +parse_query_accept_string(grn_ctx *ctx, efs_info *efsi, + const char *str, unsigned int str_size) +{ + grn_obj *column, *token; + grn_operator mode; + int32_t weight; + + GRN_PTR_PUT(ctx, &efsi->token_stack, + grn_expr_add_str(ctx, efsi->e, str, str_size)); + { + efs_info *q = efsi; + PARSE(GRN_EXPR_TOKEN_QSTRING); + } + + GRN_PTR_POP(&efsi->token_stack, token); + column = grn_ptr_value_at(&efsi->column_stack, -1); + grn_expr_append_const(efsi->ctx, efsi->e, column, GRN_OP_GET_VALUE, 1); + grn_expr_append_obj(efsi->ctx, efsi->e, token, GRN_OP_PUSH, 1); + + mode = grn_int32_value_at(&efsi->mode_stack, -1); + weight = grn_int32_value_at(&efsi->weight_stack, -1); + switch (mode) { + case GRN_OP_ASSIGN : + grn_expr_append_op(efsi->ctx, efsi->e, mode, 2); + break; + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + { + int max_interval; + max_interval = grn_int32_value_at(&efsi->max_interval_stack, -1); + grn_expr_append_const_int(efsi->ctx, efsi->e, max_interval, + GRN_OP_PUSH, 1); + if (weight == 0) { + grn_expr_append_op(efsi->ctx, efsi->e, mode, 3); + } else { + grn_expr_append_const_int(efsi->ctx, efsi->e, weight, mode, 3); + } + } + break; + case GRN_OP_SIMILAR : + { + int similarity_threshold; + similarity_threshold = + grn_int32_value_at(&efsi->similarity_threshold_stack, -1); + grn_expr_append_const_int(efsi->ctx, efsi->e, similarity_threshold, + GRN_OP_PUSH, 1); + if (weight == 0) { + grn_expr_append_op(efsi->ctx, efsi->e, mode, 3); + } else { + grn_expr_append_const_int(efsi->ctx, efsi->e, weight, mode, 3); + } + } + break; + default : + if (weight == 0) { + grn_expr_append_op(efsi->ctx, efsi->e, mode, 2); + } else { + grn_expr_append_const_int(efsi->ctx, efsi->e, weight, mode, 2); + } + break; + } +} + +static void +parse_query_flush_pending_token(grn_ctx *ctx, efs_info *q) +{ + const char *cur_keep; + + if (!(q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) { + return; + } + + if (q->pending_token.string_length == 0) { + return; + } + + cur_keep = q->cur; + q->cur = q->pending_token.string; + if (q->pending_token.token == GRN_EXPR_TOKEN_ADJUST || + q->pending_token.token == GRN_EXPR_TOKEN_NEGATIVE) { + GRN_INT32_PUT(ctx, &q->weight_stack, q->pending_token.weight); + } + PARSE(q->pending_token.token); + q->cur = cur_keep; + + q->pending_token.string = NULL; + q->pending_token.string_length = 0; + q->pending_token.token = 0; + q->pending_token.weight = 0; +} + +static void +parse_query_accept_logical_op(grn_ctx *ctx, + efs_info *q, + const char *string, + unsigned int string_length, + int token) +{ + if (!(q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) { + PARSE(token); + return; + } + + if (q->pending_token.string_length > 0) { + parse_query_accept_string(ctx, + q, + q->pending_token.string, + q->pending_token.string_length); + } + + q->pending_token.string = string; + q->pending_token.string_length = string_length; + q->pending_token.token = token; +} + +static void +parse_query_accept_adjust(grn_ctx *ctx, + efs_info *q, + const char *string, + unsigned int string_length, + int token, + int weight) +{ + if (!(q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) { + GRN_INT32_PUT(ctx, &q->weight_stack, weight); + PARSE(token); + return; + } + + if (q->pending_token.string_length > 0) { + parse_query_accept_string(ctx, + q, + q->pending_token.string, + q->pending_token.string_length); + } + + q->pending_token.string = string; + q->pending_token.string_length = string_length; + q->pending_token.token = token; + q->pending_token.weight = weight; +} + +static grn_rc +parse_query_word(grn_ctx *ctx, efs_info *q) +{ + const char *end; + unsigned int len; + GRN_BULK_REWIND(&q->buf); + for (end = q->cur;; ) { + /* null check and length check */ + if (!(len = grn_charlen(ctx, end, q->str_end))) { + q->cur = q->str_end; + break; + } + if (grn_isspace(end, ctx->encoding) || + *end == GRN_QUERY_PARENL || *end == GRN_QUERY_PARENR) { + q->cur = end; + break; + } + if (q->flags & GRN_EXPR_ALLOW_COLUMN && *end == GRN_QUERY_COLUMN) { + grn_operator mode; + grn_obj *c = grn_obj_column(ctx, q->table, + GRN_TEXT_VALUE(&q->buf), + GRN_TEXT_LEN(&q->buf)); + if (c && end + 1 < q->str_end) { + switch (end[1]) { + case '!' : + mode = GRN_OP_NOT_EQUAL; + q->cur = end + 2; + break; + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + mode = GRN_OP_ASSIGN; + q->cur = end + 2; + } else { + mode = GRN_OP_EQUAL; + q->cur = end + 1; + } + break; + case '<' : + if (end + 2 < q->str_end && end[2] == '=') { + mode = GRN_OP_LESS_EQUAL; + q->cur = end + 3; + } else { + mode = GRN_OP_LESS; + q->cur = end + 2; + } + break; + case '>' : + if (end + 2 < q->str_end && end[2] == '=') { + mode = GRN_OP_GREATER_EQUAL; + q->cur = end + 3; + } else { + mode = GRN_OP_GREATER; + q->cur = end + 2; + } + break; + case '@' : + mode = GRN_OP_MATCH; + q->cur = end + 2; + break; + case '^' : + mode = GRN_OP_PREFIX; + q->cur = end + 2; + break; + case '$' : + mode = GRN_OP_SUFFIX; + q->cur = end + 2; + break; + case '~' : + mode = GRN_OP_REGEXP; + q->cur = end + 2; + break; + default : + mode = GRN_OP_EQUAL; + q->cur = end + 1; + break; + } + } else if (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR) { + GRN_TEXT_PUT(ctx, &q->buf, end, len); + end += len; + continue; + } else { + ERR(GRN_INVALID_ARGUMENT, "column lookup failed"); + q->cur = q->str_end; + return ctx->rc; + } + parse_query_flush_pending_token(ctx, q); + PARSE(GRN_EXPR_TOKEN_IDENTIFIER); + PARSE(GRN_EXPR_TOKEN_RELATIVE_OP); + + grn_expr_take_obj(ctx, q->e, c); + GRN_PTR_PUT(ctx, &q->column_stack, c); + GRN_INT32_PUT(ctx, &q->mode_stack, mode); + + return GRN_SUCCESS; + } else if (GRN_TEXT_LEN(&q->buf) > 0 && *end == GRN_QUERY_PREFIX) { + q->cur = end + 1; + GRN_INT32_PUT(ctx, &q->mode_stack, GRN_OP_PREFIX); + break; + } else if (*end == GRN_QUERY_ESCAPE) { + end += len; + if (!(len = grn_charlen(ctx, end, q->str_end))) { + q->cur = q->str_end; + break; + } + } + GRN_TEXT_PUT(ctx, &q->buf, end, len); + end += len; + } + parse_query_flush_pending_token(ctx, q); + parse_query_accept_string(ctx, + q, + GRN_TEXT_VALUE(&q->buf), + GRN_TEXT_LEN(&q->buf)); + + return GRN_SUCCESS; +} + +static grn_rc +parse_query(grn_ctx *ctx, efs_info *q) +{ + int option = 0; + grn_operator mode; + efs_op op_, *op = &op_; + grn_bool first_token = GRN_TRUE; + grn_bool only_first_and = GRN_FALSE; + grn_bool block_started = GRN_FALSE; + + op->op = q->default_op; + op->weight = DEFAULT_WEIGHT; + while (!ctx->rc) { + skip_space(ctx, q); + + if (q->cur >= q->str_end) { goto exit; } + if (*q->cur == '\0') { goto exit; } + + only_first_and = GRN_FALSE; + switch (*q->cur) { + case GRN_QUERY_PARENR : + if (q->paren_depth == 0 && q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR) { + const char parenr = GRN_QUERY_PARENR; + parse_query_flush_pending_token(ctx, q); + parse_query_accept_string(ctx, q, &parenr, 1); + } else { + parse_query_flush_pending_token(ctx, q); + PARSE(GRN_EXPR_TOKEN_PARENR); + q->paren_depth--; + } + q->cur++; + break; + case GRN_QUERY_QUOTEL : + q->cur++; + + { + grn_bool closed = GRN_FALSE; + const char *start, *s; + start = s = q->cur; + GRN_BULK_REWIND(&q->buf); + while (1) { + unsigned int len; + if (s >= q->str_end) { + q->cur = s; + break; + } + len = grn_charlen(ctx, s, q->str_end); + if (len == 0) { + /* invalid string containing malformed multibyte char */ + goto exit; + } else if (len == 1) { + if (*s == GRN_QUERY_QUOTER) { + q->cur = s + 1; + closed = GRN_TRUE; + break; + } else if (*s == GRN_QUERY_ESCAPE && s + 1 < q->str_end) { + s++; + len = grn_charlen(ctx, s, q->str_end); + } + } + GRN_TEXT_PUT(ctx, &q->buf, s, len); + s += len; + } + if (!closed && (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) { + q->cur = start - 1; + parse_query_word(ctx, q); + } else { + parse_query_flush_pending_token(ctx, q); + parse_query_accept_string(ctx, + q, + GRN_TEXT_VALUE(&q->buf), + GRN_TEXT_LEN(&q->buf)); + } + } + + break; + case GRN_QUERY_PREFIX : + q->cur++; + if (parse_query_op(q, op, &mode, &option)) { + switch (mode) { + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + GRN_INT32_PUT(ctx, &q->max_interval_stack, option); + break; + case GRN_OP_SIMILAR : + GRN_INT32_PUT(ctx, &q->similarity_threshold_stack, option); + break; + default : + break; + } + GRN_INT32_PUT(ctx, &q->mode_stack, mode); + parse_query_flush_pending_token(ctx, q); + PARSE(GRN_EXPR_TOKEN_RELATIVE_OP); + } else { + q->cur--; + parse_query_word(ctx, q); + } + break; + case GRN_QUERY_AND : + if (first_token) { + only_first_and = GRN_TRUE; + } else { + op->op = GRN_OP_AND; + parse_query_accept_logical_op(ctx, + q, + q->cur, 1, + GRN_EXPR_TOKEN_LOGICAL_AND); + } + q->cur++; + break; + case GRN_QUERY_AND_NOT : + if (first_token) { + if (q->flags & GRN_EXPR_ALLOW_LEADING_NOT) { + grn_obj *all_records = grn_ctx_get(ctx, "all_records", 11); + if (all_records) { + /* dummy token */ + PARSE(GRN_EXPR_TOKEN_QSTRING); + grn_expr_append_obj(ctx, q->e, all_records, GRN_OP_PUSH, 1); + grn_expr_append_op(ctx, q->e, GRN_OP_CALL, 0); + } + } else if (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR) { + parse_query_flush_pending_token(ctx, q); + parse_query_accept_string(ctx, q, q->cur, 1); + q->cur++; + break; + } + } + op->op = GRN_OP_AND_NOT; + parse_query_accept_logical_op(ctx, + q, + q->cur, 1, + GRN_EXPR_TOKEN_LOGICAL_AND_NOT); + q->cur++; + break; + case GRN_QUERY_ADJ_INC : + if (op->weight < 127) { op->weight++; } + op->op = GRN_OP_ADJUST; + parse_query_accept_adjust(ctx, + q, + q->cur, 1, + GRN_EXPR_TOKEN_ADJUST, + op->weight); + q->cur++; + break; + case GRN_QUERY_ADJ_DEC : + if (op->weight > -128) { op->weight--; } + op->op = GRN_OP_ADJUST; + parse_query_accept_adjust(ctx, + q, + q->cur, 1, + GRN_EXPR_TOKEN_ADJUST, + op->weight); + q->cur++; + break; + case GRN_QUERY_ADJ_NEG : + if (first_token) { + parse_query_flush_pending_token(ctx, q); + parse_query_accept_string(ctx, q, q->cur, 1); + } else { + op->op = GRN_OP_ADJUST; + parse_query_accept_adjust(ctx, + q, + q->cur, 1, + GRN_EXPR_TOKEN_NEGATIVE, + -DEFAULT_WEIGHT); + } + q->cur++; + break; + case GRN_QUERY_PARENL : + parse_query_flush_pending_token(ctx, q); + PARSE(GRN_EXPR_TOKEN_PARENL); + q->cur++; + q->paren_depth++; + block_started = GRN_TRUE; + break; + case 'O' : + if (q->cur + 2 < q->str_end && q->cur[1] == 'R' && q->cur[2] == ' ') { + if (first_token && (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR)) { + parse_query_flush_pending_token(ctx, q); + parse_query_accept_string(ctx, q, q->cur, 2); + } else { + parse_query_accept_logical_op(ctx, + q, + q->cur, 2, + GRN_EXPR_TOKEN_LOGICAL_OR); + } + q->cur += 2; + break; + } + /* fallthru */ + default : + parse_query_word(ctx, q); + break; + } + first_token = block_started; + block_started = GRN_FALSE; + } +exit : + if (q->flags & GRN_EXPR_QUERY_NO_SYNTAX_ERROR) { + if (q->pending_token.string_length > 0) { + parse_query_accept_string(ctx, + q, + q->pending_token.string, + q->pending_token.string_length); + } else if (only_first_and) { + const char query_and[] = {GRN_QUERY_AND}; + parse_query_accept_string(ctx, + q, + query_and, + 1); + } + if (q->paren_depth > 0) { + int paren_depth = q->paren_depth; + while (paren_depth > 0) { + const char parenl = GRN_QUERY_PARENL; + parse_query_accept_string(ctx, q, &parenl, 1); + PARSE(GRN_EXPR_TOKEN_PARENR); + paren_depth--; + } + } + } + PARSE(0); + return GRN_SUCCESS; +} + +static grn_rc +get_string(grn_ctx *ctx, efs_info *q, char quote) +{ + const char *s; + unsigned int len; + grn_rc rc = GRN_END_OF_DATA; + GRN_BULK_REWIND(&q->buf); + for (s = q->cur + 1; s < q->str_end; s += len) { + if (!(len = grn_charlen(ctx, s, q->str_end))) { break; } + if (len == 1) { + if (*s == quote) { + s++; + rc = GRN_SUCCESS; + break; + } + if (*s == GRN_QUERY_ESCAPE && s + 1 < q->str_end) { + s++; + if (!(len = grn_charlen(ctx, s, q->str_end))) { break; } + } + } + GRN_TEXT_PUT(ctx, &q->buf, s, len); + } + q->cur = s; + return rc; +} + +static grn_obj * +resolve_top_level_name(grn_ctx *ctx, const char *name, unsigned int name_size) +{ + unsigned int i; + unsigned int first_delimiter_position = 0; + unsigned int n_delimiters = 0; + grn_obj *top_level_object; + grn_obj *object; + + for (i = 0; i < name_size; i++) { + if (name[i] != GRN_DB_DELIMITER) { + continue; + } + + if (n_delimiters == 0) { + first_delimiter_position = i; + } + n_delimiters++; + } + + if (n_delimiters < 2) { + return grn_ctx_get(ctx, name, name_size); + } + + top_level_object = grn_ctx_get(ctx, name, first_delimiter_position); + if (!top_level_object) { + return NULL; + } + object = grn_obj_column(ctx, top_level_object, + name + first_delimiter_position + 1, + name_size - first_delimiter_position - 1); + grn_obj_unlink(ctx, top_level_object); + return object; +} + +static grn_rc +get_identifier(grn_ctx *ctx, efs_info *q, grn_obj *name_resolve_context) +{ + const char *s; + unsigned int len; + grn_rc rc = GRN_SUCCESS; + for (s = q->cur; s < q->str_end; s += len) { + if (!(len = grn_charlen(ctx, s, q->str_end))) { + rc = GRN_END_OF_DATA; + goto exit; + } + if (grn_isspace(s, ctx->encoding)) { goto done; } + if (len == 1) { + switch (*s) { + case '\0' : case '(' : case ')' : case '{' : case '}' : + case '[' : case ']' : case ',' : case ':' : case '@' : + case '?' : case '"' : case '*' : case '+' : case '-' : + case '|' : case '/' : case '%' : case '!' : case '^' : + case '&' : case '>' : case '<' : case '=' : case '~' : + /* case '.' : */ + goto done; + break; + } + } + } +done : + len = s - q->cur; + switch (*q->cur) { + case 'd' : + if (len == 6 && !memcmp(q->cur, "delete", 6)) { + PARSE(GRN_EXPR_TOKEN_DELETE); + goto exit; + } + break; + case 'f' : + if (len == 5 && !memcmp(q->cur, "false", 5)) { + grn_obj buf; + PARSE(GRN_EXPR_TOKEN_BOOLEAN); + GRN_BOOL_INIT(&buf, 0); + GRN_BOOL_SET(ctx, &buf, 0); + grn_expr_append_const(ctx, q->e, &buf, GRN_OP_PUSH, 1); + GRN_OBJ_FIN(ctx, &buf); + goto exit; + } + break; + case 'i' : + if (len == 2 && !memcmp(q->cur, "in", 2)) { + PARSE(GRN_EXPR_TOKEN_IN); + goto exit; + } + break; + case 'n' : + if (len == 4 && !memcmp(q->cur, "null", 4)) { + grn_obj buf; + PARSE(GRN_EXPR_TOKEN_NULL); + GRN_VOID_INIT(&buf); + grn_expr_append_const(ctx, q->e, &buf, GRN_OP_PUSH, 1); + GRN_OBJ_FIN(ctx, &buf); + goto exit; + } + break; + case 't' : + if (len == 4 && !memcmp(q->cur, "true", 4)) { + grn_obj buf; + PARSE(GRN_EXPR_TOKEN_BOOLEAN); + GRN_BOOL_INIT(&buf, 0); + GRN_BOOL_SET(ctx, &buf, 1); + grn_expr_append_const(ctx, q->e, &buf, GRN_OP_PUSH, 1); + GRN_OBJ_FIN(ctx, &buf); + goto exit; + } + break; + } + { + grn_obj *obj; + const char *name = q->cur; + unsigned int name_size = s - q->cur; + if (name_resolve_context) { + if ((obj = grn_obj_column(ctx, name_resolve_context, name, name_size))) { + if (obj->header.type == GRN_ACCESSOR) { + grn_expr_take_obj(ctx, q->e, obj); + } + PARSE(GRN_EXPR_TOKEN_IDENTIFIER); + grn_expr_append_obj(ctx, q->e, obj, GRN_OP_GET_VALUE, 2); + goto exit; + } + } + if ((obj = grn_expr_get_var(ctx, q->e, name, name_size))) { + PARSE(GRN_EXPR_TOKEN_IDENTIFIER); + grn_expr_append_obj(ctx, q->e, obj, GRN_OP_PUSH, 1); + goto exit; + } + if ((obj = grn_obj_column(ctx, q->table, name, name_size))) { + if (obj->header.type == GRN_ACCESSOR) { + grn_expr_take_obj(ctx, q->e, obj); + } + PARSE(GRN_EXPR_TOKEN_IDENTIFIER); + grn_expr_append_obj(ctx, q->e, obj, GRN_OP_GET_VALUE, 1); + goto exit; + } + if ((obj = resolve_top_level_name(ctx, name, name_size))) { + if (obj->header.type == GRN_ACCESSOR) { + grn_expr_take_obj(ctx, q->e, obj); + } + PARSE(GRN_EXPR_TOKEN_IDENTIFIER); + grn_expr_append_obj(ctx, q->e, obj, GRN_OP_PUSH, 1); + goto exit; + } + if (q->flags & GRN_EXPR_SYNTAX_OUTPUT_COLUMNS) { + PARSE(GRN_EXPR_TOKEN_NONEXISTENT_COLUMN); + } else { + rc = GRN_SYNTAX_ERROR; + ERR(rc, + "[expr][parse] unknown identifier: <%.*s>", + (int)name_size, + name); + } + } +exit : + q->cur = s; + return rc; +} + +static void +set_tos_minor_to_curr(grn_ctx *ctx, efs_info *q) +{ + yyParser *parser = ctx->impl->parser; + yyStackEntry *yytos = parser->yytos; + yytos->minor.yy0 = ((grn_expr *)(q->e))->codes_curr; +} + +static grn_obj * +parse_script_extract_name_resolve_context(grn_ctx *ctx, efs_info *q) +{ + grn_expr *expr = (grn_expr *)(q->e); + grn_expr_code *code_start; + grn_expr_code *code_last; + + if (expr->codes_curr == 0) { + return NULL; + } + + code_start = expr->codes; + code_last = code_start + (expr->codes_curr - 1); + switch (code_last->op) { + case GRN_OP_GET_MEMBER : + { + unsigned int n_used_codes_for_key; + grn_expr_code *code_key; + grn_expr_code *code_receiver; + + code_key = code_last - 1; + if (code_key < code_start) { + return NULL; + } + + n_used_codes_for_key = grn_expr_code_n_used_codes(ctx, + code_start, + code_key); + if (n_used_codes_for_key == 0) { + return NULL; + } + code_receiver = code_key - n_used_codes_for_key; + if (code_receiver < code_start) { + return NULL; + } + return code_receiver->value; + } + break; + default : + /* TODO: Support other operators. */ + return NULL; + break; + } +} + +static grn_rc +parse_script(grn_ctx *ctx, efs_info *q) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *name_resolve_context = NULL; + for (;;) { + grn_obj *current_name_resolve_context = name_resolve_context; + name_resolve_context = NULL; + skip_space(ctx, q); + if (q->cur >= q->str_end) { rc = GRN_END_OF_DATA; goto exit; } + switch (*q->cur) { + case '\0' : + rc = GRN_END_OF_DATA; + goto exit; + break; + case '(' : + PARSE(GRN_EXPR_TOKEN_PARENL); + q->cur++; + break; + case ')' : + PARSE(GRN_EXPR_TOKEN_PARENR); + q->cur++; + break; + case '{' : + PARSE(GRN_EXPR_TOKEN_BRACEL); + q->cur++; + break; + case '}' : + PARSE(GRN_EXPR_TOKEN_BRACER); + q->cur++; + break; + case '[' : + PARSE(GRN_EXPR_TOKEN_BRACKETL); + q->cur++; + break; + case ']' : + PARSE(GRN_EXPR_TOKEN_BRACKETR); + q->cur++; + break; + case ',' : + PARSE(GRN_EXPR_TOKEN_COMMA); + q->cur++; + break; + case '.' : + PARSE(GRN_EXPR_TOKEN_DOT); + name_resolve_context = parse_script_extract_name_resolve_context(ctx, q); + q->cur++; + break; + case ':' : + PARSE(GRN_EXPR_TOKEN_COLON); + q->cur++; + set_tos_minor_to_curr(ctx, q); + grn_expr_append_op(ctx, q->e, GRN_OP_JUMP, 0); + break; + case '@' : + switch (q->cur[1]) { + case '^' : + PARSE(GRN_EXPR_TOKEN_PREFIX); + q->cur += 2; + break; + case '$' : + PARSE(GRN_EXPR_TOKEN_SUFFIX); + q->cur += 2; + break; + case '~' : + PARSE(GRN_EXPR_TOKEN_REGEXP); + q->cur += 2; + break; + default : + PARSE(GRN_EXPR_TOKEN_MATCH); + q->cur++; + break; + } + break; + case '~' : + PARSE(GRN_EXPR_TOKEN_BITWISE_NOT); + q->cur++; + break; + case '?' : + PARSE(GRN_EXPR_TOKEN_QUESTION); + q->cur++; + set_tos_minor_to_curr(ctx, q); + grn_expr_append_op(ctx, q->e, GRN_OP_CJUMP, 0); + break; + case '"' : + if ((rc = get_string(ctx, q, '"'))) { goto exit; } + PARSE(GRN_EXPR_TOKEN_STRING); + grn_expr_append_const(ctx, q->e, &q->buf, GRN_OP_PUSH, 1); + break; + case '\'' : + if ((rc = get_string(ctx, q, '\''))) { goto exit; } + PARSE(GRN_EXPR_TOKEN_STRING); + grn_expr_append_const(ctx, q->e, &q->buf, GRN_OP_PUSH, 1); + break; + case '*' : + switch (q->cur[1]) { + case 'N' : + { + const char *next_start = q->cur + 2; + const char *end; + int max_interval; + max_interval = grn_atoi(next_start, q->str_end, &end); + if (end == next_start) { + max_interval = DEFAULT_MAX_INTERVAL; + } else { + next_start = end; + } + GRN_INT32_PUT(ctx, &q->max_interval_stack, max_interval); + PARSE(GRN_EXPR_TOKEN_NEAR); + q->cur = next_start; + } + break; + case 'S' : + PARSE(GRN_EXPR_TOKEN_SIMILAR); + q->cur += 2; + break; + case 'T' : + PARSE(GRN_EXPR_TOKEN_TERM_EXTRACT); + q->cur += 2; + break; + case '>' : + PARSE(GRN_EXPR_TOKEN_ADJUST); + q->cur += 2; + break; + case '<' : + PARSE(GRN_EXPR_TOKEN_ADJUST); + q->cur += 2; + break; + case '~' : + PARSE(GRN_EXPR_TOKEN_ADJUST); + q->cur += 2; + break; + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_STAR_ASSIGN); + q->cur += 2; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'*=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_STAR); + q->cur++; + break; + } + break; + case '+' : + switch (q->cur[1]) { + case '+' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_INCR); + q->cur += 2; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'++' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_PLUS_ASSIGN); + q->cur += 2; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'+=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_PLUS); + q->cur++; + break; + } + break; + case '-' : + switch (q->cur[1]) { + case '-' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_DECR); + q->cur += 2; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'--' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_MINUS_ASSIGN); + q->cur += 2; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'-=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_MINUS); + q->cur++; + break; + } + break; + case '|' : + switch (q->cur[1]) { + case '|' : + PARSE(GRN_EXPR_TOKEN_LOGICAL_OR); + q->cur += 2; + break; + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_OR_ASSIGN); + q->cur += 2; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'|=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_BITWISE_OR); + q->cur++; + break; + } + break; + case '/' : + switch (q->cur[1]) { + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_SLASH_ASSIGN); + q->cur += 2; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'/=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_SLASH); + q->cur++; + break; + } + break; + case '%' : + switch (q->cur[1]) { + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_MOD_ASSIGN); + q->cur += 2; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'%%=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_MOD); + q->cur++; + break; + } + break; + case '!' : + switch (q->cur[1]) { + case '=' : + PARSE(GRN_EXPR_TOKEN_NOT_EQUAL); + q->cur += 2; + break; + default : + PARSE(GRN_EXPR_TOKEN_NOT); + q->cur++; + break; + } + break; + case '^' : + switch (q->cur[1]) { + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + q->cur += 2; + PARSE(GRN_EXPR_TOKEN_XOR_ASSIGN); + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'^=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_BITWISE_XOR); + q->cur++; + break; + } + break; + case '&' : + switch (q->cur[1]) { + case '&' : + PARSE(GRN_EXPR_TOKEN_LOGICAL_AND); + q->cur += 2; + break; + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_AND_ASSIGN); + q->cur += 2; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'&=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + case '!' : + PARSE(GRN_EXPR_TOKEN_LOGICAL_AND_NOT); + q->cur += 2; + break; + default : + PARSE(GRN_EXPR_TOKEN_BITWISE_AND); + q->cur++; + break; + } + break; + case '>' : + switch (q->cur[1]) { + case '>' : + switch (q->cur[2]) { + case '>' : + switch (q->cur[3]) { + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_SHIFTRR_ASSIGN); + q->cur += 4; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'>>>=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_SHIFTRR); + q->cur += 3; + break; + } + break; + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_SHIFTR_ASSIGN); + q->cur += 3; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'>>=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_SHIFTR); + q->cur += 2; + break; + } + break; + case '=' : + PARSE(GRN_EXPR_TOKEN_GREATER_EQUAL); + q->cur += 2; + break; + default : + PARSE(GRN_EXPR_TOKEN_GREATER); + q->cur++; + break; + } + break; + case '<' : + switch (q->cur[1]) { + case '<' : + switch (q->cur[2]) { + case '=' : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_SHIFTL_ASSIGN); + q->cur += 3; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'<<=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + default : + PARSE(GRN_EXPR_TOKEN_SHIFTL); + q->cur += 2; + break; + } + break; + case '=' : + PARSE(GRN_EXPR_TOKEN_LESS_EQUAL); + q->cur += 2; + break; + default : + PARSE(GRN_EXPR_TOKEN_LESS); + q->cur++; + break; + } + break; + case '=' : + switch (q->cur[1]) { + case '=' : + PARSE(GRN_EXPR_TOKEN_EQUAL); + q->cur += 2; + break; + default : + if (q->flags & GRN_EXPR_ALLOW_UPDATE) { + PARSE(GRN_EXPR_TOKEN_ASSIGN); + q->cur++; + } else { + ERR(GRN_UPDATE_NOT_ALLOWED, + "'=' is not allowed: <%.*s>", (int)(q->str_end - q->str), q->str); + } + break; + } + break; + case '0' : case '1' : case '2' : case '3' : case '4' : + case '5' : case '6' : case '7' : case '8' : case '9' : + { + const char *rest; + int64_t int64 = grn_atoll(q->cur, q->str_end, &rest); + // checks to see grn_atoll was appropriate + // (NOTE: *q->cur begins with a digit. Thus, grn_atoll parses at least + // one char.) + if (q->str_end != rest && + (*rest == '.' || *rest == 'e' || *rest == 'E' || + (*rest >= '0' && *rest <= '9'))) { + char *rest_float; + double d = strtod(q->cur, &rest_float); + grn_obj floatbuf; + GRN_FLOAT_INIT(&floatbuf, 0); + GRN_FLOAT_SET(ctx, &floatbuf, d); + grn_expr_append_const(ctx, q->e, &floatbuf, GRN_OP_PUSH, 1); + rest = rest_float; + } else { + const char *rest64 = rest; + grn_atoui(q->cur, q->str_end, &rest); + // checks to see grn_atoi failed (see above NOTE) + if ((int64 > UINT32_MAX) || + (q->str_end != rest && *rest >= '0' && *rest <= '9')) { + grn_obj int64buf; + GRN_INT64_INIT(&int64buf, 0); + GRN_INT64_SET(ctx, &int64buf, int64); + grn_expr_append_const(ctx, q->e, &int64buf, GRN_OP_PUSH, 1); + rest = rest64; + } else if (int64 > INT32_MAX || int64 < INT32_MIN) { + grn_obj int64buf; + GRN_INT64_INIT(&int64buf, 0); + GRN_INT64_SET(ctx, &int64buf, int64); + grn_expr_append_const(ctx, q->e, &int64buf, GRN_OP_PUSH, 1); + } else { + grn_obj int32buf; + GRN_INT32_INIT(&int32buf, 0); + GRN_INT32_SET(ctx, &int32buf, (int32_t)int64); + grn_expr_append_const(ctx, q->e, &int32buf, GRN_OP_PUSH, 1); + } + } + PARSE(GRN_EXPR_TOKEN_DECIMAL); + q->cur = rest; + } + break; + default : + if ((rc = get_identifier(ctx, q, current_name_resolve_context))) { + goto exit; + } + break; + } + if (ctx->rc) { rc = ctx->rc; break; } + } +exit : + PARSE(0); + return rc; +} + +grn_rc +grn_expr_parse(grn_ctx *ctx, grn_obj *expr, + const char *str, unsigned int str_size, + grn_obj *default_column, grn_operator default_mode, + grn_operator default_op, grn_expr_flags flags) +{ + efs_info efsi; + if (grn_expr_parser_open(ctx)) { return ctx->rc; } + GRN_API_ENTER; + efsi.ctx = ctx; + efsi.str = str; + if ((efsi.v = grn_expr_get_var_by_offset(ctx, expr, 0)) && + (efsi.table = grn_ctx_at(ctx, efsi.v->header.domain))) { + GRN_TEXT_INIT(&efsi.buf, 0); + GRN_INT32_INIT(&efsi.op_stack, GRN_OBJ_VECTOR); + GRN_INT32_INIT(&efsi.mode_stack, GRN_OBJ_VECTOR); + GRN_INT32_INIT(&efsi.max_interval_stack, GRN_OBJ_VECTOR); + GRN_INT32_INIT(&efsi.similarity_threshold_stack, GRN_OBJ_VECTOR); + GRN_INT32_INIT(&efsi.weight_stack, GRN_OBJ_VECTOR); + GRN_PTR_INIT(&efsi.column_stack, GRN_OBJ_VECTOR, GRN_ID_NIL); + GRN_PTR_INIT(&efsi.token_stack, GRN_OBJ_VECTOR, GRN_ID_NIL); + efsi.e = expr; + efsi.str = str; + efsi.cur = str; + efsi.str_end = str + str_size; + efsi.default_column = default_column; + GRN_PTR_PUT(ctx, &efsi.column_stack, default_column); + GRN_INT32_PUT(ctx, &efsi.op_stack, default_op); + GRN_INT32_PUT(ctx, &efsi.mode_stack, default_mode); + GRN_INT32_PUT(ctx, &efsi.weight_stack, 0); + efsi.default_flags = efsi.flags = flags; + efsi.escalation_threshold = GRN_DEFAULT_MATCH_ESCALATION_THRESHOLD; + efsi.escalation_decaystep = DEFAULT_DECAYSTEP; + efsi.weight_offset = 0; + memset(&(efsi.opt), 0, sizeof(grn_select_optarg)); + efsi.opt.weight_vector = NULL; + efsi.weight_set = NULL; + efsi.object_literal = NULL; + efsi.paren_depth = 0; + efsi.pending_token.string = NULL; + efsi.pending_token.string_length = 0; + efsi.pending_token.token = 0; + + if (flags & (GRN_EXPR_SYNTAX_SCRIPT | + GRN_EXPR_SYNTAX_OUTPUT_COLUMNS | + GRN_EXPR_SYNTAX_ADJUSTER)) { + efs_info *q = &efsi; + if (flags & GRN_EXPR_SYNTAX_OUTPUT_COLUMNS) { + PARSE(GRN_EXPR_TOKEN_START_OUTPUT_COLUMNS); + } else if (flags & GRN_EXPR_SYNTAX_ADJUSTER) { + PARSE(GRN_EXPR_TOKEN_START_ADJUSTER); + } + parse_script(ctx, &efsi); + } else { + parse_query(ctx, &efsi); + } + + /* + grn_obj strbuf; + GRN_TEXT_INIT(&strbuf, 0); + grn_expr_inspect_internal(ctx, &strbuf, expr); + GRN_TEXT_PUTC(ctx, &strbuf, '\0'); + GRN_LOG(ctx, GRN_LOG_NOTICE, "query=(%s)", GRN_TEXT_VALUE(&strbuf)); + GRN_OBJ_FIN(ctx, &strbuf); + */ + + /* + efsi.opt.vector_size = DEFAULT_WEIGHT_VECTOR_SIZE; + efsi.opt.func = efsi.weight_set ? section_weight_cb : NULL; + efsi.opt.func_arg = efsi.weight_set; + efsi.snip_conds = NULL; + */ + GRN_OBJ_FIN(ctx, &efsi.op_stack); + GRN_OBJ_FIN(ctx, &efsi.mode_stack); + GRN_OBJ_FIN(ctx, &efsi.max_interval_stack); + GRN_OBJ_FIN(ctx, &efsi.similarity_threshold_stack); + GRN_OBJ_FIN(ctx, &efsi.weight_stack); + GRN_OBJ_FIN(ctx, &efsi.column_stack); + GRN_OBJ_FIN(ctx, &efsi.token_stack); + GRN_OBJ_FIN(ctx, &efsi.buf); + if (efsi.object_literal) { + grn_obj *value; + GRN_HASH_EACH(ctx, efsi.object_literal, i, NULL, NULL, (void **)&value, { + GRN_OBJ_FIN(ctx, value); + }); + grn_hash_close(ctx, efsi.object_literal); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "variable is not defined correctly"); + } + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_expr_parser_close(grn_ctx *ctx) +{ + if (ctx->impl->parser) { + yyParser *parser = (yyParser *)ctx->impl->parser; + ctx->impl->parser = NULL; + grn_expr_parserFree(parser, free); + } + return ctx->rc; +} + +typedef grn_rc (*grn_expr_syntax_expand_term_func)(grn_ctx *ctx, + const char *term, + unsigned int term_len, + grn_obj *substituted_term, + grn_user_data *user_data); +static grn_rc +grn_expr_syntax_expand_term_by_func(grn_ctx *ctx, + const char *term, unsigned int term_len, + grn_obj *expanded_term, + grn_user_data *user_data) +{ + grn_rc rc; + grn_obj *expander = user_data->ptr; + grn_obj grn_term; + grn_obj *caller; + grn_obj *rc_object; + int nargs = 0; + + GRN_TEXT_INIT(&grn_term, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET(ctx, &grn_term, term, term_len); + grn_ctx_push(ctx, &grn_term); + nargs++; + grn_ctx_push(ctx, expanded_term); + nargs++; + + caller = grn_expr_create(ctx, NULL, 0); + rc = grn_proc_call(ctx, expander, nargs, caller); + GRN_OBJ_FIN(ctx, &grn_term); + rc_object = grn_ctx_pop(ctx); + rc = GRN_INT32_VALUE(rc_object); + grn_obj_unlink(ctx, caller); + + return rc; +} + +typedef struct { + grn_obj *table; + grn_obj *column; +} grn_expr_syntax_expand_term_by_column_data; + +static grn_rc +grn_expr_syntax_expand_term_by_column(grn_ctx *ctx, + const char *term, unsigned int term_len, + grn_obj *expanded_term, + grn_user_data *user_data) +{ + grn_rc rc = GRN_END_OF_DATA; + grn_id id; + grn_expr_syntax_expand_term_by_column_data *data = user_data->ptr; + grn_obj *table, *column; + + table = data->table; + column = data->column; + if ((id = grn_table_get(ctx, table, term, term_len))) { + if ((column->header.type == GRN_COLUMN_VAR_SIZE) && + ((column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR)) { + unsigned int i, n; + grn_obj values; + GRN_TEXT_INIT(&values, GRN_OBJ_VECTOR); + grn_obj_get_value(ctx, column, id, &values); + n = grn_vector_size(ctx, &values); + if (n > 1) { GRN_TEXT_PUTC(ctx, expanded_term, '('); } + for (i = 0; i < n; i++) { + const char *value; + unsigned int length; + if (i > 0) { + GRN_TEXT_PUTS(ctx, expanded_term, " OR "); + } + if (n > 1) { GRN_TEXT_PUTC(ctx, expanded_term, '('); } + length = grn_vector_get_element(ctx, &values, i, &value, NULL, NULL); + GRN_TEXT_PUT(ctx, expanded_term, value, length); + if (n > 1) { GRN_TEXT_PUTC(ctx, expanded_term, ')'); } + } + if (n > 1) { GRN_TEXT_PUTC(ctx, expanded_term, ')'); } + GRN_OBJ_FIN(ctx, &values); + } else { + grn_obj_get_value(ctx, column, id, expanded_term); + } + rc = GRN_SUCCESS; + } + return rc; +} + +typedef struct { + grn_obj *table; + grn_obj *term_column; + grn_obj *expanded_term_column; +} grn_expr_syntax_expand_term_by_table_data; + +static grn_rc +grn_expr_syntax_expand_term_by_table(grn_ctx *ctx, + const char *term, unsigned int term_len, + grn_obj *expanded_term, + grn_user_data *user_data) +{ + grn_rc rc = GRN_END_OF_DATA; + grn_expr_syntax_expand_term_by_table_data *data = user_data->ptr; + grn_obj *table; + grn_obj *term_column; + grn_obj *expanded_term_column; + grn_obj *expression; + grn_obj *variable; + grn_obj *found_terms; + int n_terms; + + table = data->table; + term_column = data->term_column; + expanded_term_column = data->expanded_term_column; + + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expression, variable); + if (ctx->rc != GRN_SUCCESS) { + ERR(ctx->rc, + "[query][expand][table] " + "failed to create expression: <%s>", + ctx->errbuf); + return ctx->rc; + } + grn_expr_append_const(ctx, expression, term_column, GRN_OP_GET_VALUE, 1); + grn_expr_append_const_str(ctx, expression, term, term_len, GRN_OP_PUSH, 1); + grn_expr_append_op(ctx, expression, GRN_OP_EQUAL, 2); + if (ctx->rc != GRN_SUCCESS) { + grn_obj_close(ctx, expression); + ERR(ctx->rc, + "[query][expand][table] " + "failed to build expression: <%s>", + ctx->errbuf); + return ctx->rc; + } + + found_terms = grn_table_select(ctx, table, expression, NULL, GRN_OP_OR); + grn_obj_close(ctx, expression); + if (!found_terms) { + ERR(ctx->rc, + "[query][expand][table] " + "failed to find term: <%.*s>: <%s>", + (int)term_len, + term, + ctx->errbuf); + return ctx->rc; + } + + n_terms = grn_table_size(ctx, found_terms); + if (n_terms == 0) { + grn_obj_close(ctx, found_terms); + return rc; + } + + { + int nth_term; + + GRN_TEXT_PUTC(ctx, expanded_term, '('); + nth_term = 0; + GRN_TABLE_EACH_BEGIN(ctx, found_terms, cursor, id) { + void *key; + grn_id record_id; + + grn_table_cursor_get_key(ctx, cursor, &key); + record_id = *((grn_id *)key); + if (grn_obj_is_vector_column(ctx, expanded_term_column)) { + unsigned int j, n_values; + grn_obj values; + GRN_TEXT_INIT(&values, GRN_OBJ_VECTOR); + grn_obj_get_value(ctx, expanded_term_column, record_id, &values); + n_values = grn_vector_size(ctx, &values); + n_terms += n_values - 1; + for (j = 0; j < n_values; j++) { + const char *value; + unsigned int length; + if (nth_term > 0) { + GRN_TEXT_PUTS(ctx, expanded_term, " OR "); + } + if (n_terms > 1) { + GRN_TEXT_PUTC(ctx, expanded_term, '('); + } + length = grn_vector_get_element(ctx, &values, j, &value, NULL, NULL); + GRN_TEXT_PUT(ctx, expanded_term, value, length); + if (n_terms > 1) { + GRN_TEXT_PUTC(ctx, expanded_term, ')'); + } + nth_term++; + } + GRN_OBJ_FIN(ctx, &values); + } else { + if (nth_term > 0) { + GRN_TEXT_PUTS(ctx, expanded_term, " OR "); + } + if (n_terms > 1) { GRN_TEXT_PUTC(ctx, expanded_term, '('); } + grn_obj_get_value(ctx, expanded_term_column, record_id, expanded_term); + if (n_terms > 1) { GRN_TEXT_PUTC(ctx, expanded_term, ')'); } + nth_term++; + } + } GRN_TABLE_EACH_END(ctx, cursor); + GRN_TEXT_PUTC(ctx, expanded_term, ')'); + } + rc = GRN_SUCCESS; + grn_obj_close(ctx, found_terms); + + return rc; +} + +static grn_rc +grn_expr_syntax_expand_query_terms(grn_ctx *ctx, + const char *query, unsigned int query_size, + grn_expr_flags flags, + grn_obj *expanded_query, + grn_expr_syntax_expand_term_func expand_term_func, + grn_user_data *user_data) +{ + grn_obj buf; + unsigned int len; + const char *start, *cur = query, *query_end = query + (size_t)query_size; + GRN_TEXT_INIT(&buf, 0); + for (;;) { + while (cur < query_end && grn_isspace(cur, ctx->encoding)) { + if (!(len = grn_charlen(ctx, cur, query_end))) { goto exit; } + GRN_TEXT_PUT(ctx, expanded_query, cur, len); + cur += len; + } + if (query_end <= cur) { break; } + switch (*cur) { + case '\0' : + goto exit; + break; + case GRN_QUERY_AND : + case GRN_QUERY_ADJ_INC : + case GRN_QUERY_ADJ_DEC : + case GRN_QUERY_ADJ_NEG : + case GRN_QUERY_AND_NOT : + case GRN_QUERY_PARENL : + case GRN_QUERY_PARENR : + case GRN_QUERY_PREFIX : + GRN_TEXT_PUTC(ctx, expanded_query, *cur); + cur++; + break; + case GRN_QUERY_QUOTEL : + GRN_BULK_REWIND(&buf); + for (start = cur++; cur < query_end; cur += len) { + if (!(len = grn_charlen(ctx, cur, query_end))) { + goto exit; + } else if (len == 1) { + if (*cur == GRN_QUERY_QUOTER) { + cur++; + break; + } else if (cur + 1 < query_end && *cur == GRN_QUERY_ESCAPE) { + cur++; + len = grn_charlen(ctx, cur, query_end); + } + } + GRN_TEXT_PUT(ctx, &buf, cur, len); + } + if (expand_term_func(ctx, GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf), + expanded_query, user_data)) { + GRN_TEXT_PUT(ctx, expanded_query, start, cur - start); + } + break; + case 'O' : + if (cur + 2 <= query_end && cur[1] == 'R' && + (cur + 2 == query_end || grn_isspace(cur + 2, ctx->encoding))) { + GRN_TEXT_PUT(ctx, expanded_query, cur, 2); + cur += 2; + break; + } + /* fallthru */ + default : + for (start = cur; cur < query_end; cur += len) { + if (!(len = grn_charlen(ctx, cur, query_end))) { + goto exit; + } else if (grn_isspace(cur, ctx->encoding)) { + break; + } else if (len == 1) { + if (*cur == GRN_QUERY_PARENL || + *cur == GRN_QUERY_PARENR || + *cur == GRN_QUERY_PREFIX) { + break; + } else if (flags & GRN_EXPR_ALLOW_COLUMN && *cur == GRN_QUERY_COLUMN) { + if (cur + 1 < query_end) { + switch (cur[1]) { + case '!' : + case '@' : + case '^' : + case '$' : + cur += 2; + break; + case '=' : + cur += (flags & GRN_EXPR_ALLOW_UPDATE) ? 2 : 1; + break; + case '<' : + case '>' : + cur += (cur + 2 < query_end && cur[2] == '=') ? 3 : 2; + break; + default : + cur += 1; + break; + } + } else { + cur += 1; + } + GRN_TEXT_PUT(ctx, expanded_query, start, cur - start); + start = cur; + break; + } + } + } + if (start < cur) { + if (expand_term_func(ctx, start, cur - start, + expanded_query, user_data)) { + GRN_TEXT_PUT(ctx, expanded_query, start, cur - start); + } + } + break; + } + } +exit : + GRN_OBJ_FIN(ctx, &buf); + return GRN_SUCCESS; +} + +grn_rc +grn_expr_syntax_expand_query(grn_ctx *ctx, + const char *query, int query_size, + grn_expr_flags flags, + grn_obj *expander, + grn_obj *expanded_query) +{ + GRN_API_ENTER; + + if (query_size < 0) { + query_size = strlen(query); + } + + switch (expander->header.type) { + case GRN_PROC : + if (((grn_proc *)expander)->type == GRN_PROC_FUNCTION) { + grn_user_data user_data; + user_data.ptr = expander; + grn_expr_syntax_expand_query_terms(ctx, + query, query_size, + flags, + expanded_query, + grn_expr_syntax_expand_term_by_func, + &user_data); + } else { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_obj_name(ctx, expander, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[query][expand][proc] " + "proc query expander must be a function proc: <%.*s>", + name_size, name); + } + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + { + grn_obj *expansion_table; + expansion_table = grn_column_table(ctx, expander); + if (expansion_table) { + grn_user_data user_data; + grn_expr_syntax_expand_term_by_column_data data; + user_data.ptr = &data; + data.table = expansion_table; + data.column = expander; + grn_expr_syntax_expand_query_terms(ctx, + query, query_size, + flags, + expanded_query, + grn_expr_syntax_expand_term_by_column, + &user_data); + } else { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_obj_name(ctx, expander, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[query][expand][column] " + "failed to get table of query expansion column: <%.*s>", + name_size, name); + } + } + break; + default : + { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + grn_obj type_name; + + name_size = grn_obj_name(ctx, expander, name, GRN_TABLE_MAX_KEY_SIZE); + GRN_TEXT_INIT(&type_name, 0); + grn_inspect_type(ctx, &type_name, expander->header.type); + ERR(GRN_INVALID_ARGUMENT, + "[query][expand] " + "query expander must be a data column or function proc: <%.*s>(%.*s)", + name_size, name, + (int)GRN_TEXT_LEN(&type_name), GRN_TEXT_VALUE(&type_name)); + GRN_OBJ_FIN(ctx, &type_name); + } + break; + } + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_expr_syntax_expand_query_by_table(grn_ctx *ctx, + const char *query, int query_size, + grn_expr_flags flags, + grn_obj *term_column, + grn_obj *expanded_term_column, + grn_obj *expanded_query) +{ + grn_obj *table; + grn_bool term_column_is_key; + + GRN_API_ENTER; + + if (query_size < 0) { + query_size = strlen(query); + } + + if (!grn_obj_is_data_column(ctx, expanded_term_column)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, expanded_term_column); + ERR(GRN_INVALID_ARGUMENT, + "[query][expand][table] " + "expanded term column must be a data column: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + GRN_API_RETURN(ctx->rc); + } + table = grn_column_table(ctx, expanded_term_column); + + if (!term_column) { + term_column_is_key = GRN_TRUE; + } else { + if (grn_obj_is_key_accessor(ctx, term_column)) { + term_column_is_key = GRN_TRUE; + } else if (grn_obj_is_data_column(ctx, term_column)) { + term_column_is_key = GRN_FALSE; + } else { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, term_column); + ERR(GRN_INVALID_ARGUMENT, + "[query][expand][table] " + "term column must be NULL, _key or a data column: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + GRN_API_RETURN(ctx->rc); + } + if (term_column->header.domain != expanded_term_column->header.domain) { + grn_obj inspected_term_column; + grn_obj inspected_expanded_term_column; + GRN_TEXT_INIT(&inspected_term_column, 0); + GRN_TEXT_INIT(&inspected_expanded_term_column, 0); + grn_inspect(ctx, &inspected_term_column, term_column); + grn_inspect(ctx, &inspected_expanded_term_column, expanded_term_column); + ERR(GRN_INVALID_ARGUMENT, + "[query][expand][table] " + "term column and expanded term column must belong to the same table: " + "term column: <%.*s>, " + "expanded term column: <%*.s>", + (int)GRN_TEXT_LEN(&inspected_term_column), + GRN_TEXT_VALUE(&inspected_term_column), + (int)GRN_TEXT_LEN(&inspected_expanded_term_column), + GRN_TEXT_VALUE(&inspected_expanded_term_column)); + GRN_OBJ_FIN(ctx, &inspected_term_column); + GRN_OBJ_FIN(ctx, &inspected_expanded_term_column); + GRN_API_RETURN(ctx->rc); + } + } + + if (term_column_is_key) { + grn_user_data user_data; + grn_expr_syntax_expand_term_by_column_data data; + user_data.ptr = &data; + data.table = table; + data.column = expanded_term_column; + grn_expr_syntax_expand_query_terms(ctx, + query, query_size, + flags, + expanded_query, + grn_expr_syntax_expand_term_by_column, + &user_data); + } else { + grn_user_data user_data; + grn_expr_syntax_expand_term_by_table_data data; + user_data.ptr = &data; + data.table = table; + data.term_column = term_column; + data.expanded_term_column = expanded_term_column; + grn_expr_syntax_expand_query_terms(ctx, + query, query_size, + flags, + expanded_query, + grn_expr_syntax_expand_term_by_table, + &user_data); + } + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_expr_get_keywords(grn_ctx *ctx, grn_obj *expr, grn_obj *keywords) +{ + int i, n; + scan_info **sis, *si; + GRN_API_ENTER; + if ((sis = grn_scan_info_build(ctx, expr, &n, GRN_OP_OR, GRN_FALSE))) { + int butp = 0, nparens = 0, npbut = 0; + grn_obj but_stack; + GRN_UINT32_INIT(&but_stack, GRN_OBJ_VECTOR); + for (i = n; i--;) { + si = sis[i]; + if (si->flags & SCAN_POP) { + nparens++; + if (si->logical_op == GRN_OP_AND_NOT) { + GRN_UINT32_PUT(ctx, &but_stack, npbut); + npbut = nparens; + butp = 1 - butp; + } + } else { + if (butp == (si->logical_op == GRN_OP_AND_NOT) && + si->query) { + switch (si->op) { + case GRN_OP_MATCH : + if (keywords->header.type == GRN_PVECTOR) { + GRN_PTR_PUT(ctx, keywords, si->query); + } else { + grn_vector_add_element(ctx, + keywords, + GRN_TEXT_VALUE(si->query), + GRN_TEXT_LEN(si->query), + 0, + GRN_DB_TEXT); + } + break; + case GRN_OP_SIMILAR : + if (keywords->header.type == GRN_VECTOR && + GRN_BULK_VSIZE(&(si->index)) > 0) { + grn_token_cursor *token_cursor; + unsigned int token_flags = 0; + grn_obj *index = GRN_PTR_VALUE(&(si->index)); + grn_obj *lexicon; + + lexicon = grn_ctx_at(ctx, index->header.domain); + token_cursor = grn_token_cursor_open(ctx, + lexicon, + GRN_TEXT_VALUE(si->query), + GRN_TEXT_LEN(si->query), + GRN_TOKENIZE_GET, + token_flags); + if (token_cursor) { + grn_obj *source_table; + uint32_t n_records_threshold; + source_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, index)); + n_records_threshold = grn_table_size(ctx, source_table) / 2; + while (token_cursor->status != GRN_TOKEN_CURSOR_DONE) { + grn_id token_id; + uint32_t n_estimated_records; + token_id = grn_token_cursor_next(ctx, token_cursor); + if (token_id == GRN_ID_NIL) { + continue; + } + n_estimated_records = + grn_ii_estimate_size(ctx, (grn_ii *)index, token_id); + if (n_estimated_records >= n_records_threshold) { + continue; + } + grn_vector_add_element(ctx, + keywords, + token_cursor->curr, + token_cursor->curr_size, + 0, + GRN_DB_TEXT); + } + grn_token_cursor_close(ctx, token_cursor); + } + } + break; + default : + break; + } + } + if (si->flags & SCAN_PUSH) { + if (nparens == npbut) { + butp = 1 - butp; + GRN_UINT32_POP(&but_stack, npbut); + } + nparens--; + } + } + } + GRN_OBJ_FIN(ctx, &but_stack); + for (i = n; i--;) { SI_FREE(sis[i]); } + GRN_FREE(sis); + } + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_rc +grn_expr_snip_add_conditions(grn_ctx *ctx, grn_obj *expr, grn_obj *snip, + unsigned int n_tags, + const char **opentags, unsigned int *opentag_lens, + const char **closetags, unsigned int *closetag_lens) +{ + grn_rc rc; + grn_obj keywords; + + GRN_API_ENTER; + + GRN_PTR_INIT(&keywords, GRN_OBJ_VECTOR, GRN_ID_NIL); + rc = grn_expr_get_keywords(ctx, expr, &keywords); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FIN(ctx, &keywords); + GRN_API_RETURN(rc); + } + + if (n_tags) { + int i; + for (i = 0;; i = (i + 1) % n_tags) { + grn_obj *keyword; + GRN_PTR_POP(&keywords, keyword); + if (!keyword) { break; } + grn_snip_add_cond(ctx, snip, + GRN_TEXT_VALUE(keyword), GRN_TEXT_LEN(keyword), + opentags[i], opentag_lens[i], + closetags[i], closetag_lens[i]); + } + } else { + for (;;) { + grn_obj *keyword; + GRN_PTR_POP(&keywords, keyword); + if (!keyword) { break; } + grn_snip_add_cond(ctx, snip, + GRN_TEXT_VALUE(keyword), GRN_TEXT_LEN(keyword), + NULL, 0, NULL, 0); + } + } + GRN_OBJ_FIN(ctx, &keywords); + + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_obj * +grn_expr_snip(grn_ctx *ctx, grn_obj *expr, int flags, + unsigned int width, unsigned int max_results, + unsigned int n_tags, + const char **opentags, unsigned int *opentag_lens, + const char **closetags, unsigned int *closetag_lens, + grn_snip_mapping *mapping) +{ + grn_obj *res = NULL; + GRN_API_ENTER; + if ((res = grn_snip_open(ctx, flags, width, max_results, + NULL, 0, NULL, 0, mapping))) { + grn_expr_snip_add_conditions(ctx, expr, res, + n_tags, + opentags, opentag_lens, + closetags, closetag_lens); + } + GRN_API_RETURN(res); +} + +/* + So far, grn_column_filter() is nothing but a very rough prototype. + Although GRN_COLUMN_EACH() can accelerate many range queries, + the following stuff must be resolved one by one. + + * support accessors as column + * support tables which have deleted records + * support various operators + * support various column types +*/ +grn_rc +grn_column_filter(grn_ctx *ctx, grn_obj *column, + grn_operator operator, + grn_obj *value, grn_obj *result_set, + grn_operator set_operation) +{ + uint32_t *vp; + grn_posting posting; + uint32_t value_ = grn_atoui(GRN_TEXT_VALUE(value), GRN_BULK_CURR(value), NULL); + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + GRN_COLUMN_EACH(ctx, column, id, vp, { + if (*vp < value_) { + posting.rid = id; + grn_ii_posting_add(ctx, &posting, (grn_hash *)result_set, set_operation); + } + }); + grn_ii_resolve_sel_and(ctx, (grn_hash *)result_set, set_operation); + return ctx->rc; +} + +grn_rc +grn_expr_syntax_escape(grn_ctx *ctx, const char *string, int string_size, + const char *target_characters, + char escape_character, + grn_obj *escaped_string) +{ + grn_rc rc = GRN_SUCCESS; + const char *current, *string_end; + + if (!string) { + return GRN_INVALID_ARGUMENT; + } + + GRN_API_ENTER; + if (string_size < 0) { + string_size = strlen(string); + } + string_end = string + string_size; + + current = string; + while (current < string_end) { + unsigned int char_size; + char_size = grn_charlen(ctx, current, string_end); + switch (char_size) { + case 0 : + /* string includes malformed multibyte character. */ + return GRN_INVALID_ARGUMENT; + break; + case 1 : + if (strchr(target_characters, *current)) { + GRN_TEXT_PUTC(ctx, escaped_string, escape_character); + } + GRN_TEXT_PUT(ctx, escaped_string, current, char_size); + current += char_size; + break; + default : + GRN_TEXT_PUT(ctx, escaped_string, current, char_size); + current += char_size; + break; + } + } + + GRN_API_RETURN(rc); +} + +grn_rc +grn_expr_syntax_escape_query(grn_ctx *ctx, const char *query, int query_size, + grn_obj *escaped_query) +{ + const char target_characters[] = { + GRN_QUERY_AND, + GRN_QUERY_AND_NOT, + GRN_QUERY_ADJ_INC, + GRN_QUERY_ADJ_DEC, + GRN_QUERY_ADJ_NEG, + GRN_QUERY_PREFIX, + GRN_QUERY_PARENL, + GRN_QUERY_PARENR, + GRN_QUERY_QUOTEL, + GRN_QUERY_ESCAPE, + GRN_QUERY_COLUMN, + '\0', + }; + return grn_expr_syntax_escape(ctx, query, query_size, + target_characters, GRN_QUERY_ESCAPE, + escaped_query); +} + +grn_rc +grn_expr_dump_plan(grn_ctx *ctx, grn_obj *expr, grn_obj *buffer) +{ + int n; + scan_info **sis; + + GRN_API_ENTER; + sis = grn_scan_info_build(ctx, expr, &n, GRN_OP_OR, GRN_FALSE); + if (sis) { + int i; + grn_inspect_scan_info_list(ctx, buffer, sis, n); + for (i = 0; i < n; i++) { + SI_FREE(sis[i]); + } + GRN_FREE(sis); + } else { + GRN_TEXT_PUTS(ctx, buffer, "sequential search\n"); + } + GRN_API_RETURN(GRN_SUCCESS); +} + +static unsigned int +grn_expr_estimate_size_raw(grn_ctx *ctx, grn_obj *expr, grn_obj *table) +{ + return grn_table_size(ctx, table); +} + +unsigned int +grn_expr_estimate_size(grn_ctx *ctx, grn_obj *expr) +{ + grn_obj *table; + grn_obj *variable; + unsigned int size; + + variable = grn_expr_get_var_by_offset(ctx, expr, 0); + if (!variable) { + ERR(GRN_INVALID_ARGUMENT, "at least one variable must be defined"); + return 0; + } + + table = grn_ctx_at(ctx, variable->header.domain); + if (!table) { + ERR(GRN_INVALID_ARGUMENT, + "variable refers unknown domain: <%u>", variable->header.domain); + return 0; + } + + GRN_API_ENTER; +#ifdef GRN_WITH_MRUBY + grn_ctx_impl_mrb_ensure_init(ctx); + if (ctx->rc != GRN_SUCCESS) { + GRN_API_RETURN(0); + } + if (ctx->impl->mrb.state) { + size = grn_mrb_expr_estimate_size(ctx, expr, table); + } else { + size = grn_expr_estimate_size_raw(ctx, expr, table); + } +#else + size = grn_expr_estimate_size_raw(ctx, expr, table); +#endif + GRN_API_RETURN(size); +} diff --git a/storage/mroonga/vendor/groonga/lib/expr_code.c b/storage/mroonga/vendor/groonga/lib/expr_code.c new file mode 100644 index 00000000..a2dfc60b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/expr_code.c @@ -0,0 +1,55 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_expr_code.h" + +unsigned int +grn_expr_code_n_used_codes(grn_ctx *ctx, + grn_expr_code *start, + grn_expr_code *target) +{ + unsigned int n_codes; + int i, n_args; + grn_expr_code *sub_code; + + if (start == target) { + return 0; + } + + n_args = target->nargs; + if (target->value) { + n_args--; + if (n_args == 0) { + return 1; + } + } + + n_codes = 1; + sub_code = target - 1; + for (i = 0; i < n_args; i++) { + int sub_n_codes; + sub_n_codes = grn_expr_code_n_used_codes(ctx, start, sub_code); + n_codes += sub_n_codes; + sub_code -= sub_n_codes; + if (sub_code < start) { + /* TODO: report error */ + return 0; + } + } + + return n_codes; +} diff --git a/storage/mroonga/vendor/groonga/lib/expr_executor.c b/storage/mroonga/vendor/groonga/lib/expr_executor.c new file mode 100644 index 00000000..bc78a650 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/expr_executor.c @@ -0,0 +1,945 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_ctx_impl.h" +#include "grn_expr_executor.h" + +#ifdef GRN_WITH_ONIGMO +# define GRN_SUPPORT_REGEXP +#endif + +#ifdef GRN_SUPPORT_REGEXP +# include "grn_normalizer.h" +# include +#endif + +typedef union { + struct { + grn_obj result_buffer; + } constant; + struct { + grn_obj *column; + grn_obj value_buffer; + } value; +#ifdef GRN_SUPPORT_REGEXP + struct { + grn_obj result_buffer; + OnigRegex regex; + grn_obj value_buffer; + grn_obj *normalizer; + } simple_regexp; +#endif /* GRN_SUPPORT_REGEXP */ + struct { + grn_proc_ctx proc_ctx; + int n_args; + } proc; + struct { + grn_obj result_buffer; + grn_ra *ra; + grn_ra_cache ra_cache; + unsigned int ra_element_size; + grn_obj value_buffer; + grn_obj constant_buffer; + grn_operator_exec_func *exec; + } simple_condition_ra; + struct { + grn_bool need_exec; + grn_obj result_buffer; + grn_obj value_buffer; + grn_obj constant_buffer; + grn_operator_exec_func *exec; + } simple_condition; +} grn_expr_executor_data; + +typedef grn_obj *(*grn_expr_executor_exec_func)(grn_ctx *ctx, + grn_expr_executor *executor, + grn_id id); +typedef void (*grn_expr_executor_fin_func)(grn_ctx *ctx, + grn_expr_executor *executor); + +struct _grn_expr_executor { + grn_obj *expr; + grn_obj *variable; + grn_expr_executor_exec_func exec; + grn_expr_executor_fin_func fin; + grn_expr_executor_data data; +}; + +static void +grn_expr_executor_init_general(grn_ctx *ctx, + grn_expr_executor *executor) +{ +} + +static grn_obj * +grn_expr_executor_exec_general(grn_ctx *ctx, + grn_expr_executor *executor, + grn_id id) +{ + GRN_RECORD_SET(ctx, executor->variable, id); + return grn_expr_exec(ctx, executor->expr, 0); +} + +static void +grn_expr_executor_fin_general(grn_ctx *ctx, + grn_expr_executor *executor) +{ +} + +static grn_bool +grn_expr_executor_is_constant(grn_ctx *ctx, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + grn_expr_code *target; + + if (e->codes_curr != 1) { + return GRN_FALSE; + } + + target = &(e->codes[0]); + + if (target->op != GRN_OP_PUSH) { + return GRN_FALSE; + } + if (!target->value) { + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static void +grn_expr_executor_init_constant(grn_ctx *ctx, + grn_expr_executor *executor) +{ + grn_obj *result_buffer = &(executor->data.constant.result_buffer); + grn_obj *result; + + GRN_VOID_INIT(result_buffer); + result = grn_expr_exec(ctx, executor->expr, 0); + if (ctx->rc == GRN_SUCCESS) { + grn_obj_reinit(ctx, + result_buffer, + result->header.domain, + result->header.flags); + /* TODO: Support vector */ + grn_bulk_write(ctx, + result_buffer, + GRN_BULK_HEAD(result), + GRN_BULK_VSIZE(result)); + } +} + +static grn_obj * +grn_expr_executor_exec_constant(grn_ctx *ctx, + grn_expr_executor *executor, + grn_id id) +{ + return &(executor->data.constant.result_buffer); +} + +static void +grn_expr_executor_fin_constant(grn_ctx *ctx, + grn_expr_executor *executor) +{ + GRN_OBJ_FIN(ctx, &(executor->data.constant.result_buffer)); +} + +static grn_bool +grn_expr_executor_is_value(grn_ctx *ctx, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + grn_expr_code *target; + + if (e->codes_curr != 1) { + return GRN_FALSE; + } + + target = &(e->codes[0]); + + if (target->op != GRN_OP_GET_VALUE) { + return GRN_FALSE; + } + if (!target->value) { + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static void +grn_expr_executor_init_value(grn_ctx *ctx, + grn_expr_executor *executor) +{ + grn_expr *e = (grn_expr *)(executor->expr); + + executor->data.value.column = e->codes[0].value; + GRN_VOID_INIT(&(executor->data.value.value_buffer)); +} + +static grn_obj * +grn_expr_executor_exec_value(grn_ctx *ctx, + grn_expr_executor *executor, + grn_id id) +{ + grn_obj *value_buffer = &(executor->data.value.value_buffer); + + GRN_BULK_REWIND(value_buffer); + grn_obj_get_value(ctx, executor->data.value.column, id, value_buffer); + + return value_buffer; +} + +static void +grn_expr_executor_fin_value(grn_ctx *ctx, + grn_expr_executor *executor) +{ + GRN_OBJ_FIN(ctx, &(executor->data.value.value_buffer)); +} + +#ifdef GRN_SUPPORT_REGEXP +static grn_bool +grn_expr_executor_is_simple_regexp(grn_ctx *ctx, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + grn_expr_code *target; + grn_expr_code *pattern; + grn_expr_code *operator; + + if (e->codes_curr != 3) { + return GRN_FALSE; + } + + target = &(e->codes[0]); + pattern = &(e->codes[1]); + operator = &(e->codes[2]); + + if (operator->op != GRN_OP_REGEXP) { + return GRN_FALSE; + } + if (operator->nargs != 2) { + return GRN_FALSE; + } + + if (target->op != GRN_OP_GET_VALUE) { + return GRN_FALSE; + } + if (target->nargs != 1) { + return GRN_FALSE; + } + if (!target->value) { + return GRN_FALSE; + } + if (target->value->header.type != GRN_COLUMN_VAR_SIZE) { + return GRN_FALSE; + } + if ((target->value->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) != + GRN_OBJ_COLUMN_SCALAR) { + return GRN_FALSE; + } + switch (grn_obj_get_range(ctx, target->value)) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + break; + default : + return GRN_FALSE; + } + + if (pattern->op != GRN_OP_PUSH) { + return GRN_FALSE; + } + if (pattern->nargs != 1) { + return GRN_FALSE; + } + if (!pattern->value) { + return GRN_FALSE; + } + if (pattern->value->header.type != GRN_BULK) { + return GRN_FALSE; + } + switch (pattern->value->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + break; + default : + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static void +grn_expr_executor_init_simple_regexp(grn_ctx *ctx, + grn_expr_executor *executor) +{ + grn_expr *e = (grn_expr *)(executor->expr); + grn_obj *result_buffer = &(executor->data.simple_regexp.result_buffer); + OnigEncoding onig_encoding; + int onig_result; + OnigErrorInfo onig_error_info; + grn_obj *pattern; + + GRN_BOOL_INIT(result_buffer, 0); + GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE); + + if (ctx->encoding == GRN_ENC_NONE) { + executor->data.simple_regexp.regex = NULL; + return; + } + + switch (ctx->encoding) { + case GRN_ENC_EUC_JP : + onig_encoding = ONIG_ENCODING_EUC_JP; + break; + case GRN_ENC_UTF8 : + onig_encoding = ONIG_ENCODING_UTF8; + break; + case GRN_ENC_SJIS : + onig_encoding = ONIG_ENCODING_CP932; + break; + case GRN_ENC_LATIN1 : + onig_encoding = ONIG_ENCODING_ISO_8859_1; + break; + case GRN_ENC_KOI8R : + onig_encoding = ONIG_ENCODING_KOI8_R; + break; + default : + executor->data.simple_regexp.regex = NULL; + return; + } + + pattern = e->codes[1].value; + onig_result = onig_new(&(executor->data.simple_regexp.regex), + GRN_TEXT_VALUE(pattern), + GRN_TEXT_VALUE(pattern) + GRN_TEXT_LEN(pattern), + ONIG_OPTION_ASCII_RANGE | + ONIG_OPTION_MULTILINE, + onig_encoding, + ONIG_SYNTAX_RUBY, + &onig_error_info); + if (onig_result != ONIG_NORMAL) { + char message[ONIG_MAX_ERROR_MESSAGE_LEN]; + onig_error_code_to_str(message, onig_result, onig_error_info); + ERR(GRN_INVALID_ARGUMENT, + "[expr-executor][regexp] " + "failed to create regular expression object: <%.*s>: %s", + (int)GRN_TEXT_LEN(pattern), GRN_TEXT_VALUE(pattern), + message); + return; + } + + GRN_VOID_INIT(&(executor->data.simple_regexp.value_buffer)); + + executor->data.simple_regexp.normalizer = + grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); +} + +static grn_obj * +grn_expr_executor_exec_simple_regexp(grn_ctx *ctx, + grn_expr_executor *executor, + grn_id id) +{ + grn_expr *e = (grn_expr *)(executor->expr); + OnigRegex regex = executor->data.simple_regexp.regex; + grn_obj *value_buffer = &(executor->data.simple_regexp.value_buffer); + grn_obj *result_buffer = &(executor->data.simple_regexp.result_buffer); + + if (ctx->rc) { + GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE); + return result_buffer; + } + + if (!regex) { + return result_buffer; + } + + grn_obj_reinit_for(ctx, value_buffer, e->codes[0].value); + grn_obj_get_value(ctx, e->codes[0].value, id, value_buffer); + { + grn_obj *norm_target; + const char *norm_target_raw; + unsigned int norm_target_raw_length_in_bytes; + + norm_target = grn_string_open(ctx, + GRN_TEXT_VALUE(value_buffer), + GRN_TEXT_LEN(value_buffer), + executor->data.simple_regexp.normalizer, + 0); + grn_string_get_normalized(ctx, norm_target, + &norm_target_raw, + &norm_target_raw_length_in_bytes, + NULL); + + { + OnigPosition position; + position = onig_search(regex, + norm_target_raw, + norm_target_raw + norm_target_raw_length_in_bytes, + norm_target_raw, + norm_target_raw + norm_target_raw_length_in_bytes, + NULL, + ONIG_OPTION_NONE); + grn_obj_close(ctx, norm_target); + GRN_BOOL_SET(ctx, result_buffer, (position != ONIG_MISMATCH)); + return result_buffer; + } + } +} + +static void +grn_expr_executor_fin_simple_regexp(grn_ctx *ctx, + grn_expr_executor *executor) +{ + GRN_OBJ_FIN(ctx, &(executor->data.simple_regexp.result_buffer)); + + if (!executor->data.simple_regexp.regex) { + return; + } + + onig_free(executor->data.simple_regexp.regex); + GRN_OBJ_FIN(ctx, &(executor->data.simple_regexp.value_buffer)); +} +#endif /* GRN_SUPPORT_REGEXP */ + +static grn_bool +grn_expr_executor_is_proc(grn_ctx *ctx, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + grn_obj *first; + grn_proc *proc; + + if (e->codes_curr < 2) { + return GRN_FALSE; + } + + first = e->codes[0].value; + if (!grn_obj_is_function_proc(ctx, first)) { + return GRN_FALSE; + } + + proc = (grn_proc *)first; + if (!(proc->funcs[PROC_INIT] && + proc->funcs[PROC_NEXT])) { + return GRN_FALSE; + } + + if (e->codes[e->codes_curr - 1].op != GRN_OP_CALL) { + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static void +grn_expr_executor_init_proc(grn_ctx *ctx, + grn_expr_executor *executor) +{ + grn_proc_ctx *proc_ctx = &(executor->data.proc.proc_ctx); + grn_expr *expr; + grn_proc *proc; + + expr = (grn_expr *)(executor->expr); + proc = (grn_proc *)(expr->codes[0].value); + proc_ctx->proc = proc; + proc_ctx->caller = executor->expr; + proc_ctx->phase = PROC_INIT; + + executor->data.proc.n_args = expr->codes[expr->codes_curr - 1].nargs - 1; + + proc->funcs[PROC_INIT](ctx, 0, NULL, &(proc_ctx->user_data)); +} + +static grn_obj * +grn_expr_executor_exec_proc(grn_ctx *ctx, + grn_expr_executor *executor, + grn_id id) +{ + grn_proc_ctx *proc_ctx = &(executor->data.proc.proc_ctx); + int n_args = executor->data.proc.n_args; + grn_proc *proc; + grn_expr *expr; + grn_obj **args; + uint32_t values_curr; + uint32_t values_tail; + grn_obj *result; + + proc = proc_ctx->proc; + proc_ctx->phase = PROC_NEXT; + GRN_RECORD_SET(ctx, executor->variable, id); + + expr = (grn_expr *)(executor->expr); + values_curr = expr->values_curr; + values_tail = expr->values_tail; + + expr->codes += 1; + expr->codes_curr -= 2; + grn_expr_exec(ctx, executor->expr, 0); + expr->codes_curr += 2; + expr->codes -= 1; + + args = ctx->impl->stack + ctx->impl->stack_curr; + ctx->impl->stack_curr += n_args; + expr->values_curr = expr->values_tail; + result = proc->funcs[PROC_NEXT](ctx, + n_args, + args, + &(proc_ctx->user_data)); + ctx->impl->stack_curr -= n_args; + + expr->values_tail = values_tail; + expr->values_curr = values_curr; + + return result; +} + +static void +grn_expr_executor_fin_proc(grn_ctx *ctx, + grn_expr_executor *executor) +{ + grn_proc_ctx *proc_ctx = &(executor->data.proc.proc_ctx); + grn_proc *proc; + + proc = proc_ctx->proc; + proc_ctx->phase = PROC_FIN; + if (proc->funcs[PROC_FIN]) { + proc->funcs[PROC_FIN](ctx, 0, NULL, &(proc_ctx->user_data)); + } +} + +static grn_bool +grn_expr_executor_is_simple_condition_ra(grn_ctx *ctx, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + grn_expr_code *target; + grn_expr_code *constant; + grn_expr_code *operator; + + if (e->codes_curr != 3) { + return GRN_FALSE; + } + + target = &(e->codes[0]); + constant = &(e->codes[1]); + operator = &(e->codes[2]); + + switch (operator->op) { + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + break; + default : + return GRN_FALSE; + } + if (operator->nargs != 2) { + return GRN_FALSE; + } + + if (target->op != GRN_OP_GET_VALUE) { + return GRN_FALSE; + } + if (target->nargs != 1) { + return GRN_FALSE; + } + if (target->value->header.type != GRN_COLUMN_FIX_SIZE) { + return GRN_FALSE; + } + + if (constant->op != GRN_OP_PUSH) { + return GRN_FALSE; + } + if (constant->nargs != 1) { + return GRN_FALSE; + } + if (!constant->value) { + return GRN_FALSE; + } + if (constant->value->header.type != GRN_BULK) { + return GRN_FALSE; + } + + { + grn_obj constant_buffer; + grn_rc rc; + GRN_VOID_INIT(&constant_buffer); + grn_obj_reinit_for(ctx, &constant_buffer, target->value); + rc = grn_obj_cast(ctx, constant->value, &constant_buffer, GRN_FALSE); + GRN_OBJ_FIN(ctx, &constant_buffer); + if (rc != GRN_SUCCESS) { + return GRN_FALSE; + } + } + + return GRN_TRUE; +} + +static void +grn_expr_executor_init_simple_condition_ra(grn_ctx *ctx, + grn_expr_executor *executor) +{ + grn_expr *e = (grn_expr *)(executor->expr); + grn_obj *target; + grn_obj *constant; + grn_operator op; + grn_obj *result_buffer; + grn_obj *value_buffer; + grn_obj *constant_buffer; + + target = e->codes[0].value; + constant = e->codes[1].value; + op = e->codes[2].op; + + result_buffer = &(executor->data.simple_condition_ra.result_buffer); + GRN_BOOL_INIT(result_buffer, 0); + GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE); + + value_buffer = &(executor->data.simple_condition_ra.value_buffer); + GRN_VOID_INIT(value_buffer); + grn_obj_reinit_for(ctx, value_buffer, target); + + executor->data.simple_condition_ra.ra = (grn_ra *)target; + GRN_RA_CACHE_INIT(executor->data.simple_condition_ra.ra, + &(executor->data.simple_condition_ra.ra_cache)); + grn_ra_info(ctx, + executor->data.simple_condition_ra.ra, + &(executor->data.simple_condition_ra.ra_element_size)); + + executor->data.simple_condition_ra.exec = grn_operator_to_exec_func(op); + + constant_buffer = &(executor->data.simple_condition_ra.constant_buffer); + GRN_VOID_INIT(constant_buffer); + grn_obj_reinit_for(ctx, constant_buffer, target); + grn_obj_cast(ctx, constant, constant_buffer, GRN_FALSE); +} + +static grn_obj * +grn_expr_executor_exec_simple_condition_ra(grn_ctx *ctx, + grn_expr_executor *executor, + grn_id id) +{ + grn_obj *result_buffer = &(executor->data.simple_condition_ra.result_buffer); + grn_obj *value_buffer = &(executor->data.simple_condition_ra.value_buffer); + grn_obj *constant_buffer = + &(executor->data.simple_condition_ra.constant_buffer); + + if (ctx->rc) { + GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE); + return result_buffer; + } + + { + grn_ra *ra = executor->data.simple_condition_ra.ra; + grn_ra_cache *ra_cache = &(executor->data.simple_condition_ra.ra_cache); + unsigned int ra_element_size = + executor->data.simple_condition_ra.ra_element_size; + void *raw_value; + raw_value = grn_ra_ref_cache(ctx, ra, id, ra_cache); + GRN_BULK_REWIND(value_buffer); + grn_bulk_write(ctx, value_buffer, raw_value, ra_element_size); + } + + if (executor->data.simple_condition_ra.exec(ctx, + value_buffer, + constant_buffer)) { + GRN_BOOL_SET(ctx, result_buffer, GRN_TRUE); + } else { + GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE); + } + return result_buffer; +} + +static void +grn_expr_executor_fin_simple_condition_ra(grn_ctx *ctx, + grn_expr_executor *executor) +{ + GRN_OBJ_FIN(ctx, &(executor->data.simple_condition_ra.result_buffer)); + GRN_RA_CACHE_FIN(executor->data.simple_condition_ra.ra, + &(executor->data.simple_condition_ra.ra_cache)); + GRN_OBJ_FIN(ctx, &(executor->data.simple_condition_ra.value_buffer)); + GRN_OBJ_FIN(ctx, &(executor->data.simple_condition_ra.constant_buffer)); +} + +static grn_bool +grn_expr_executor_is_simple_condition(grn_ctx *ctx, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + grn_expr_code *target; + grn_expr_code *constant; + grn_expr_code *operator; + + if (e->codes_curr != 3) { + return GRN_FALSE; + } + + target = &(e->codes[0]); + constant = &(e->codes[1]); + operator = &(e->codes[2]); + + switch (operator->op) { + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + case GRN_OP_LESS : + case GRN_OP_GREATER : + case GRN_OP_LESS_EQUAL : + case GRN_OP_GREATER_EQUAL : + break; + default : + return GRN_FALSE; + } + if (operator->nargs != 2) { + return GRN_FALSE; + } + + if (target->op != GRN_OP_GET_VALUE) { + return GRN_FALSE; + } + if (target->nargs != 1) { + return GRN_FALSE; + } + if (!grn_obj_is_scalar_column(ctx, target->value)) { + return GRN_FALSE; + } + + if (constant->op != GRN_OP_PUSH) { + return GRN_FALSE; + } + if (constant->nargs != 1) { + return GRN_FALSE; + } + if (!constant->value) { + return GRN_FALSE; + } + if (constant->value->header.type != GRN_BULK) { + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static void +grn_expr_executor_init_simple_condition(grn_ctx *ctx, + grn_expr_executor *executor) +{ + grn_expr *e = (grn_expr *)(executor->expr); + grn_obj *target; + grn_obj *constant; + grn_operator op; + grn_obj *result_buffer; + grn_obj *value_buffer; + grn_obj *constant_buffer; + grn_rc rc; + + target = e->codes[0].value; + constant = e->codes[1].value; + op = e->codes[2].op; + + executor->data.simple_condition.need_exec = GRN_TRUE; + + result_buffer = &(executor->data.simple_condition.result_buffer); + GRN_BOOL_INIT(result_buffer, 0); + GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE); + + value_buffer = &(executor->data.simple_condition.value_buffer); + GRN_VOID_INIT(value_buffer); + grn_obj_reinit_for(ctx, value_buffer, target); + + executor->data.simple_condition.exec = grn_operator_to_exec_func(op); + + constant_buffer = &(executor->data.simple_condition.constant_buffer); + GRN_VOID_INIT(constant_buffer); + grn_obj_reinit_for(ctx, constant_buffer, target); + rc = grn_obj_cast(ctx, constant, constant_buffer, GRN_FALSE); + if (rc != GRN_SUCCESS) { + grn_obj *type; + + type = grn_ctx_at(ctx, constant_buffer->header.domain); + if (grn_obj_is_table(ctx, type)) { + GRN_BOOL_SET(ctx, result_buffer, (op == GRN_OP_NOT_EQUAL)); + executor->data.simple_condition.need_exec = GRN_FALSE; + } else { + int type_name_size; + char type_name[GRN_TABLE_MAX_KEY_SIZE]; + grn_obj inspected; + + type_name_size = grn_obj_name(ctx, type, type_name, + GRN_TABLE_MAX_KEY_SIZE); + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, constant); + ERR(rc, + "[expr-executor][condition] " + "failed to cast to <%.*s>: <%.*s>", + type_name_size, type_name, + (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); + } + } +} + +static grn_obj * +grn_expr_executor_exec_simple_condition(grn_ctx *ctx, + grn_expr_executor *executor, + grn_id id) +{ + grn_expr *e = (grn_expr *)(executor->expr); + grn_obj *target; + grn_obj *result_buffer = &(executor->data.simple_condition.result_buffer); + grn_obj *value_buffer = &(executor->data.simple_condition.value_buffer); + grn_obj *constant_buffer = &(executor->data.simple_condition.constant_buffer); + + if (ctx->rc) { + GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE); + return result_buffer; + } + + if (!executor->data.simple_condition.need_exec) { + return result_buffer; + } + + target = e->codes[0].value; + GRN_BULK_REWIND(value_buffer); + grn_obj_get_value(ctx, target, id, value_buffer); + + if (executor->data.simple_condition.exec(ctx, value_buffer, constant_buffer)) { + GRN_BOOL_SET(ctx, result_buffer, GRN_TRUE); + } else { + GRN_BOOL_SET(ctx, result_buffer, GRN_FALSE); + } + return result_buffer; +} + +static void +grn_expr_executor_fin_simple_condition(grn_ctx *ctx, + grn_expr_executor *executor) +{ + GRN_OBJ_FIN(ctx, &(executor->data.simple_condition.result_buffer)); + GRN_OBJ_FIN(ctx, &(executor->data.simple_condition.value_buffer)); + GRN_OBJ_FIN(ctx, &(executor->data.simple_condition.constant_buffer)); +} + +grn_expr_executor * +grn_expr_executor_open(grn_ctx *ctx, grn_obj *expr) +{ + grn_obj *variable; + grn_expr_executor *executor; + + GRN_API_ENTER; + + if (!grn_obj_is_expr(ctx, expr)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, expr); + ERR(ctx->rc, + "[expr-executor][open] invalid expression: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + GRN_API_RETURN(NULL); + } + + variable = grn_expr_get_var_by_offset(ctx, expr, 0); + if (!variable) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, expr); + ERR(ctx->rc, + "[expr-executor][open] expression has no variable: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + GRN_API_RETURN(NULL); + } + + executor = GRN_CALLOC(sizeof(grn_expr_executor)); + if (!executor) { + ERR(ctx->rc, + "[expr-executor][open] failed to allocate: %s", + ctx->errbuf); + GRN_API_RETURN(NULL); + } + + executor->expr = expr; + executor->variable = variable; + if (grn_expr_executor_is_constant(ctx, expr)) { + grn_expr_executor_init_constant(ctx, executor); + executor->exec = grn_expr_executor_exec_constant; + executor->fin = grn_expr_executor_fin_constant; + } else if (grn_expr_executor_is_value(ctx, expr)) { + grn_expr_executor_init_value(ctx, executor); + executor->exec = grn_expr_executor_exec_value; + executor->fin = grn_expr_executor_fin_value; +#ifdef GRN_SUPPORT_REGEXP + } else if (grn_expr_executor_is_simple_regexp(ctx, expr)) { + grn_expr_executor_init_simple_regexp(ctx, executor); + executor->exec = grn_expr_executor_exec_simple_regexp; + executor->fin = grn_expr_executor_fin_simple_regexp; +#endif /* GRN_SUPPORT_REGEXP */ + } else if (grn_expr_executor_is_proc(ctx, expr)) { + grn_expr_executor_init_proc(ctx, executor); + executor->exec = grn_expr_executor_exec_proc; + executor->fin = grn_expr_executor_fin_proc; + } else if (grn_expr_executor_is_simple_condition_ra(ctx, expr)) { + grn_expr_executor_init_simple_condition_ra(ctx, executor); + executor->exec = grn_expr_executor_exec_simple_condition_ra; + executor->fin = grn_expr_executor_fin_simple_condition_ra; + } else if (grn_expr_executor_is_simple_condition(ctx, expr)) { + grn_expr_executor_init_simple_condition(ctx, executor); + executor->exec = grn_expr_executor_exec_simple_condition; + executor->fin = grn_expr_executor_fin_simple_condition; + } else { + grn_expr_executor_init_general(ctx, executor); + executor->exec = grn_expr_executor_exec_general; + executor->fin = grn_expr_executor_fin_general; + } + + GRN_API_RETURN(executor); +} + +grn_obj * +grn_expr_executor_exec(grn_ctx *ctx, grn_expr_executor *executor, grn_id id) +{ + grn_obj *value; + + GRN_API_ENTER; + + if (!executor) { + GRN_API_RETURN(NULL); + } + + value = executor->exec(ctx, executor, id); + + GRN_API_RETURN(value); +} + +grn_rc +grn_expr_executor_close(grn_ctx *ctx, grn_expr_executor *executor) +{ + GRN_API_ENTER; + + if (!executor) { + GRN_API_RETURN(GRN_SUCCESS); + } + + executor->fin(ctx, executor); + GRN_FREE(executor); + + GRN_API_RETURN(GRN_SUCCESS); +} diff --git a/storage/mroonga/vendor/groonga/lib/file_lock.c b/storage/mroonga/vendor/groonga/lib/file_lock.c new file mode 100644 index 00000000..3cf8acf1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/file_lock.c @@ -0,0 +1,121 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_file_lock.h" +#include "grn_ctx.h" + +#include + +#ifdef WIN32 +# include +# include +#else /* WIN32 */ +# include +# include +#endif /* WIN32 */ + +#ifdef WIN32 +# define GRN_FILE_LOCK_IS_INVALID(file_lock) \ + ((file_lock)->handle == INVALID_HANDLE_VALUE) +#else /* WIN32 */ +# define GRN_FILE_LOCK_IS_INVALID(file_lock) \ + ((file_lock)->fd == -1) +#endif /* WIN32 */ + +void +grn_file_lock_init(grn_ctx *ctx, + grn_file_lock *file_lock, + const char *path) +{ + file_lock->path = path; +#ifdef WIN32 + file_lock->handle = INVALID_HANDLE_VALUE; +#else /* WIN32 */ + file_lock->fd = -1; +#endif /* WIN32 */ +} + +grn_bool +grn_file_lock_acquire(grn_ctx *ctx, + grn_file_lock *file_lock, + int timeout, + const char *error_message_tag) +{ + int i; + int n_lock_tries = timeout; + + if (!file_lock->path) { + return GRN_TRUE; + } + + for (i = 0; i < n_lock_tries; i++) { +#ifdef WIN32 + file_lock->handle = CreateFile(file_lock->path, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); +#else /* WIN32 */ + file_lock->fd = open(file_lock->path, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); +#endif + if (!GRN_FILE_LOCK_IS_INVALID(file_lock)) { + break; + } + grn_nanosleep(GRN_LOCK_WAIT_TIME_NANOSECOND); + } + + if (GRN_FILE_LOCK_IS_INVALID(file_lock)) { + ERR(GRN_NO_LOCKS_AVAILABLE, + "%s failed to acquire lock: <%s>", + error_message_tag, file_lock->path); + return GRN_FALSE; + } else { + return GRN_TRUE; + } +} + +void +grn_file_lock_release(grn_ctx *ctx, grn_file_lock *file_lock) +{ + if (GRN_FILE_LOCK_IS_INVALID(file_lock)) { + return; + } + +#ifdef WIN32 + CloseHandle(file_lock->handle); + DeleteFile(file_lock->path); + + file_lock->handle = INVALID_HANDLE_VALUE; +#else /* WIN32 */ + close(file_lock->fd); + unlink(file_lock->path); + + file_lock->fd = -1; +#endif /* WIN32 */ + file_lock->path = NULL; +} + +void +grn_file_lock_fin(grn_ctx *ctx, grn_file_lock *file_lock) +{ + if (!GRN_FILE_LOCK_IS_INVALID(file_lock)) { + grn_file_lock_release(ctx, file_lock); + } +} diff --git a/storage/mroonga/vendor/groonga/lib/file_reader.c b/storage/mroonga/vendor/groonga/lib/file_reader.c new file mode 100644 index 00000000..0ba23274 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/file_reader.c @@ -0,0 +1,109 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_ctx.h" +#include "grn_str.h" + +#include +#include + +#ifdef WIN32 +# include +#endif /* WIN32 */ + +struct _grn_file_reader { + FILE *file; + grn_bool file_need_close; +}; + +grn_file_reader * +grn_file_reader_open(grn_ctx *ctx, const char *path) +{ + grn_file_reader *reader; + FILE *file; + grn_bool file_need_close; + + GRN_API_ENTER; + + if (!path) { + ERR(GRN_INVALID_ARGUMENT, "[file-reader][open] path must not NULL"); + GRN_API_RETURN(NULL); + } + + if (strcmp(path, "-") == 0) { + file = stdin; + file_need_close = GRN_FALSE; + } else { + file = grn_fopen(path, "r"); + if (!file) { + SERR("[file-reader][open] failed to open path: <%s>", path); + GRN_API_RETURN(NULL); + } + file_need_close = GRN_TRUE; + } + + reader = GRN_MALLOC(sizeof(grn_file_reader)); + reader->file = file; + reader->file_need_close = file_need_close; + + GRN_API_RETURN(reader); +} + +void +grn_file_reader_close(grn_ctx *ctx, grn_file_reader *reader) +{ + if (!reader) { + return; + } + + if (reader->file_need_close) { + if (fclose(reader->file) != 0) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "[file-reader][close] failed to close: <%s>", + grn_strerror(errno)); + } + } + + GRN_FREE(reader); +} + +grn_rc +grn_file_reader_read_line(grn_ctx *ctx, + grn_file_reader *reader, + grn_obj *buffer) +{ + grn_rc rc = GRN_END_OF_DATA; + + for (;;) { + size_t len; + +#define BUFFER_SIZE 4096 + grn_bulk_reserve(ctx, buffer, BUFFER_SIZE); + if (!fgets(GRN_BULK_CURR(buffer), BUFFER_SIZE, reader->file)) { + break; + } +#undef BUFFER_SIZE + + if (!(len = strlen(GRN_BULK_CURR(buffer)))) { break; } + GRN_BULK_INCR_LEN(buffer, len); + rc = GRN_SUCCESS; + if (GRN_BULK_CURR(buffer)[-1] == '\n') { break; } + } + + return rc; +} diff --git a/storage/mroonga/vendor/groonga/lib/geo.c b/storage/mroonga/vendor/groonga/lib/geo.c new file mode 100644 index 00000000..26aca445 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/geo.c @@ -0,0 +1,2788 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_geo.h" +#include "grn_pat.h" +#include "grn_util.h" + +#include +#include + +#define GRN_GEO_POINT_IN_NORTH_EAST(point) \ + ((point)->latitude >= 0 && (point)->longitude >= 0) +#define GRN_GEO_POINT_IN_NORTH_WEST(point) \ + ((point)->latitude >= 0 && (point)->longitude < 0) +#define GRN_GEO_POINT_IN_SOUTH_WEST(point) \ + ((point)->latitude < 0 && (point)->longitude < 0) +#define GRN_GEO_POINT_IN_SOUTH_EAST(point) \ + ((point)->latitude < 0 && (point)->longitude >= 0) + +#define GRN_GEO_LONGITUDE_IS_WRAPPED(top_left, bottom_right) \ + ((top_left)->longitude > 0 && (bottom_right)->longitude < 0) + +typedef struct { + grn_id id; + double d; +} geo_entry; + +typedef struct +{ + grn_geo_point key; + int key_size; +} mesh_entry; + +typedef struct { + grn_obj *pat; + grn_obj top_left_point_buffer; + grn_obj bottom_right_point_buffer; + grn_geo_point *top_left; + grn_geo_point *bottom_right; +} in_rectangle_data; + +typedef struct { + grn_geo_point min; + grn_geo_point max; + int rectangle_common_bit; + uint8_t rectangle_common_key[sizeof(grn_geo_point)]; +} in_rectangle_area_data; + +static int +compute_diff_bit(uint8_t *geo_key1, uint8_t *geo_key2) +{ + int i, j, diff_bit = 0; + + for (i = 0; i < sizeof(grn_geo_point); i++) { + if (geo_key1[i] != geo_key2[i]) { + diff_bit = 8; + for (j = 0; j < 8; j++) { + if ((geo_key1[i] & (1 << (7 - j))) != (geo_key2[i] & (1 << (7 - j)))) { + diff_bit = j; + break; + } + } + break; + } + } + + return i * 8 + diff_bit; +} + +static void +compute_min_and_max_key(uint8_t *key_base, int diff_bit, + uint8_t *key_min, uint8_t *key_max) +{ + int diff_byte, diff_bit_mask; + + diff_byte = diff_bit / 8; + diff_bit_mask = 0xff >> (diff_bit % 8); + + if (diff_byte == sizeof(grn_geo_point)) { + if (key_min) { grn_memcpy(key_min, key_base, diff_byte); } + if (key_max) { grn_memcpy(key_max, key_base, diff_byte); } + } else { + if (key_min) { + grn_memcpy(key_min, key_base, diff_byte + 1); + key_min[diff_byte] &= ~diff_bit_mask; + memset(key_min + diff_byte + 1, 0, + sizeof(grn_geo_point) - diff_byte - 1); + } + + if (key_max) { + grn_memcpy(key_max, key_base, diff_byte + 1); + key_max[diff_byte] |= diff_bit_mask; + memset(key_max + diff_byte + 1, 0xff, + sizeof(grn_geo_point) - diff_byte - 1); + } + } +} + +static void +compute_min_and_max(grn_geo_point *base_point, int diff_bit, + grn_geo_point *geo_min, grn_geo_point *geo_max) +{ + uint8_t geo_key_base[sizeof(grn_geo_point)]; + uint8_t geo_key_min[sizeof(grn_geo_point)]; + uint8_t geo_key_max[sizeof(grn_geo_point)]; + + grn_gton(geo_key_base, base_point, sizeof(grn_geo_point)); + compute_min_and_max_key(geo_key_base, diff_bit, + geo_min ? geo_key_min : NULL, + geo_max ? geo_key_max : NULL); + if (geo_min) { + grn_ntog((uint8_t *)geo_min, geo_key_min, sizeof(grn_geo_point)); + } + if (geo_max) { + grn_ntog((uint8_t *)geo_max, geo_key_max, sizeof(grn_geo_point)); + } +} + +/* #define GEO_DEBUG */ + +#ifdef GEO_DEBUG +#include + +static void +inspect_mesh(grn_ctx *ctx, grn_geo_point *key, int key_size, int n) +{ + grn_geo_point min, max; + + printf("mesh: %d:%d\n", n, key_size); + + printf("key: "); + grn_p_geo_point(ctx, key); + + compute_min_and_max(key, key_size, &min, &max); + printf("min: "); + grn_p_geo_point(ctx, &min); + printf("max: "); + grn_p_geo_point(ctx, &max); +} + +static void +inspect_mesh_entry(grn_ctx *ctx, mesh_entry *entries, int n) +{ + mesh_entry *entry; + + entry = entries + n; + inspect_mesh(ctx, &(entry->key), entry->key_size, n); +} + +static void +inspect_tid(grn_ctx *ctx, grn_id tid, grn_geo_point *point, double d) +{ + printf("tid: %d:%g", tid, d); + grn_p_geo_point(ctx, point); +} + +static void +inspect_key(grn_ctx *ctx, uint8_t *key) +{ + int i; + for (i = 0; i < 8; i++) { + int j; + for (j = 0; j < 8; j++) { + printf("%d", (key[i] & (1 << (7 - j))) >> (7 - j)); + } + printf(" "); + } + printf("\n"); +} + +static void +print_key_mark(grn_ctx *ctx, int target_bit) +{ + int i; + + for (i = 0; i < target_bit; i++) { + printf(" "); + if (i > 0 && i % 8 == 0) { + printf(" "); + } + } + if (i > 0 && i % 8 == 0) { + printf(" "); + } + printf("^\n"); +} + +static void +inspect_cursor_entry(grn_ctx *ctx, grn_geo_cursor_entry *entry) +{ + grn_geo_point point; + + printf("entry: "); + grn_ntog((uint8_t *)&point, entry->key, sizeof(grn_geo_point)); + grn_p_geo_point(ctx, &point); + inspect_key(ctx, entry->key); + print_key_mark(ctx, entry->target_bit); + + printf(" target bit: %d\n", entry->target_bit); + +#define INSPECT_STATUS_FLAG(name) \ + ((entry->status_flags & GRN_GEO_CURSOR_ENTRY_STATUS_ ## name) ? "true" : "false") + + printf(" top included: %s\n", INSPECT_STATUS_FLAG(TOP_INCLUDED)); + printf("bottom included: %s\n", INSPECT_STATUS_FLAG(BOTTOM_INCLUDED)); + printf(" left included: %s\n", INSPECT_STATUS_FLAG(LEFT_INCLUDED)); + printf(" right included: %s\n", INSPECT_STATUS_FLAG(RIGHT_INCLUDED)); + printf(" latitude inner: %s\n", INSPECT_STATUS_FLAG(LATITUDE_INNER)); + printf("longitude inner: %s\n", INSPECT_STATUS_FLAG(LONGITUDE_INNER)); + +#undef INSPECT_STATUS_FLAG +} + +static void +inspect_cursor_entry_targets(grn_ctx *ctx, grn_geo_cursor_entry *entry, + uint8_t *top_left_key, uint8_t *bottom_right_key, + grn_geo_cursor_entry *next_entry0, + grn_geo_cursor_entry *next_entry1) +{ + printf("entry: "); + inspect_key(ctx, entry->key); + printf("top-left: "); + inspect_key(ctx, top_left_key); + printf("bottom-right: "); + inspect_key(ctx, bottom_right_key); + printf("next-entry-0: "); + inspect_key(ctx, next_entry0->key); + printf("next-entry-1: "); + inspect_key(ctx, next_entry1->key); + printf(" "); + print_key_mark(ctx, entry->target_bit + 1); +} +#else +# define inspect_mesh(...) +# define inspect_mesh_entry(...) +# define inspect_tid(...) +# define inspect_key(...) +# define print_key_mark(...) +# define inspect_cursor_entry(...) +# define inspect_cursor_entry_targets(...) +#endif + +static int +grn_geo_table_sort_detect_far_point(grn_ctx *ctx, grn_obj *table, grn_obj *index, + grn_pat *pat, geo_entry *entries, + grn_pat_cursor *pc, int n, + grn_bool accessorp, + grn_geo_point *base_point, + double *d_far, int *diff_bit) +{ + int i = 0, diff_bit_prev, diff_bit_current; + grn_id tid; + geo_entry *ep, *p; + double d; + uint8_t geo_key_prev[sizeof(grn_geo_point)]; + uint8_t geo_key_curr[sizeof(grn_geo_point)]; + grn_geo_point point; + + *d_far = 0.0; + grn_gton(geo_key_curr, base_point, sizeof(grn_geo_point)); + *diff_bit = sizeof(grn_geo_point) * 8; + diff_bit_current = sizeof(grn_geo_point) * 8; + grn_memcpy(&point, base_point, sizeof(grn_geo_point)); + ep = entries; + inspect_mesh(ctx, &point, *diff_bit, -1); + while ((tid = grn_pat_cursor_next(ctx, pc))) { + grn_ii_cursor *ic = grn_ii_cursor_open(ctx, (grn_ii *)index, tid, 0, 0, 1, 0); + if (ic) { + grn_posting *posting; + grn_gton(geo_key_prev, &point, sizeof(grn_geo_point)); + grn_pat_get_key(ctx, pat, tid, &point, sizeof(grn_geo_point)); + grn_gton(geo_key_curr, &point, sizeof(grn_geo_point)); + d = grn_geo_distance_rectangle_raw(ctx, base_point, &point); + inspect_tid(ctx, tid, &point, d); + + diff_bit_prev = diff_bit_current; + diff_bit_current = compute_diff_bit(geo_key_curr, geo_key_prev); +#ifdef GEO_DEBUG + printf("diff: %d:%d:%d\n", *diff_bit, diff_bit_prev, diff_bit_current); +#endif + if ((diff_bit_current % 2) == 1) { + diff_bit_current--; + } + if (diff_bit_current < diff_bit_prev && *diff_bit > diff_bit_current) { + if (i == n) { + grn_ii_cursor_close(ctx, ic); + break; + } + *diff_bit = diff_bit_current; + } + + if (d > *d_far) { + *d_far = d; + } + while ((posting = grn_ii_cursor_next(ctx, ic))) { + grn_id rid = accessorp + ? grn_table_get(ctx, table, &posting->rid, sizeof(grn_id)) + : posting->rid; + if (rid) { + for (p = ep; entries < p && p[-1].d > d; p--) { + p->id = p[-1].id; + p->d = p[-1].d; + } + p->id = rid; + p->d = d; + if (i < n) { + ep++; + i++; + } + } + } + grn_ii_cursor_close(ctx, ic); + } + } + + return i; +} + +typedef enum { + MESH_LEFT_TOP, + MESH_RIGHT_TOP, + MESH_RIGHT_BOTTOM, + MESH_LEFT_BOTTOM +} mesh_position; + +/* + meshes should have + 86 >= spaces when include_base_point_hash == GRN_FALSE, + 87 >= spaces when include_base_point_hash == GRN_TRUE. +*/ +static int +grn_geo_get_meshes_for_circle(grn_ctx *ctx, grn_geo_point *base_point, + double d_far, int diff_bit, + int include_base_point_mesh, + mesh_entry *meshes) +{ + double d; + int n_meshes; + int lat_diff, lng_diff; + mesh_position position; + grn_geo_point geo_base, geo_min, geo_max; + + compute_min_and_max(base_point, diff_bit - 2, &geo_min, &geo_max); + + lat_diff = (geo_max.latitude - geo_min.latitude + 1) / 2; + lng_diff = (geo_max.longitude - geo_min.longitude + 1) / 2; + geo_base.latitude = geo_min.latitude + lat_diff; + geo_base.longitude = geo_min.longitude + lng_diff; + if (base_point->latitude >= geo_base.latitude) { + if (base_point->longitude >= geo_base.longitude) { + position = MESH_RIGHT_TOP; + } else { + position = MESH_LEFT_TOP; + } + } else { + if (base_point->longitude >= geo_base.longitude) { + position = MESH_RIGHT_BOTTOM; + } else { + position = MESH_LEFT_BOTTOM; + } + } + /* + base_point: b + geo_min: i + geo_max: a + geo_base: x: must be at the left bottom in the top right mesh. + + e.g.: base_point is at the left bottom mesh case: + +------+------+ + | | a| + | |x | + ^+------+------+ + || | | + lng_diff || b | | + \/i------+------+ + <------> + lat_diff + + grn_min + lat_diff -> the right mesh. + grn_min + lng_diff -> the top mesh. + */ +#ifdef GEO_DEBUG + grn_p_geo_point(ctx, base_point); + printf("base: "); + grn_p_geo_point(ctx, &geo_base); + printf("min: "); + grn_p_geo_point(ctx, &geo_min); + printf("max: "); + grn_p_geo_point(ctx, &geo_max); + printf("diff: %d (%d, %d)\n", diff_bit, lat_diff, lng_diff); + switch (position) { + case MESH_LEFT_TOP : + printf("position: left-top\n"); + break; + case MESH_RIGHT_TOP : + printf("position: right-top\n"); + break; + case MESH_RIGHT_BOTTOM : + printf("position: right-bottom\n"); + break; + case MESH_LEFT_BOTTOM : + printf("position: left-bottom\n"); + break; + } +#endif + + n_meshes = 0; + +#define add_mesh(lat_diff_,lng_diff_,key_size_) do {\ + meshes[n_meshes].key.latitude = geo_base.latitude + (lat_diff_);\ + meshes[n_meshes].key.longitude = geo_base.longitude + (lng_diff_);\ + meshes[n_meshes].key_size = key_size_;\ + n_meshes++;\ +} while (0) + + if (include_base_point_mesh || position != MESH_LEFT_TOP) { + add_mesh(0, -lng_diff, diff_bit); + } + if (include_base_point_mesh || position != MESH_RIGHT_TOP) { + add_mesh(0, 0, diff_bit); + } + if (include_base_point_mesh || position != MESH_RIGHT_BOTTOM) { + add_mesh(-lat_diff, 0, diff_bit); + } + if (include_base_point_mesh || position != MESH_LEFT_BOTTOM) { + add_mesh(-lat_diff, -lng_diff, diff_bit); + } + + /* + b: base_point + x: geo_base + 0-83: sub meshes. 0-83 are added order. + + j: -5 -4 -3 -2 -1 0 1 2 3 4 + +---+---+---+---+---+---+---+---+---+---+ + |74 |75 |76 |77 |78 |79 |80 |81 |82 |83 | 4 + +---+---+---+---+---+---+---+---+---+---+ + |64 |65 |66 |67 |68 |69 |70 |71 |72 |73 | 3 + +---+---+---+---+---+---+---+---+---+---+ + |54 |55 |56 |57 |58 |59 |60 |61 |62 |63 | 2 + +---+---+---+---+---+---+---+---+---+---+ + |48 |49 |50 | b | |51 |52 |53 | 1 + +---+---+---+ | +---+---+---+ + |42 |43 |44 | |x |45 |46 |47 | 0 + +---+---+---+-------+-------+---+---+---+ + |36 |37 |38 | | |39 |40 |41 | -1 + +---+---+---+ base meshes +---+---+---+ + |30 |31 |32 | | |33 |34 |35 | -2 + +---+---+---+---+---+---+---+---+---+---+ + |20 |21 |22 |23 |24 |25 |26 |27 |28 |29 | -3 + +---+---+---+---+---+---+---+---+---+---+ + |10 |11 |12 |13 |14 |15 |16 |17 |18 |19 | -4 + +---+---+---+---+---+---+---+---+---+---+ + | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -5 + +---+---+---+---+---+---+---+---+---+---+ + i + */ + { + int i, j, n_sub_meshes, lat, lat_min, lat_max, lng, lng_min, lng_max; + n_sub_meshes = 0; + for (i = -5; i < 5; i++) { + lat_min = ((lat_diff + 1) / 2) * i; + lat_max = ((lat_diff + 1) / 2) * (i + 1) - 1; + for (j = -5; j < 5; j++) { + if (-3 < i && i < 2 && -3 < j && j < 2) { + continue; + } + lng_min = ((lng_diff + 1) / 2) * j; + lng_max = ((lng_diff + 1) / 2) * (j + 1) - 1; + if (base_point->latitude <= geo_base.latitude + lat_min) { + lat = geo_base.latitude + lat_min; + } else if (geo_base.latitude + lat_max < base_point->latitude) { + lat = geo_base.latitude + lat_max; + } else { + lat = base_point->latitude; + } + if (base_point->longitude <= geo_base.longitude + lng_min) { + lng = geo_base.longitude + lng_min; + } else if (geo_base.longitude + lng_max < base_point->longitude) { + lng = geo_base.longitude + lng_max; + } else { + lng = base_point->longitude; + } + meshes[n_meshes].key.latitude = lat; + meshes[n_meshes].key.longitude = lng; + d = grn_geo_distance_rectangle_raw(ctx, base_point, + &(meshes[n_meshes].key)); + if (d < d_far) { +#ifdef GEO_DEBUG + printf("sub-mesh: %d: (%d,%d): (%d,%d;%d,%d)\n", + n_sub_meshes, base_point->latitude, base_point->longitude, + geo_base.latitude + lat_min, + geo_base.latitude + lat_max, + geo_base.longitude + lng_min, + geo_base.longitude + lng_max); + grn_p_geo_point(ctx, &(meshes[n_meshes].key)); +#endif + meshes[n_meshes].key_size = diff_bit + 2; + n_meshes++; + } + n_sub_meshes++; + } + } + } + +#undef add_mesh + + return n_meshes; +} + +static int +grn_geo_table_sort_collect_points(grn_ctx *ctx, grn_obj *table, grn_obj *index, + grn_pat *pat, + geo_entry *entries, int n_entries, + int n, grn_bool accessorp, + grn_geo_point *base_point, + double d_far, int diff_bit) +{ + int n_meshes; + mesh_entry meshes[86]; + geo_entry *ep, *p; + + n_meshes = grn_geo_get_meshes_for_circle(ctx, base_point, d_far, diff_bit, + GRN_FALSE, meshes); + + ep = entries + n_entries; + while (n_meshes--) { + grn_id tid; + grn_pat_cursor *pc = grn_pat_cursor_open(ctx, pat, + &(meshes[n_meshes].key), + meshes[n_meshes].key_size, + NULL, 0, + 0, -1, + GRN_CURSOR_PREFIX|GRN_CURSOR_SIZE_BY_BIT); + inspect_mesh_entry(ctx, meshes, n_meshes); + if (pc) { + while ((tid = grn_pat_cursor_next(ctx, pc))) { + grn_ii_cursor *ic = grn_ii_cursor_open(ctx, (grn_ii *)index, tid, 0, 0, 1, 0); + if (ic) { + double d; + grn_geo_point pos; + grn_posting *posting; + grn_pat_get_key(ctx, pat, tid, &pos, sizeof(grn_geo_point)); + d = grn_geo_distance_rectangle_raw(ctx, base_point, &pos); + inspect_tid(ctx, tid, &pos, d); + while ((posting = grn_ii_cursor_next(ctx, ic))) { + grn_id rid = accessorp + ? grn_table_get(ctx, table, &posting->rid, sizeof(grn_id)) + : posting->rid; + if (rid) { + for (p = ep; entries < p && p[-1].d > d; p--) { + p->id = p[-1].id; + p->d = p[-1].d; + } + p->id = rid; + p->d = d; + if (n_entries < n) { + ep++; + n_entries++; + } + } + } + grn_ii_cursor_close(ctx, ic); + } + } + grn_pat_cursor_close(ctx, pc); + } + } + return n_entries; +} + +static inline grn_obj * +find_geo_sort_index(grn_ctx *ctx, grn_obj *key) +{ + grn_obj *index = NULL; + + if (GRN_ACCESSORP(key)) { + grn_accessor *accessor = (grn_accessor *)key; + if (accessor->action != GRN_ACCESSOR_GET_KEY) { + return NULL; + } + if (!(DB_OBJ(accessor->obj)->id & GRN_OBJ_TMP_OBJECT)) { + return NULL; + } + if (accessor->obj->header.type != GRN_TABLE_HASH_KEY) { + return NULL; + } + if (!accessor->next) { + return NULL; + } + grn_column_index(ctx, accessor->next->obj, GRN_OP_LESS, &index, 1, NULL); + } else { + grn_column_index(ctx, key, GRN_OP_LESS, &index, 1, NULL); + } + + return index; +} + +static inline int +grn_geo_table_sort_by_distance(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + grn_pat *pat, + grn_pat_cursor *pc, + grn_bool accessorp, + grn_geo_point *base_point, + int offset, + int limit, + grn_obj *result) +{ + int n_entries = 0, e = offset + limit; + geo_entry *entries; + + if ((entries = GRN_MALLOC(sizeof(geo_entry) * (e + 1)))) { + int n, diff_bit; + double d_far; + geo_entry *ep; + grn_bool need_not_indexed_records; + grn_hash *indexed_records = NULL; + + n = grn_geo_table_sort_detect_far_point(ctx, table, index, pat, + entries, pc, e, accessorp, + base_point, + &d_far, &diff_bit); + if (diff_bit > 0) { + n = grn_geo_table_sort_collect_points(ctx, table, index, pat, + entries, n, e, accessorp, + base_point, d_far, diff_bit); + } + need_not_indexed_records = offset + limit > n; + if (need_not_indexed_records) { + indexed_records = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); + } + for (ep = entries + offset; + n_entries < limit && ep < entries + n; + n_entries++, ep++) { + grn_id *sorted_id; + if (!grn_array_add(ctx, (grn_array *)result, (void **)&sorted_id)) { + if (indexed_records) { + grn_hash_close(ctx, indexed_records); + indexed_records = NULL; + } + break; + } + *sorted_id = ep->id; + if (indexed_records) { + grn_hash_add(ctx, indexed_records, &(ep->id), sizeof(grn_id), + NULL, NULL); + } + } + GRN_FREE(entries); + if (indexed_records) { + GRN_TABLE_EACH(ctx, table, GRN_ID_NIL, GRN_ID_MAX, id, NULL, NULL, NULL, { + if (!grn_hash_get(ctx, indexed_records, &id, sizeof(grn_id), NULL)) { + grn_id *sorted_id; + if (grn_array_add(ctx, (grn_array *)result, (void **)&sorted_id)) { + *sorted_id = id; + } + n_entries++; + if (n_entries == limit) { + break; + } + }; + }); + grn_hash_close(ctx, indexed_records); + } + } + + return n_entries; +} + +int +grn_geo_table_sort(grn_ctx *ctx, grn_obj *table, int offset, int limit, + grn_obj *result, grn_obj *column, grn_obj *geo_point) +{ + grn_obj *index; + int i = 0; + + GRN_API_ENTER; + + if (offset < 0 || limit < 0) { + unsigned int size; + grn_rc rc; + size = grn_table_size(ctx, table); + rc = grn_normalize_offset_and_limit(ctx, size, &offset, &limit); + if (rc != GRN_SUCCESS) { + ERR(rc, + "[sort][geo] failed to normalize offset and limit: " + "offset:%d limit:%d table-size:%u", + offset, limit, size); + GRN_API_RETURN(i); + } + } + + if ((index = find_geo_sort_index(ctx, column))) { + grn_id tid; + grn_pat *pat = (grn_pat *)grn_ctx_at(ctx, index->header.domain); + grn_id domain; + grn_pat_cursor *pc; + if (!pat) { + char index_name[GRN_TABLE_MAX_KEY_SIZE]; + int index_name_size; + char lexicon_name[GRN_TABLE_MAX_KEY_SIZE]; + int lexicon_name_size; + index_name_size = grn_obj_name(ctx, + index, + index_name, + GRN_TABLE_MAX_KEY_SIZE); + lexicon_name_size = grn_table_get_key(ctx, + grn_ctx_db(ctx), + index->header.domain, + lexicon_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_OBJECT_CORRUPT, + "[sort][geo] lexicon is broken: <%.*s>: <%.*s>(%d)", + index_name_size, index_name, + lexicon_name_size, lexicon_name, + index->header.domain); + GRN_API_RETURN(i); + } + domain = pat->obj.header.domain; + pc = grn_pat_cursor_open(ctx, pat, NULL, 0, + GRN_BULK_HEAD(geo_point), + GRN_BULK_VSIZE(geo_point), + 0, -1, GRN_CURSOR_PREFIX); + if (pc) { + if (domain != GRN_DB_TOKYO_GEO_POINT && domain != GRN_DB_WGS84_GEO_POINT) { + int e = offset + limit; + while (i < e && (tid = grn_pat_cursor_next(ctx, pc))) { + grn_ii_cursor *ic = grn_ii_cursor_open(ctx, (grn_ii *)index, tid, 0, 0, 1, 0); + if (ic) { + grn_posting *posting; + while (i < e && (posting = grn_ii_cursor_next(ctx, ic))) { + if (offset <= i) { + grn_id *v; + if (!grn_array_add(ctx, (grn_array *)result, (void **)&v)) { break; } + *v = posting->rid; + } + i++; + } + grn_ii_cursor_close(ctx, ic); + } + } + } else { + grn_geo_point *base_point = (grn_geo_point *)GRN_BULK_HEAD(geo_point); + i = grn_geo_table_sort_by_distance(ctx, table, index, pat, + pc, + GRN_ACCESSORP(column), + base_point, + offset, limit, result); + } + grn_pat_cursor_close(ctx, pc); + } + } + GRN_API_RETURN(i); +} + +grn_rc +grn_geo_resolve_approximate_type(grn_ctx *ctx, grn_obj *type_name, + grn_geo_approximate_type *type) +{ + grn_rc rc; + grn_obj approximate_type; + + GRN_TEXT_INIT(&approximate_type, 0); + rc = grn_obj_cast(ctx, type_name, &approximate_type, GRN_FALSE); + if (rc == GRN_SUCCESS) { + const char *name; + unsigned int size; + name = GRN_TEXT_VALUE(&approximate_type); + size = GRN_TEXT_LEN(&approximate_type); + if ((strncmp("rectangle", name, size) == 0) || + (strncmp("rect", name, size) == 0)) { + *type = GRN_GEO_APPROXIMATE_RECTANGLE; + } else if ((strncmp("sphere", name, size) == 0) || + (strncmp("sphr", name, size) == 0)) { + *type = GRN_GEO_APPROXIMATE_SPHERE; + } else if ((strncmp("ellipsoid", name, size) == 0) || + (strncmp("ellip", name, size) == 0)) { + *type = GRN_GEO_APPROXIMATE_ELLIPSOID; + } else { + ERR(GRN_INVALID_ARGUMENT, + "geo distance approximate type must be one of " + "[rectangle, rect, sphere, sphr, ellipsoid, ellip]" + ": <%.*s>", + size, name); + } + } + GRN_OBJ_FIN(ctx, &approximate_type); + + return rc; +} + +typedef double (*grn_geo_distance_raw_func)(grn_ctx *ctx, + grn_geo_point *point1, + grn_geo_point *point2); + +grn_rc +grn_selector_geo_in_circle(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + grn_geo_approximate_type type = GRN_GEO_APPROXIMATE_RECTANGLE; + + if (!(nargs == 4 || nargs == 5)) { + ERR(GRN_INVALID_ARGUMENT, + "geo_in_circle(): requires 3 or 4 arguments but was <%d> arguments", + nargs - 1); + return ctx->rc; + } + + if (!index) { + grn_obj *point_column; + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + point_column = args[1]; + column_name_size = grn_obj_name(ctx, point_column, + column_name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "geo_in_circle(): index for <%.*s> is missing", + column_name_size, column_name); + return ctx->rc; + } + + if (nargs == 5) { + if (grn_geo_resolve_approximate_type(ctx, args[4], &type) != GRN_SUCCESS) { + return ctx->rc; + } + } + + { + grn_obj *center_point, *distance; + center_point = args[2]; + distance = args[3]; + grn_geo_select_in_circle(ctx, index, center_point, distance, type, res, op); + } + + return ctx->rc; +} + +static grn_geo_distance_raw_func +grn_geo_resolve_distance_raw_func (grn_ctx *ctx, + grn_geo_approximate_type approximate_type, + grn_id domain) +{ + grn_geo_distance_raw_func distance_raw_func = NULL; + + switch (approximate_type) { + case GRN_GEO_APPROXIMATE_RECTANGLE : + distance_raw_func = grn_geo_distance_rectangle_raw; + break; + case GRN_GEO_APPROXIMATE_SPHERE : + distance_raw_func = grn_geo_distance_sphere_raw; + break; + case GRN_GEO_APPROXIMATE_ELLIPSOID : + if (domain == GRN_DB_WGS84_GEO_POINT) { + distance_raw_func = grn_geo_distance_ellipsoid_raw_wgs84; + } else { + distance_raw_func = grn_geo_distance_ellipsoid_raw_tokyo; + } + break; + default : + break; + } + + return distance_raw_func; +} + +grn_rc +grn_geo_select_in_circle(grn_ctx *ctx, grn_obj *index, + grn_obj *center_point, grn_obj *distance, + grn_geo_approximate_type approximate_type, + grn_obj *res, grn_operator op) +{ + grn_id domain; + double center_longitude, center_latitude; + double d; + grn_obj *pat, *point_on_circle = NULL, center_point_, point_on_circle_; + grn_geo_point *center, on_circle; + grn_geo_distance_raw_func distance_raw_func; + pat = grn_ctx_at(ctx, index->header.domain); + if (!pat) { + char index_name[GRN_TABLE_MAX_KEY_SIZE]; + int index_name_size; + char lexicon_name[GRN_TABLE_MAX_KEY_SIZE]; + int lexicon_name_size; + index_name_size = grn_obj_name(ctx, + index, + index_name, + GRN_TABLE_MAX_KEY_SIZE); + lexicon_name_size = grn_table_get_key(ctx, + grn_ctx_db(ctx), + index->header.domain, + lexicon_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_OBJECT_CORRUPT, + "geo_in_circle(): lexicon is broken: <%.*s>: <%.*s>(%d)", + index_name_size, index_name, + lexicon_name_size, lexicon_name, + index->header.domain); + goto exit; + } + domain = pat->header.domain; + if (domain != GRN_DB_TOKYO_GEO_POINT && domain != GRN_DB_WGS84_GEO_POINT) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size = 0; + grn_obj *domain_object; + domain_object = grn_ctx_at(ctx, domain); + if (domain_object) { + name_size = grn_obj_name(ctx, domain_object, name, GRN_TABLE_MAX_KEY_SIZE); + grn_obj_unlink(ctx, domain_object); + } else { + grn_strcpy(name, GRN_TABLE_MAX_KEY_SIZE, "(null)"); + name_size = strlen(name); + } + ERR(GRN_INVALID_ARGUMENT, + "geo_in_circle(): index table must be " + "TokyoGeoPoint or WGS84GeoPoint key type table: <%.*s>", + name_size, name); + goto exit; + } + + if (center_point->header.domain != domain) { + GRN_OBJ_INIT(¢er_point_, GRN_BULK, 0, domain); + if (grn_obj_cast(ctx, center_point, ¢er_point_, GRN_FALSE)) { goto exit; } + center_point = ¢er_point_; + } + center = GRN_GEO_POINT_VALUE_RAW(center_point); + center_longitude = GRN_GEO_INT2RAD(center->longitude); + center_latitude = GRN_GEO_INT2RAD(center->latitude); + + distance_raw_func = grn_geo_resolve_distance_raw_func(ctx, + approximate_type, + domain); + if (!distance_raw_func) { + ERR(GRN_INVALID_ARGUMENT, + "unknown approximate type: <%d>", approximate_type); + goto exit; + } + + switch (distance->header.domain) { + case GRN_DB_INT32 : + d = GRN_INT32_VALUE(distance); + on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d / (double)GRN_GEO_RADIUS); + on_circle.longitude = center->longitude; + break; + case GRN_DB_UINT32 : + d = GRN_UINT32_VALUE(distance); + on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d / (double)GRN_GEO_RADIUS); + on_circle.longitude = center->longitude; + break; + case GRN_DB_INT64 : + d = GRN_INT64_VALUE(distance); + on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d / (double)GRN_GEO_RADIUS); + on_circle.longitude = center->longitude; + break; + case GRN_DB_UINT64 : + d = GRN_UINT64_VALUE(distance); + on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d / (double)GRN_GEO_RADIUS); + on_circle.longitude = center->longitude; + break; + case GRN_DB_FLOAT : + d = GRN_FLOAT_VALUE(distance); + on_circle.latitude = center->latitude + GRN_GEO_RAD2INT(d / (double)GRN_GEO_RADIUS); + on_circle.longitude = center->longitude; + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + GRN_OBJ_INIT(&point_on_circle_, GRN_BULK, 0, domain); + if (grn_obj_cast(ctx, distance, &point_on_circle_, GRN_FALSE)) { goto exit; } + point_on_circle = &point_on_circle_; + /* fallthru */ + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + if (!point_on_circle) { + if (domain != distance->header.domain) { /* todo */ goto exit; } + point_on_circle = distance; + } + GRN_GEO_POINT_VALUE(point_on_circle, + on_circle.latitude, on_circle.longitude); + d = distance_raw_func(ctx, center, &on_circle); + if (point_on_circle == &point_on_circle_) { + grn_obj_unlink(ctx, point_on_circle); + } + break; + default : + goto exit; + } + { + int n_meshes, diff_bit; + double d_far; + mesh_entry meshes[87]; + uint8_t geo_key1[sizeof(grn_geo_point)]; + uint8_t geo_key2[sizeof(grn_geo_point)]; + + d_far = grn_geo_distance_rectangle_raw(ctx, center, &on_circle); + grn_gton(geo_key1, center, sizeof(grn_geo_point)); + grn_gton(geo_key2, &on_circle, sizeof(grn_geo_point)); + diff_bit = compute_diff_bit(geo_key1, geo_key2); +#ifdef GEO_DEBUG + printf("center point: "); + grn_p_geo_point(ctx, center); + printf("point on circle: "); + grn_p_geo_point(ctx, &on_circle); + printf("diff: %d\n", diff_bit); +#endif + if ((diff_bit % 2) == 1) { + diff_bit--; + } + n_meshes = grn_geo_get_meshes_for_circle(ctx, center, + d_far, diff_bit, GRN_TRUE, + meshes); + while (n_meshes--) { + grn_table_cursor *tc; + tc = grn_table_cursor_open(ctx, pat, + &(meshes[n_meshes].key), + meshes[n_meshes].key_size, + NULL, 0, + 0, -1, + GRN_CURSOR_PREFIX|GRN_CURSOR_SIZE_BY_BIT); + inspect_mesh_entry(ctx, meshes, n_meshes); + if (tc) { + grn_id tid; + grn_geo_point point; + while ((tid = grn_table_cursor_next(ctx, tc))) { + double point_distance; + grn_table_get_key(ctx, pat, tid, &point, sizeof(grn_geo_point)); + point_distance = distance_raw_func(ctx, &point, center); + if (point_distance <= d) { + inspect_tid(ctx, tid, &point, point_distance); + grn_ii_at(ctx, (grn_ii *)index, tid, (grn_hash *)res, op); + } + } + grn_table_cursor_close(ctx, tc); + } + } + } +exit : + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + return ctx->rc; +} + +grn_rc +grn_selector_geo_in_rectangle(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + if (nargs == 4) { + grn_obj *top_left_point, *bottom_right_point; + top_left_point = args[2]; + bottom_right_point = args[3]; + grn_geo_select_in_rectangle(ctx, index, + top_left_point, bottom_right_point, + res, op); + } else { + ERR(GRN_INVALID_ARGUMENT, + "geo_in_rectangle(): requires 3 arguments but was <%d> arguments", + nargs - 1); + } + return ctx->rc; +} + +static void +in_rectangle_data_fill(grn_ctx *ctx, grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point, + const char *process_name, + in_rectangle_data *data) +{ + grn_id domain; + const char *domain_name; + + data->pat = grn_ctx_at(ctx, index->header.domain); + if (!data->pat) { + char index_name[GRN_TABLE_MAX_KEY_SIZE]; + int index_name_size; + char lexicon_name[GRN_TABLE_MAX_KEY_SIZE]; + int lexicon_name_size; + index_name_size = grn_obj_name(ctx, + index, + index_name, + GRN_TABLE_MAX_KEY_SIZE); + lexicon_name_size = grn_table_get_key(ctx, + grn_ctx_db(ctx), + index->header.domain, + lexicon_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_OBJECT_CORRUPT, + "%s: lexicon lexicon is broken: <%.*s>: <%.*s>(%d)", + process_name, + index_name_size, index_name, + lexicon_name_size, lexicon_name, + index->header.domain); + return; + } + + domain = data->pat->header.domain; + if (domain != GRN_DB_TOKYO_GEO_POINT && domain != GRN_DB_WGS84_GEO_POINT) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size = 0; + grn_obj *domain_object; + domain_object = grn_ctx_at(ctx, domain); + if (domain_object) { + name_size = grn_obj_name(ctx, domain_object, name, GRN_TABLE_MAX_KEY_SIZE); + grn_obj_unlink(ctx, domain_object); + } else { + grn_strcpy(name, GRN_TABLE_MAX_KEY_SIZE, "(null)"); + name_size = strlen(name); + } + ERR(GRN_INVALID_ARGUMENT, + "%s: index table must be " + "TokyoGeoPoint or WGS84GeoPoint key type table: <%.*s>", + process_name, name_size, name); + return; + } + + if (domain == GRN_DB_TOKYO_GEO_POINT) { + domain_name = "TokyoGeoPoint"; + } else { + domain_name = "WGS84GeoPoint"; + } + + if (top_left_point->header.domain != domain) { + grn_obj_reinit(ctx, &(data->top_left_point_buffer), domain, GRN_BULK); + if (grn_obj_cast(ctx, top_left_point, &(data->top_left_point_buffer), + GRN_FALSE)) { + ERR(GRN_INVALID_ARGUMENT, + "%s: failed to cast to %s: <%.*s>", + process_name, domain_name, + (int)GRN_TEXT_LEN(top_left_point), + GRN_TEXT_VALUE(top_left_point)); + return; + } + top_left_point = &(data->top_left_point_buffer); + } + data->top_left = GRN_GEO_POINT_VALUE_RAW(top_left_point); + + if (bottom_right_point->header.domain != domain) { + grn_obj_reinit(ctx, &(data->bottom_right_point_buffer), domain, GRN_BULK); + if (grn_obj_cast(ctx, bottom_right_point, &(data->bottom_right_point_buffer), + GRN_FALSE)) { + ERR(GRN_INVALID_ARGUMENT, + "%s: failed to cast to %s: <%.*s>", + process_name, domain_name, + (int)GRN_TEXT_LEN(bottom_right_point), + GRN_TEXT_VALUE(bottom_right_point)); + return; + } + bottom_right_point = &(data->bottom_right_point_buffer); + } + data->bottom_right = GRN_GEO_POINT_VALUE_RAW(bottom_right_point); +} + +static void +in_rectangle_data_validate(grn_ctx *ctx, + const char *process_name, + in_rectangle_data *data) +{ + grn_geo_point *top_left, *bottom_right; + + top_left = data->top_left; + bottom_right = data->bottom_right; + + if (top_left->latitude >= GRN_GEO_MAX_LATITUDE) { + ERR(GRN_INVALID_ARGUMENT, + "%s: top left point's latitude is too big: " + "<%d>(max:%d): (%d,%d) (%d,%d)", + process_name, + GRN_GEO_MAX_LATITUDE, top_left->latitude, + top_left->latitude, top_left->longitude, + bottom_right->latitude, bottom_right->longitude); + return; + } + + if (top_left->latitude <= GRN_GEO_MIN_LATITUDE) { + ERR(GRN_INVALID_ARGUMENT, + "%s: top left point's latitude is too small: " + "<%d>(min:%d): (%d,%d) (%d,%d)", + process_name, + GRN_GEO_MIN_LATITUDE, top_left->latitude, + top_left->latitude, top_left->longitude, + bottom_right->latitude, bottom_right->longitude); + return; + } + + if (top_left->longitude >= GRN_GEO_MAX_LONGITUDE) { + ERR(GRN_INVALID_ARGUMENT, + "%s: top left point's longitude is too big: " + "<%d>(max:%d): (%d,%d) (%d,%d)", + process_name, + GRN_GEO_MAX_LONGITUDE, top_left->longitude, + top_left->latitude, top_left->longitude, + bottom_right->latitude, bottom_right->longitude); + return; + } + + if (top_left->longitude <= GRN_GEO_MIN_LONGITUDE) { + ERR(GRN_INVALID_ARGUMENT, + "%s: top left point's longitude is too small: " + "<%d>(min:%d): (%d,%d) (%d,%d)", + process_name, + GRN_GEO_MIN_LONGITUDE, top_left->longitude, + top_left->latitude, top_left->longitude, + bottom_right->latitude, bottom_right->longitude); + return; + } + + if (bottom_right->latitude >= GRN_GEO_MAX_LATITUDE) { + ERR(GRN_INVALID_ARGUMENT, + "%s: bottom right point's latitude is too big: " + "<%d>(max:%d): (%d,%d) (%d,%d)", + process_name, + GRN_GEO_MAX_LATITUDE, bottom_right->latitude, + top_left->latitude, top_left->longitude, + bottom_right->latitude, bottom_right->longitude); + return; + } + + if (bottom_right->latitude <= GRN_GEO_MIN_LATITUDE) { + ERR(GRN_INVALID_ARGUMENT, + "%s: bottom right point's latitude is too small: " + "<%d>(min:%d): (%d,%d) (%d,%d)", + process_name, + GRN_GEO_MIN_LATITUDE, bottom_right->latitude, + top_left->latitude, top_left->longitude, + bottom_right->latitude, bottom_right->longitude); + return; + } + + if (bottom_right->longitude >= GRN_GEO_MAX_LONGITUDE) { + ERR(GRN_INVALID_ARGUMENT, + "%s: bottom right point's longitude is too big: " + "<%d>(max:%d): (%d,%d) (%d,%d)", + process_name, + GRN_GEO_MAX_LONGITUDE, bottom_right->longitude, + top_left->latitude, top_left->longitude, + bottom_right->latitude, bottom_right->longitude); + return; + } + + if (bottom_right->longitude <= GRN_GEO_MIN_LONGITUDE) { + ERR(GRN_INVALID_ARGUMENT, + "%s: bottom right point's longitude is too small: " + "<%d>(min:%d): (%d,%d) (%d,%d)", + process_name, + GRN_GEO_MIN_LONGITUDE, bottom_right->longitude, + top_left->latitude, top_left->longitude, + bottom_right->latitude, bottom_right->longitude); + return; + } +} + +static void +in_rectangle_area_data_compute(grn_ctx *ctx, + grn_geo_point *top_left, + grn_geo_point *bottom_right, + in_rectangle_area_data *data) +{ + int latitude_distance, longitude_distance; + int diff_bit; + grn_geo_point base; + grn_geo_point *geo_point_input; + uint8_t geo_key_input[sizeof(grn_geo_point)]; + uint8_t geo_key_base[sizeof(grn_geo_point)]; + uint8_t geo_key_top_left[sizeof(grn_geo_point)]; + uint8_t geo_key_bottom_right[sizeof(grn_geo_point)]; + + latitude_distance = top_left->latitude - bottom_right->latitude; + longitude_distance = bottom_right->longitude - top_left->longitude; + if (latitude_distance > longitude_distance) { + geo_point_input = bottom_right; + base.latitude = bottom_right->latitude; + base.longitude = bottom_right->longitude - longitude_distance; + } else { + geo_point_input = top_left; + base.latitude = top_left->latitude - latitude_distance; + base.longitude = top_left->longitude; + } + grn_gton(geo_key_input, geo_point_input, sizeof(grn_geo_point)); + grn_gton(geo_key_base, &base, sizeof(grn_geo_point)); + diff_bit = compute_diff_bit(geo_key_input, geo_key_base); + compute_min_and_max(&base, diff_bit, &(data->min), &(data->max)); + + grn_gton(geo_key_top_left, top_left, sizeof(grn_geo_point)); + grn_gton(geo_key_bottom_right, bottom_right, sizeof(grn_geo_point)); + data->rectangle_common_bit = + compute_diff_bit(geo_key_top_left, geo_key_bottom_right) - 1; + compute_min_and_max_key(geo_key_top_left, data->rectangle_common_bit + 1, + data->rectangle_common_key, NULL); + +#ifdef GEO_DEBUG + printf("base: "); + grn_p_geo_point(ctx, &base); + printf("min: "); + grn_p_geo_point(ctx, &(data->min)); + printf("max: "); + grn_p_geo_point(ctx, &(data->max)); + printf("top-left: "); + grn_p_geo_point(ctx, top_left); + printf("bottom-right: "); + grn_p_geo_point(ctx, bottom_right); + printf("rectangle-common-bit:%10d\n", data->rectangle_common_bit); + printf("distance(latitude): %10d\n", latitude_distance); + printf("distance(longitude): %10d\n", longitude_distance); +#endif +} + +static grn_rc +in_rectangle_data_prepare(grn_ctx *ctx, grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point, + const char *process_name, + in_rectangle_data *data) +{ + if (!index) { + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "%s: index column is missing", process_name); + goto exit; + } + + in_rectangle_data_fill(ctx, index, top_left_point, bottom_right_point, + process_name, data); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + + in_rectangle_data_validate(ctx, process_name, data); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + +exit : + return ctx->rc; +} + +#define SAME_BIT_P(a, b, n_bit)\ + ((((uint8_t *)(a))[(n_bit) / 8] & (1 << (7 - ((n_bit) % 8)))) ==\ + (((uint8_t *)(b))[(n_bit) / 8] & (1 << (7 - ((n_bit) % 8))))) + +#define CURSOR_ENTRY_UPDATE_STATUS(entry, name, other_key) do {\ + if (SAME_BIT_P((entry)->key, (other_key), (entry)->target_bit)) {\ + (entry)->status_flags |= GRN_GEO_CURSOR_ENTRY_STATUS_ ## name;\ + } else {\ + (entry)->status_flags &= ~GRN_GEO_CURSOR_ENTRY_STATUS_ ## name;\ + }\ +} while (0) + +#define CURSOR_ENTRY_CHECK_STATUS(entry, name)\ + ((entry)->status_flags & GRN_GEO_CURSOR_ENTRY_STATUS_ ## name) +#define CURSOR_ENTRY_IS_INNER(entry)\ + (((entry)->status_flags &\ + (GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER |\ + GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER)) ==\ + (GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER |\ + GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER)) +#define CURSOR_ENTRY_INCLUDED_IN_LATITUDE_DIRECTION(entry)\ + ((entry)->status_flags &\ + (GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER |\ + GRN_GEO_CURSOR_ENTRY_STATUS_TOP_INCLUDED |\ + GRN_GEO_CURSOR_ENTRY_STATUS_BOTTOM_INCLUDED)) +#define CURSOR_ENTRY_INCLUDED_IN_LONGITUDE_DIRECTION(entry)\ + ((entry)->status_flags &\ + (GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER |\ + GRN_GEO_CURSOR_ENTRY_STATUS_LEFT_INCLUDED |\ + GRN_GEO_CURSOR_ENTRY_STATUS_RIGHT_INCLUDED)) + +#define SET_N_BIT(a, n_bit)\ + (((uint8_t *)(a))[((n_bit) / 8)] ^= (1 << (7 - ((n_bit) % 8)))) + +#define N_BIT(a, n_bit)\ + ((((uint8_t *)(a))[((n_bit) / 8)] &\ + (1 << (7 - ((n_bit) % 8)))) >> (1 << (7 - ((n_bit) % 8)))) + +static grn_bool +extract_rectangle_in_area(grn_ctx *ctx, + grn_geo_area_type area_type, + const grn_geo_point *top_left, + const grn_geo_point *bottom_right, + grn_geo_point *area_top_left, + grn_geo_point *area_bottom_right) +{ + grn_bool out_of_area = GRN_FALSE; + grn_bool cover_all_areas = GRN_FALSE; + + if ((GRN_GEO_POINT_IN_NORTH_WEST(top_left) && + GRN_GEO_POINT_IN_SOUTH_EAST(bottom_right)) || + (GRN_GEO_POINT_IN_NORTH_EAST(top_left) && + GRN_GEO_POINT_IN_SOUTH_WEST(bottom_right))) { + cover_all_areas = GRN_TRUE; + } + + switch (area_type) { + case GRN_GEO_AREA_NORTH_EAST : + if (cover_all_areas || + GRN_GEO_POINT_IN_NORTH_EAST(top_left) || + GRN_GEO_POINT_IN_NORTH_EAST(bottom_right)) { + area_top_left->latitude = MAX(top_left->latitude, 0); + area_bottom_right->latitude = MAX(bottom_right->latitude, 0); + if (GRN_GEO_LONGITUDE_IS_WRAPPED(top_left, bottom_right)) { + area_top_left->longitude = top_left->longitude; + area_bottom_right->longitude = GRN_GEO_MAX_LONGITUDE; + } else { + area_top_left->longitude = MAX(top_left->longitude, 0); + area_bottom_right->longitude = MAX(bottom_right->longitude, 0); + } + } else { + out_of_area = GRN_TRUE; + } + break; + case GRN_GEO_AREA_NORTH_WEST : + if (cover_all_areas || + GRN_GEO_POINT_IN_NORTH_WEST(top_left) || + GRN_GEO_POINT_IN_NORTH_WEST(bottom_right)) { + area_top_left->latitude = MAX(top_left->latitude, 0); + area_bottom_right->latitude = MAX(bottom_right->latitude, 0); + if (GRN_GEO_LONGITUDE_IS_WRAPPED(top_left, bottom_right)) { + area_top_left->longitude = GRN_GEO_MIN_LONGITUDE; + area_bottom_right->longitude = bottom_right->longitude; + } else { + area_top_left->longitude = MIN(top_left->longitude, -1); + area_bottom_right->longitude = MIN(bottom_right->longitude, -1); + } + } else { + out_of_area = GRN_TRUE; + } + break; + case GRN_GEO_AREA_SOUTH_WEST : + if (cover_all_areas || + GRN_GEO_POINT_IN_SOUTH_WEST(top_left) || + GRN_GEO_POINT_IN_SOUTH_WEST(bottom_right)) { + area_top_left->latitude = MIN(top_left->latitude, -1); + area_bottom_right->latitude = MIN(bottom_right->latitude, -1); + if (GRN_GEO_LONGITUDE_IS_WRAPPED(top_left, bottom_right)) { + area_top_left->longitude = GRN_GEO_MIN_LONGITUDE; + area_bottom_right->longitude = bottom_right->longitude; + } else { + area_top_left->longitude = MIN(top_left->longitude, -1); + area_bottom_right->longitude = MIN(bottom_right->longitude, -1); + } + } else { + out_of_area = GRN_TRUE; + } + break; + case GRN_GEO_AREA_SOUTH_EAST : + if (cover_all_areas || + GRN_GEO_POINT_IN_SOUTH_EAST(top_left) || + GRN_GEO_POINT_IN_SOUTH_EAST(bottom_right)) { + area_top_left->latitude = MIN(top_left->latitude, -1); + area_bottom_right->latitude = MIN(bottom_right->latitude, -1); + if (GRN_GEO_LONGITUDE_IS_WRAPPED(top_left, bottom_right)) { + area_top_left->longitude = top_left->longitude; + area_bottom_right->longitude = GRN_GEO_MAX_LONGITUDE; + } else { + area_top_left->longitude = MAX(top_left->longitude, 0); + area_bottom_right->longitude = MAX(bottom_right->longitude, 0); + } + } else { + out_of_area = GRN_TRUE; + } + break; + default : + out_of_area = GRN_TRUE; + break; + } + + return out_of_area; +} + +static void +grn_geo_cursor_area_init(grn_ctx *ctx, + grn_geo_cursor_area *area, + grn_geo_area_type area_type, + const grn_geo_point *top_left, + const grn_geo_point *bottom_right) +{ + grn_geo_point area_top_left, area_bottom_right; + in_rectangle_area_data data; + grn_geo_cursor_entry *entry; + grn_bool out_of_area; + + out_of_area = extract_rectangle_in_area(ctx, + area_type, + top_left, + bottom_right, + &area_top_left, + &area_bottom_right); + if (out_of_area) { + area->current_entry = -1; + return; + } + + area->current_entry = 0; + grn_memcpy(&(area->top_left), &area_top_left, sizeof(grn_geo_point)); + grn_memcpy(&(area->bottom_right), &area_bottom_right, sizeof(grn_geo_point)); + grn_gton(area->top_left_key, &area_top_left, sizeof(grn_geo_point)); + grn_gton(area->bottom_right_key, &area_bottom_right, sizeof(grn_geo_point)); + + entry = &(area->entries[area->current_entry]); + in_rectangle_area_data_compute(ctx, + &area_top_left, + &area_bottom_right, + &data); + entry->target_bit = data.rectangle_common_bit; + grn_memcpy(entry->key, data.rectangle_common_key, sizeof(grn_geo_point)); + entry->status_flags = + GRN_GEO_CURSOR_ENTRY_STATUS_TOP_INCLUDED | + GRN_GEO_CURSOR_ENTRY_STATUS_BOTTOM_INCLUDED | + GRN_GEO_CURSOR_ENTRY_STATUS_LEFT_INCLUDED | + GRN_GEO_CURSOR_ENTRY_STATUS_RIGHT_INCLUDED; + if (data.min.latitude == area_bottom_right.latitude && + data.max.latitude == area_top_left.latitude) { + entry->status_flags |= GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER; + } + if (data.min.longitude == area_top_left.longitude && + data.max.longitude == area_bottom_right.longitude) { + entry->status_flags |= GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER; + } +} + +grn_obj * +grn_geo_cursor_open_in_rectangle(grn_ctx *ctx, + grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point, + int offset, + int limit) +{ + grn_geo_cursor_in_rectangle *cursor = NULL; + in_rectangle_data data; + + GRN_API_ENTER; + GRN_VOID_INIT(&(data.top_left_point_buffer)); + GRN_VOID_INIT(&(data.bottom_right_point_buffer)); + if (in_rectangle_data_prepare(ctx, index, top_left_point, bottom_right_point, + "geo_in_rectangle()", &data)) { + goto exit; + } + + cursor = GRN_MALLOCN(grn_geo_cursor_in_rectangle, 1); + if (!cursor) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[geo][cursor][in-rectangle] failed to allocate memory for geo cursor"); + goto exit; + } + + cursor->pat = data.pat; + cursor->index = index; + grn_memcpy(&(cursor->top_left), data.top_left, sizeof(grn_geo_point)); + grn_memcpy(&(cursor->bottom_right), data.bottom_right, sizeof(grn_geo_point)); + cursor->pat_cursor = NULL; + cursor->ii_cursor = NULL; + cursor->offset = offset; + cursor->rest = limit; + + cursor->current_area = GRN_GEO_AREA_NORTH_EAST; + { + grn_geo_area_type area_type; + const grn_geo_point *top_left = &(cursor->top_left); + const grn_geo_point *bottom_right = &(cursor->bottom_right); + for (area_type = GRN_GEO_AREA_NORTH_EAST; + area_type < GRN_GEO_AREA_LAST; + area_type++) { + grn_geo_cursor_area_init(ctx, &(cursor->areas[area_type]), + area_type, top_left, bottom_right); + } + } + { + char minimum_reduce_bit_env[GRN_ENV_BUFFER_SIZE]; + cursor->minimum_reduce_bit = 0; + grn_getenv("GRN_GEO_IN_RECTANGLE_MINIMUM_REDUCE_BIT", + minimum_reduce_bit_env, + GRN_ENV_BUFFER_SIZE); + if (minimum_reduce_bit_env[0]) { + cursor->minimum_reduce_bit = atoi(minimum_reduce_bit_env); + } + if (cursor->minimum_reduce_bit < 1) { + cursor->minimum_reduce_bit = 1; + } + } + GRN_DB_OBJ_SET_TYPE(cursor, GRN_CURSOR_COLUMN_GEO_INDEX); + { + grn_obj *db; + grn_id id; + db = grn_ctx_db(ctx); + id = grn_obj_register(ctx, db, NULL, 0); + DB_OBJ(cursor)->header.domain = GRN_ID_NIL; + DB_OBJ(cursor)->range = GRN_ID_NIL; + grn_db_obj_init(ctx, db, id, DB_OBJ(cursor)); + } + +exit : + grn_obj_unlink(ctx, &(data.top_left_point_buffer)); + grn_obj_unlink(ctx, &(data.bottom_right_point_buffer)); + GRN_API_RETURN((grn_obj *)cursor); +} + +static inline grn_bool +grn_geo_cursor_entry_next_push(grn_ctx *ctx, + grn_geo_cursor_in_rectangle *cursor, + grn_geo_cursor_entry *entry) +{ + grn_geo_cursor_entry *next_entry; + grn_geo_point entry_base; + grn_table_cursor *pat_cursor; + grn_bool pushed = GRN_FALSE; + + grn_ntog((uint8_t*)(&entry_base), entry->key, sizeof(grn_geo_point)); + pat_cursor = grn_table_cursor_open(ctx, + cursor->pat, + &entry_base, + entry->target_bit + 1, + NULL, 0, + 0, -1, + GRN_CURSOR_PREFIX|GRN_CURSOR_SIZE_BY_BIT); + if (pat_cursor) { + if (grn_table_cursor_next(ctx, pat_cursor)) { + grn_geo_cursor_area *area; + area = &(cursor->areas[cursor->current_area]); + next_entry = &(area->entries[++area->current_entry]); + grn_memcpy(next_entry, entry, sizeof(grn_geo_cursor_entry)); + pushed = GRN_TRUE; + } + grn_table_cursor_close(ctx, pat_cursor); + } + + return pushed; +} + +static inline grn_bool +grn_geo_cursor_entry_next(grn_ctx *ctx, + grn_geo_cursor_in_rectangle *cursor, + grn_geo_cursor_entry *entry) +{ + uint8_t *top_left_key; + uint8_t *bottom_right_key; + int max_target_bit = GRN_GEO_KEY_MAX_BITS - cursor->minimum_reduce_bit; + grn_geo_cursor_area *area = NULL; + + while (cursor->current_area < GRN_GEO_AREA_LAST) { + area = &(cursor->areas[cursor->current_area]); + if (area->current_entry >= 0) { + break; + } + cursor->current_area++; + area = NULL; + } + + if (!area) { + return GRN_FALSE; + } + + top_left_key = area->top_left_key; + bottom_right_key = area->bottom_right_key; + grn_memcpy(entry, + &(area->entries[area->current_entry--]), + sizeof(grn_geo_cursor_entry)); + while (GRN_TRUE) { + grn_geo_cursor_entry next_entry0, next_entry1; + grn_bool pushed = GRN_FALSE; + + /* + top_left_key: tl + bottom_right_key: br + + e.g.: top_left_key is at the top left sub mesh and + bottom_right_key is at the bottom right sub mesh. + top_left_key is also at the top left - bottom right + sub-sub mesh and + bottom_right_key is at the bottom right - bottom left + sub-sub mesh. + + ^latitude +----+----+----+----+ + | 1 |1010|1011|1110|1111| + | | | | | | + | 1 +----+----+----+----+ + \/ 0 |1000|1001|1100|1101| + | | tl | | | + +----+----+----+----+ + 1 |0010|0011|0110|0111| + | | | | | + 0 +----+----+----+----+ + 0 |0000|0001|0100|0101| + | | | br | | + +----+----+----+----+ + 0 1 0 1 + |-------| |-------| + 0 1 + <------> + longitude + + entry.target_bit + 1 -> next_entry0 + entry.target_bit + 1 and entry.key ^ (entry.target_bit + 1) in bit + -> next_entry1 + + entry: represents the biggest mesh. + (1010, 1011, 1110, 1111, + 1000, 1001, 1100, 1101, + 0010, 0011, 0110, 0111, + 0000, 0001, 0100, 0101) + next_entry0: represents bottom sub-mesh. + (0010, 0011, 0110, 0111, + 0000, 0001, 0100, 0101) + next_entry1: represents top sub-mesh. + (1010, 1011, 1110, 1111, + 1000, 1001, 1100, 1101) + + entry->status_flags = TOP_INCLUDED | + BOTTOM_INCLUDED | + LEFT_INCLUDED | + RIGHT_INCLUDED + next_entry0->status_flags = BOTTOM_INCLUDED | + LEFT_INCLUDED | + RIGHT_INCLUDED + next_entry1->status_flags = TOP_INCLUDED | + LEFT_INCLUDED | + RIGHT_INCLUDED + + Both next_entry1 and next_entry0 are pushed to the stack in cursor. + */ + +#ifdef GEO_DEBUG + inspect_cursor_entry(ctx, entry); +#endif + + if (entry->target_bit >= max_target_bit) { +#ifdef GEO_DEBUG + printf("%d: force stopping to reduce a mesh\n", entry->target_bit); +#endif + break; + } + + if (CURSOR_ENTRY_IS_INNER(entry)) { +#ifdef GEO_DEBUG + printf("%d: inner entries\n", entry->target_bit); +#endif + break; + } + + grn_memcpy(&next_entry0, entry, sizeof(grn_geo_cursor_entry)); + next_entry0.target_bit++; + grn_memcpy(&next_entry1, entry, sizeof(grn_geo_cursor_entry)); + next_entry1.target_bit++; + SET_N_BIT(next_entry1.key, next_entry1.target_bit); + +#ifdef GEO_DEBUG + inspect_cursor_entry_targets(ctx, entry, top_left_key, bottom_right_key, + &next_entry0, &next_entry1); +#endif + + if ((entry->target_bit + 1) % 2 == 0) { + if (CURSOR_ENTRY_CHECK_STATUS(entry, TOP_INCLUDED)) { + CURSOR_ENTRY_UPDATE_STATUS(&next_entry0, TOP_INCLUDED, top_left_key); + CURSOR_ENTRY_UPDATE_STATUS(&next_entry1, TOP_INCLUDED, top_left_key); + } + if (CURSOR_ENTRY_CHECK_STATUS(entry, BOTTOM_INCLUDED)) { + CURSOR_ENTRY_UPDATE_STATUS(&next_entry0, BOTTOM_INCLUDED, + bottom_right_key); + CURSOR_ENTRY_UPDATE_STATUS(&next_entry1, BOTTOM_INCLUDED, + bottom_right_key); + } + + if (CURSOR_ENTRY_CHECK_STATUS(entry, TOP_INCLUDED) && + !CURSOR_ENTRY_CHECK_STATUS(entry, BOTTOM_INCLUDED) && + CURSOR_ENTRY_CHECK_STATUS(&next_entry1, TOP_INCLUDED)) { + next_entry0.status_flags |= GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER; + } else if (!CURSOR_ENTRY_CHECK_STATUS(entry, TOP_INCLUDED) && + CURSOR_ENTRY_CHECK_STATUS(entry, BOTTOM_INCLUDED) && + CURSOR_ENTRY_CHECK_STATUS(&next_entry0, BOTTOM_INCLUDED)) { + next_entry1.status_flags |= GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER; + } + + if (CURSOR_ENTRY_INCLUDED_IN_LATITUDE_DIRECTION(&next_entry1)) { + if (grn_geo_cursor_entry_next_push(ctx, cursor, &next_entry1)) { + pushed = GRN_TRUE; +#ifdef GEO_DEBUG + printf("%d: latitude: push 1\n", next_entry1.target_bit); +#endif + } + } + if (CURSOR_ENTRY_INCLUDED_IN_LATITUDE_DIRECTION(&next_entry0)) { + if (grn_geo_cursor_entry_next_push(ctx, cursor, &next_entry0)) { + pushed = GRN_TRUE; +#ifdef GEO_DEBUG + printf("%d: latitude: push 0\n", next_entry0.target_bit); +#endif + } + } + } else { + if (CURSOR_ENTRY_CHECK_STATUS(entry, RIGHT_INCLUDED)) { + CURSOR_ENTRY_UPDATE_STATUS(&next_entry0, RIGHT_INCLUDED, + bottom_right_key); + CURSOR_ENTRY_UPDATE_STATUS(&next_entry1, RIGHT_INCLUDED, + bottom_right_key); + } + if (CURSOR_ENTRY_CHECK_STATUS(entry, LEFT_INCLUDED)) { + CURSOR_ENTRY_UPDATE_STATUS(&next_entry0, LEFT_INCLUDED, top_left_key); + CURSOR_ENTRY_UPDATE_STATUS(&next_entry1, LEFT_INCLUDED, top_left_key); + } + + if (CURSOR_ENTRY_CHECK_STATUS(entry, LEFT_INCLUDED) && + !CURSOR_ENTRY_CHECK_STATUS(entry, RIGHT_INCLUDED) && + CURSOR_ENTRY_CHECK_STATUS(&next_entry0, LEFT_INCLUDED)) { + next_entry1.status_flags |= GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER; + } else if (!CURSOR_ENTRY_CHECK_STATUS(entry, LEFT_INCLUDED) && + CURSOR_ENTRY_CHECK_STATUS(entry, RIGHT_INCLUDED) && + CURSOR_ENTRY_CHECK_STATUS(&next_entry1, RIGHT_INCLUDED)) { + next_entry0.status_flags |= GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER; + } + + if (CURSOR_ENTRY_INCLUDED_IN_LONGITUDE_DIRECTION(&next_entry1)) { + if (grn_geo_cursor_entry_next_push(ctx, cursor, &next_entry1)) { + pushed = GRN_TRUE; +#ifdef GEO_DEBUG + printf("%d: longitude: push 1\n", next_entry1.target_bit); +#endif + } + } + if (CURSOR_ENTRY_INCLUDED_IN_LONGITUDE_DIRECTION(&next_entry0)) { + if (grn_geo_cursor_entry_next_push(ctx, cursor, &next_entry0)) { + pushed = GRN_TRUE; +#ifdef GEO_DEBUG + printf("%d: longitude: push 0\n", next_entry0.target_bit); +#endif + } + } + } + + if (pushed) { +#ifdef GEO_DEBUG + int i; + + printf("%d: pushed\n", entry->target_bit); + printf("stack:\n"); + for (i = area->current_entry; i >= 0; i--) { + grn_geo_cursor_entry *stack_entry; + stack_entry = &(area->entries[i]); + printf("%2d: ", i); + inspect_key(ctx, stack_entry->key); + printf(" "); + print_key_mark(ctx, stack_entry->target_bit); + } +#endif + grn_memcpy(entry, + &(area->entries[area->current_entry--]), + sizeof(grn_geo_cursor_entry)); +#ifdef GEO_DEBUG + printf("%d: pop entry\n", entry->target_bit); +#endif + } else { + break; + } + } + +#ifdef GEO_DEBUG + printf("found:\n"); + inspect_cursor_entry(ctx, entry); +#endif + + return GRN_TRUE; +} + +typedef grn_bool (*grn_geo_cursor_callback)(grn_ctx *ctx, grn_posting *posting, void *user_data); + +static void +grn_geo_cursor_each(grn_ctx *ctx, grn_obj *geo_cursor, + grn_geo_cursor_callback callback, void *user_data) +{ + grn_geo_cursor_in_rectangle *cursor; + grn_obj *pat; + grn_table_cursor *pat_cursor; + grn_ii *ii; + grn_ii_cursor *ii_cursor; + grn_posting *posting = NULL; + grn_geo_point *current, *top_left, *bottom_right; + grn_id index_id; + + cursor = (grn_geo_cursor_in_rectangle *)geo_cursor; + if (cursor->rest == 0) { + return; + } + + pat = cursor->pat; + pat_cursor = cursor->pat_cursor; + ii = (grn_ii *)(cursor->index); + ii_cursor = cursor->ii_cursor; + current = &(cursor->current); + top_left = &(cursor->top_left); + bottom_right = &(cursor->bottom_right); + + while (GRN_TRUE) { + if (!pat_cursor) { + grn_geo_cursor_entry entry; + grn_geo_point entry_base; + if (!grn_geo_cursor_entry_next(ctx, cursor, &entry)) { + cursor->rest = 0; + return; + } + grn_ntog((uint8_t*)(&entry_base), entry.key, sizeof(grn_geo_point)); + if (!(cursor->pat_cursor = pat_cursor = + grn_table_cursor_open(ctx, + pat, + &entry_base, + entry.target_bit + 1, + NULL, 0, + 0, -1, + GRN_CURSOR_PREFIX|GRN_CURSOR_SIZE_BY_BIT))) { + cursor->rest = 0; + return; + } +#ifdef GEO_DEBUG + inspect_mesh(ctx, &entry_base, entry.target_bit, 0); +#endif + } + + while (ii_cursor || (index_id = grn_table_cursor_next(ctx, pat_cursor))) { + if (!ii_cursor) { + grn_table_get_key(ctx, pat, index_id, current, sizeof(grn_geo_point)); + if (grn_geo_in_rectangle_raw(ctx, current, top_left, bottom_right)) { + inspect_tid(ctx, index_id, current, 0); + if (!(cursor->ii_cursor = ii_cursor = + grn_ii_cursor_open(ctx, + ii, + index_id, + GRN_ID_NIL, + GRN_ID_MAX, + ii->n_elements, + 0))) { + continue; + } + } else { + continue; + } + } + + while ((posting = grn_ii_cursor_next(ctx, ii_cursor))) { + if (cursor->offset == 0) { + grn_bool keep_each; + keep_each = callback(ctx, posting, user_data); + if (cursor->rest > 0) { + if (--(cursor->rest) == 0) { + keep_each = GRN_FALSE; + } + } + if (!keep_each) { + return; + } + } else { + cursor->offset--; + } + } + grn_ii_cursor_close(ctx, ii_cursor); + cursor->ii_cursor = ii_cursor = NULL; + } + grn_table_cursor_close(ctx, pat_cursor); + cursor->pat_cursor = pat_cursor = NULL; + } +} + +static grn_bool +grn_geo_cursor_next_callback(grn_ctx *ctx, grn_posting *posting, + void *user_data) +{ + grn_posting **return_posting = user_data; + *return_posting = posting; + return GRN_FALSE; +} + +grn_posting * +grn_geo_cursor_next(grn_ctx *ctx, grn_obj *geo_cursor) +{ + grn_posting *posting = NULL; + grn_geo_cursor_each(ctx, geo_cursor, grn_geo_cursor_next_callback, &posting); + return (grn_posting *)posting; +} + +grn_rc +grn_geo_cursor_close(grn_ctx *ctx, grn_obj *geo_cursor) +{ + grn_geo_cursor_in_rectangle *cursor; + + if (!geo_cursor) { return GRN_INVALID_ARGUMENT; } + + cursor = (grn_geo_cursor_in_rectangle *)geo_cursor; + if (cursor->pat) { grn_obj_unlink(ctx, cursor->pat); } + if (cursor->index) { grn_obj_unlink(ctx, cursor->index); } + if (cursor->pat_cursor) { grn_table_cursor_close(ctx, cursor->pat_cursor); } + if (cursor->ii_cursor) { grn_ii_cursor_close(ctx, cursor->ii_cursor); } + GRN_FREE(cursor); + + return GRN_SUCCESS; +} + +typedef struct { + grn_hash *res; + grn_operator op; +} grn_geo_select_in_rectangle_data; + +static grn_bool +grn_geo_select_in_rectangle_callback(grn_ctx *ctx, grn_posting *posting, + void *user_data) +{ + grn_geo_select_in_rectangle_data *data = user_data; + grn_ii_posting_add(ctx, posting, data->res, data->op); + return GRN_TRUE; +} + +grn_rc +grn_geo_select_in_rectangle(grn_ctx *ctx, grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point, + grn_obj *res, grn_operator op) +{ + grn_obj *cursor; + + cursor = grn_geo_cursor_open_in_rectangle(ctx, index, + top_left_point, bottom_right_point, + 0, -1); + if (cursor) { + grn_geo_select_in_rectangle_data data; + data.res = (grn_hash *)res; + data.op = op; + grn_geo_cursor_each(ctx, cursor, grn_geo_select_in_rectangle_callback, + &data); + grn_obj_unlink(ctx, cursor); + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + } + + return ctx->rc; +} + +static grn_rc +geo_point_get(grn_ctx *ctx, grn_obj *pat, int flags, grn_geo_point *geo_point) +{ + grn_rc rc = GRN_SUCCESS; + grn_id id; + grn_table_cursor *cursor = NULL; + + cursor = grn_table_cursor_open(ctx, pat, + NULL, 0, + NULL, 0, + 0, 1, + GRN_CURSOR_BY_KEY | flags); + if (!cursor) { + rc = ctx->rc; + goto exit; + } + + id = grn_table_cursor_next(ctx, cursor); + if (id == GRN_ID_NIL) { + rc = GRN_END_OF_DATA; + } else { + void *key; + int key_size; + key_size = grn_table_cursor_get_key(ctx, cursor, &key); + grn_memcpy(geo_point, key, key_size); + } + +exit: + if (cursor) { + grn_table_cursor_close(ctx, cursor); + } + return rc; +} + +uint32_t +grn_geo_estimate_size_in_rectangle(grn_ctx *ctx, + grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point) +{ + uint32_t n = 0; + int total_records; + grn_rc rc; + in_rectangle_data data; + + GRN_VOID_INIT(&(data.top_left_point_buffer)); + GRN_VOID_INIT(&(data.bottom_right_point_buffer)); + if (in_rectangle_data_prepare(ctx, index, top_left_point, bottom_right_point, + "grn_geo_estimate_in_rectangle()", &data)) { + goto exit; + } + + total_records = grn_table_size(ctx, data.pat); + if (total_records > 0) { + grn_geo_point min, max; + int select_latitude_distance, select_longitude_distance; + int total_latitude_distance, total_longitude_distance; + double select_ratio; + double estimated_n_records; + in_rectangle_area_data area_data; + + rc = geo_point_get(ctx, data.pat, GRN_CURSOR_ASCENDING, &min); + if (!rc) { + rc = geo_point_get(ctx, data.pat, GRN_CURSOR_DESCENDING, &max); + } + if (rc) { + if (rc == GRN_END_OF_DATA) { + n = total_records; + rc = GRN_SUCCESS; + } + goto exit; + } + + in_rectangle_area_data_compute(ctx, + data.top_left, + data.bottom_right, + &area_data); + select_latitude_distance = + abs(area_data.max.latitude - area_data.min.latitude); + select_longitude_distance = + abs(area_data.max.longitude - area_data.min.longitude); + total_latitude_distance = abs(max.latitude - min.latitude); + total_longitude_distance = abs(max.longitude - min.longitude); + + select_ratio = 1.0; + if (select_latitude_distance < total_latitude_distance) { + select_ratio *= ((double)select_latitude_distance / + (double)total_latitude_distance); + } + if (select_longitude_distance < total_longitude_distance) { + select_ratio *= ((double)select_longitude_distance / + (double)total_longitude_distance); + } + estimated_n_records = ceil(total_records * select_ratio); + n = (uint32_t)estimated_n_records; + } + +exit : + grn_obj_unlink(ctx, &(data.top_left_point_buffer)); + grn_obj_unlink(ctx, &(data.bottom_right_point_buffer)); + return n; +} + +int +grn_geo_estimate_in_rectangle(grn_ctx *ctx, + grn_obj *index, + grn_obj *top_left_point, + grn_obj *bottom_right_point) +{ + uint32_t size; + + size = grn_geo_estimate_size_in_rectangle(ctx, + index, + top_left_point, + bottom_right_point); + if (ctx->rc != GRN_SUCCESS) { + return -1; + } + + return size; +} + +grn_bool +grn_geo_in_circle(grn_ctx *ctx, grn_obj *point, grn_obj *center, + grn_obj *radius_or_point, + grn_geo_approximate_type approximate_type) +{ + grn_bool r = GRN_FALSE; + grn_obj center_, radius_or_point_; + grn_id domain = point->header.domain; + if (domain == GRN_DB_TOKYO_GEO_POINT || domain == GRN_DB_WGS84_GEO_POINT) { + grn_geo_distance_raw_func distance_raw_func; + double d; + if (center->header.domain != domain) { + GRN_OBJ_INIT(¢er_, GRN_BULK, 0, domain); + if (grn_obj_cast(ctx, center, ¢er_, GRN_FALSE)) { goto exit; } + center = ¢er_; + } + + distance_raw_func = grn_geo_resolve_distance_raw_func(ctx, + approximate_type, + domain); + if (!distance_raw_func) { + ERR(GRN_INVALID_ARGUMENT, + "unknown approximate type: <%d>", approximate_type); + goto exit; + } + d = distance_raw_func(ctx, + GRN_GEO_POINT_VALUE_RAW(point), + GRN_GEO_POINT_VALUE_RAW(center)); + switch (radius_or_point->header.domain) { + case GRN_DB_INT32 : + r = d <= GRN_INT32_VALUE(radius_or_point); + break; + case GRN_DB_UINT32 : + r = d <= GRN_UINT32_VALUE(radius_or_point); + break; + case GRN_DB_INT64 : + r = d <= GRN_INT64_VALUE(radius_or_point); + break; + case GRN_DB_UINT64 : + r = d <= GRN_UINT64_VALUE(radius_or_point); + break; + case GRN_DB_FLOAT : + r = d <= GRN_FLOAT_VALUE(radius_or_point); + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + GRN_OBJ_INIT(&radius_or_point_, GRN_BULK, 0, domain); + if (grn_obj_cast(ctx, radius_or_point, &radius_or_point_, GRN_FALSE)) { goto exit; } + radius_or_point = &radius_or_point_; + /* fallthru */ + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + if (domain != radius_or_point->header.domain) { /* todo */ goto exit; } + r = d <= distance_raw_func(ctx, + GRN_GEO_POINT_VALUE_RAW(radius_or_point), + GRN_GEO_POINT_VALUE_RAW(center)); + break; + default : + goto exit; + } + } else { + /* todo */ + } +exit : + return r; +} + +grn_bool +grn_geo_in_rectangle_raw(grn_ctx *ctx, grn_geo_point *point, + grn_geo_point *top_left, grn_geo_point *bottom_right) +{ + if (point->latitude > top_left->latitude) { + return GRN_FALSE; + } + if (point->latitude < bottom_right->latitude) { + return GRN_FALSE; + } + + if (GRN_GEO_LONGITUDE_IS_WRAPPED(top_left, bottom_right)) { + if (point->longitude >= top_left->longitude) { + return GRN_TRUE; + } + if (point->longitude <= bottom_right->longitude) { + return GRN_TRUE; + } + return GRN_FALSE; + } else { + if (point->longitude < top_left->longitude) { + return GRN_FALSE; + } + if (point->longitude > bottom_right->longitude) { + return GRN_FALSE; + } + return GRN_TRUE; + } +} + +grn_bool +grn_geo_in_rectangle(grn_ctx *ctx, grn_obj *point, + grn_obj *top_left, grn_obj *bottom_right) +{ + grn_bool r = GRN_FALSE; + grn_obj top_left_, bottom_right_; + grn_id domain = point->header.domain; + if (domain == GRN_DB_TOKYO_GEO_POINT || domain == GRN_DB_WGS84_GEO_POINT) { + if (top_left->header.domain != domain) { + GRN_OBJ_INIT(&top_left_, GRN_BULK, 0, domain); + if (grn_obj_cast(ctx, top_left, &top_left_, GRN_FALSE)) { goto exit; } + top_left = &top_left_; + } + if (bottom_right->header.domain != domain) { + GRN_OBJ_INIT(&bottom_right_, GRN_BULK, 0, domain); + if (grn_obj_cast(ctx, bottom_right, &bottom_right_, GRN_FALSE)) { goto exit; } + bottom_right = &bottom_right_; + } + r = grn_geo_in_rectangle_raw(ctx, + GRN_GEO_POINT_VALUE_RAW(point), + GRN_GEO_POINT_VALUE_RAW(top_left), + GRN_GEO_POINT_VALUE_RAW(bottom_right)); + } else { + /* todo */ + } +exit : + return r; +} + +typedef enum { + LONGITUDE_SHORT, + LONGITUDE_LONG, +} distance_type; + +typedef enum { + QUADRANT_1ST, + QUADRANT_2ND, + QUADRANT_3RD, + QUADRANT_4TH, + QUADRANT_1ST_TO_2ND, + QUADRANT_1ST_TO_3RD, + QUADRANT_1ST_TO_4TH, + QUADRANT_2ND_TO_1ST, + QUADRANT_2ND_TO_3RD, + QUADRANT_2ND_TO_4TH, + QUADRANT_3RD_TO_1ST, + QUADRANT_3RD_TO_2ND, + QUADRANT_3RD_TO_4TH, + QUADRANT_4TH_TO_1ST, + QUADRANT_4TH_TO_2ND, + QUADRANT_4TH_TO_3RD, +} quadrant_type; + +static distance_type +geo_longitude_distance_type(int start_longitude, int end_longitude) +{ + int diff_longitude; + int east_to_west; + int west_to_east; + if (start_longitude >= 0) { + diff_longitude = abs(start_longitude - end_longitude); + } else { + diff_longitude = abs(end_longitude - start_longitude); + } + east_to_west = start_longitude > 0 && end_longitude < 0; + west_to_east = start_longitude < 0 && end_longitude > 0; + if (start_longitude != end_longitude && + (east_to_west || west_to_east) && + diff_longitude > 180 * GRN_GEO_RESOLUTION) { + return LONGITUDE_LONG; + } else { + return LONGITUDE_SHORT; + } +} + +static inline quadrant_type +geo_quadrant_type(grn_geo_point *point1, grn_geo_point *point2) +{ +#define QUADRANT_1ST_WITH_AXIS(point) \ + (point->longitude >= 0) && (point->latitude >= 0) +#define QUADRANT_2ND_WITH_AXIS(point) \ + (point->longitude <= 0) && (point->latitude >= 0) +#define QUADRANT_3RD_WITH_AXIS(point) \ + (point->longitude <= 0) && (point->latitude <= 0) +#define QUADRANT_4TH_WITH_AXIS(point) \ + (point->longitude >= 0) && (point->latitude <= 0) + + if (QUADRANT_1ST_WITH_AXIS(point1) && QUADRANT_1ST_WITH_AXIS(point2)) { + return QUADRANT_1ST; + } else if (QUADRANT_2ND_WITH_AXIS(point1) && QUADRANT_2ND_WITH_AXIS(point2)) { + return QUADRANT_2ND; + } else if (QUADRANT_3RD_WITH_AXIS(point1) && QUADRANT_3RD_WITH_AXIS(point2)) { + return QUADRANT_3RD; + } else if (QUADRANT_4TH_WITH_AXIS(point1) && QUADRANT_4TH_WITH_AXIS(point2)) { + return QUADRANT_4TH; + } else { + if (point1->longitude > 0 && point2->longitude < 0 && + point1->latitude >= 0 && point2->latitude >= 0) { + return QUADRANT_1ST_TO_2ND; + } else if (point1->longitude < 0 && point2->longitude > 0 && + point1->latitude >= 0 && point2->latitude >= 0) { + return QUADRANT_2ND_TO_1ST; + } else if (point1->longitude < 0 && point2->longitude > 0 && + point1->latitude <= 0 && point2->latitude <= 0) { + return QUADRANT_3RD_TO_4TH; + } else if (point1->longitude > 0 && point2->longitude < 0 && + point1->latitude <= 0 && point2->latitude <= 0) { + return QUADRANT_4TH_TO_3RD; + } else if (point1->longitude >= 0 && point2->longitude >= 0 && + point1->latitude > 0 && point2->latitude < 0) { + return QUADRANT_1ST_TO_4TH; + } else if (point1->longitude >= 0 && point2->longitude >= 0 && + point1->latitude < 0 && point2->latitude > 0) { + return QUADRANT_4TH_TO_1ST; + } else if (point1->longitude <= 0 && point2->longitude <= 0 && + point1->latitude > 0 && point2->latitude < 0) { + return QUADRANT_2ND_TO_3RD; + } else if (point1->longitude <= 0 && point2->longitude <= 0 && + point1->latitude < 0 && point2->latitude > 0) { + return QUADRANT_3RD_TO_2ND; + } else if (point1->longitude >= 0 && point2->longitude <= 0 && + point1->latitude > 0 && point2->latitude < 0) { + return QUADRANT_1ST_TO_3RD; + } else if (point1->longitude <= 0 && point2->longitude >= 0 && + point1->latitude < 0 && point2->latitude > 0) { + return QUADRANT_3RD_TO_1ST; + } else if (point1->longitude <= 0 && point2->longitude >= 0 && + point1->latitude > 0 && point2->latitude < 0) { + return QUADRANT_2ND_TO_4TH; + } else if (point1->longitude >= 0 && point2->longitude <= 0 && + point1->latitude < 0 && point2->latitude > 0) { + return QUADRANT_4TH_TO_2ND; + } else { + /* FIXME */ + return QUADRANT_1ST; + } + } +#undef QUADRANT_1ST_WITH_AXIS +#undef QUADRANT_2ND_WITH_AXIS +#undef QUADRANT_3RD_WITH_AXIS +#undef QUADRANT_4TH_WITH_AXIS +} + +static inline double +geo_distance_rectangle_square_root(double start_longitude, double start_latitude, + double end_longitude, double end_latitude) +{ + double diff_longitude; + double x, y; + + diff_longitude = end_longitude - start_longitude; + x = diff_longitude * cos((start_latitude + end_latitude) * 0.5); + y = end_latitude - start_latitude; + return sqrt((x * x) + (y * y)); +} + +static inline double +geo_distance_rectangle_short_dist_type(quadrant_type quad_type, + double lng1, double lat1, + double lng2, double lat2) +{ + double distance; + double longitude_delta, latitude_delta; + + if (quad_type == QUADRANT_1ST_TO_4TH || + quad_type == QUADRANT_4TH_TO_1ST || + quad_type == QUADRANT_2ND_TO_3RD || + quad_type == QUADRANT_3RD_TO_2ND) { + longitude_delta = lng2 - lng1; + if (longitude_delta > 0 || longitude_delta < 0) { + if (lat2 > lat1) { + distance = geo_distance_rectangle_square_root(lng1, + lat1, + lng2, + lat2) * GRN_GEO_RADIUS; + } else { + distance = geo_distance_rectangle_square_root(lng2, + lat2, + lng1, + lat1) * GRN_GEO_RADIUS; + } + } else { + latitude_delta = fabs(lat1) + fabs(lat2); + distance = sqrt(latitude_delta * latitude_delta) * GRN_GEO_RADIUS; + } + } else if (quad_type == QUADRANT_1ST_TO_3RD || + quad_type == QUADRANT_2ND_TO_4TH) { + distance = geo_distance_rectangle_square_root(lng1, + lat1, + lng2, + lat2) * GRN_GEO_RADIUS; + } else if (quad_type == QUADRANT_3RD_TO_1ST || + quad_type == QUADRANT_4TH_TO_2ND) { + distance = geo_distance_rectangle_square_root(lng2, + lat2, + lng1, + lat1) * GRN_GEO_RADIUS; + } else if (quad_type == QUADRANT_1ST_TO_2ND || + quad_type == QUADRANT_2ND_TO_1ST || + quad_type == QUADRANT_3RD_TO_4TH || + quad_type == QUADRANT_4TH_TO_3RD) { + if (lat2 > lat1) { + distance = geo_distance_rectangle_square_root(lng1, + lat1, + lng2, + lat2) * GRN_GEO_RADIUS; + } else if (lat2 < lat1) { + distance = geo_distance_rectangle_square_root(lng2, + lat2, + lng1, + lat1) * GRN_GEO_RADIUS; + } else { + longitude_delta = lng2 - lng1; + distance = longitude_delta * cos(lat1); + distance = sqrt(distance * distance) * GRN_GEO_RADIUS; + } + } else { + distance = geo_distance_rectangle_square_root(lng1, + lat1, + lng2, + lat2) * GRN_GEO_RADIUS; + } + return distance; +} + +static inline double +geo_distance_rectangle_long_dist_type(quadrant_type quad_type, + double lng1, double lat1, + double lng2, double lat2) +{ +#define M_2PI 6.28318530717958647692 + + double distance; + + if (quad_type == QUADRANT_1ST_TO_2ND || + quad_type == QUADRANT_4TH_TO_3RD) { + if (lat1 > lat2) { + distance = geo_distance_rectangle_square_root(lng2 + M_2PI, + lat2, + lng1, + lat1) * GRN_GEO_RADIUS; + } else { + distance = geo_distance_rectangle_square_root(lng1, + lat1, + lng2 + M_2PI, + lat2) * GRN_GEO_RADIUS; + } + } else if (quad_type == QUADRANT_2ND_TO_1ST || + quad_type == QUADRANT_3RD_TO_4TH) { + if (lat1 > lat2) { + distance = geo_distance_rectangle_square_root(lng2, + lat2, + lng1 + M_2PI, + lat1) * GRN_GEO_RADIUS; + } else { + distance = geo_distance_rectangle_square_root(lng1 + M_2PI, + lat1, + lng2, + lat2) * GRN_GEO_RADIUS; + } + } else if (quad_type == QUADRANT_1ST_TO_3RD) { + distance = geo_distance_rectangle_square_root(lng2 + M_2PI, + lat2, + lng1, + lat1) * GRN_GEO_RADIUS; + } else if (quad_type == QUADRANT_3RD_TO_1ST) { + distance = geo_distance_rectangle_square_root(lng1 + M_2PI, + lat1, + lng2, + lat2) * GRN_GEO_RADIUS; + } else if (quad_type == QUADRANT_2ND_TO_4TH) { + distance = geo_distance_rectangle_square_root(lng2, + lat2, + lng1 + M_2PI, + lat1) * GRN_GEO_RADIUS; + } else if (quad_type == QUADRANT_4TH_TO_2ND) { + distance = geo_distance_rectangle_square_root(lng1, + lat1, + lng2 + M_2PI, + lat2) * GRN_GEO_RADIUS; + } else { + if (lng1 > lng2) { + distance = geo_distance_rectangle_square_root(lng1, + lat1, + lng2 + M_2PI, + lat2) * GRN_GEO_RADIUS; + } else { + distance = geo_distance_rectangle_square_root(lng2, + lat2, + lng1 + M_2PI, + lat1) * GRN_GEO_RADIUS; + } + } + return distance; +#undef M_2PI +} + +double +grn_geo_distance_rectangle_raw(grn_ctx *ctx, + grn_geo_point *point1, grn_geo_point *point2) +{ + + double lng1, lat1, lng2, lat2, distance; + distance_type dist_type; + quadrant_type quad_type; + + lat1 = GRN_GEO_INT2RAD(point1->latitude); + lng1 = GRN_GEO_INT2RAD(point1->longitude); + lat2 = GRN_GEO_INT2RAD(point2->latitude); + lng2 = GRN_GEO_INT2RAD(point2->longitude); + quad_type = geo_quadrant_type(point1, point2); + if (quad_type <= QUADRANT_4TH) { + distance = geo_distance_rectangle_square_root(lng1, + lat1, + lng2, + lat2) * GRN_GEO_RADIUS; + } else { + dist_type = geo_longitude_distance_type(point1->longitude, + point2->longitude); + if (dist_type == LONGITUDE_SHORT) { + distance = geo_distance_rectangle_short_dist_type(quad_type, + lng1, lat1, + lng2, lat2); + } else { + distance = geo_distance_rectangle_long_dist_type(quad_type, + lng1, lat1, + lng2, lat2); + } + } + return distance; +} + +double +grn_geo_distance_sphere_raw(grn_ctx *ctx, + grn_geo_point *point1, grn_geo_point *point2) +{ + double lng1, lat1, lng2, lat2, x, y; + + lat1 = GRN_GEO_INT2RAD(point1->latitude); + lng1 = GRN_GEO_INT2RAD(point1->longitude); + lat2 = GRN_GEO_INT2RAD(point2->latitude); + lng2 = GRN_GEO_INT2RAD(point2->longitude); + x = sin(fabs(lng2 - lng1) * 0.5); + y = sin(fabs(lat2 - lat1) * 0.5); + return asin(sqrt((y * y) + cos(lat1) * cos(lat2) * x * x)) * 2 * GRN_GEO_RADIUS; +} + +double +grn_geo_distance_ellipsoid_raw(grn_ctx *ctx, + grn_geo_point *point1, grn_geo_point *point2, + int c1, int c2, double c3) +{ + double lng1, lat1, lng2, lat2, p, q, r, m, n, x, y; + + lat1 = GRN_GEO_INT2RAD(point1->latitude); + lng1 = GRN_GEO_INT2RAD(point1->longitude); + lat2 = GRN_GEO_INT2RAD(point2->latitude); + lng2 = GRN_GEO_INT2RAD(point2->longitude); + p = (lat1 + lat2) * 0.5; + q = (1 - c3 * sin(p) * sin(p)); + r = sqrt(q); + m = c1 / (q * r); + n = c2 / r; + x = n * cos(p) * fabs(lng1 - lng2); + y = m * fabs(lat1 - lat2); + return sqrt((x * x) + (y * y)); +} + +double +grn_geo_distance_ellipsoid_raw_tokyo(grn_ctx *ctx, + grn_geo_point *point1, + grn_geo_point *point2) +{ + return grn_geo_distance_ellipsoid_raw(ctx, point1, point2, + GRN_GEO_BES_C1, + GRN_GEO_BES_C2, + GRN_GEO_BES_C3); +} + +double +grn_geo_distance_ellipsoid_raw_wgs84(grn_ctx *ctx, + grn_geo_point *point1, + grn_geo_point *point2) +{ + return grn_geo_distance_ellipsoid_raw(ctx, point1, point2, + GRN_GEO_GRS_C1, + GRN_GEO_GRS_C2, + GRN_GEO_GRS_C3); +} + +double +grn_geo_distance(grn_ctx *ctx, grn_obj *point1, grn_obj *point2, + grn_geo_approximate_type type) +{ + double d = 0.0; + + switch (type) { + case GRN_GEO_APPROXIMATE_RECTANGLE : + d = grn_geo_distance_rectangle(ctx, point1, point2); + break; + case GRN_GEO_APPROXIMATE_SPHERE : + d = grn_geo_distance_sphere(ctx, point1, point2); + break; + case GRN_GEO_APPROXIMATE_ELLIPSOID : + d = grn_geo_distance_ellipsoid(ctx, point1, point2); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "unknown approximate type: <%d>", type); + break; + } + return d; +} + +double +grn_geo_distance_rectangle(grn_ctx *ctx, grn_obj *point1, grn_obj *point2) +{ + double d = 0; + grn_bool point1_initialized = GRN_FALSE; + grn_bool point2_initialized = GRN_FALSE; + grn_obj point1_, point2_; + grn_id domain1 = point1->header.domain; + grn_id domain2 = point2->header.domain; + if (domain1 == GRN_DB_TOKYO_GEO_POINT || domain1 == GRN_DB_WGS84_GEO_POINT) { + if (domain1 != domain2) { + GRN_OBJ_INIT(&point2_, GRN_BULK, 0, domain1); + point2_initialized = GRN_TRUE; + if (grn_obj_cast(ctx, point2, &point2_, GRN_FALSE)) { goto exit; } + point2 = &point2_; + } + } else if (domain2 == GRN_DB_TOKYO_GEO_POINT || + domain2 == GRN_DB_WGS84_GEO_POINT) { + GRN_OBJ_INIT(&point1_, GRN_BULK, 0, domain2); + point1_initialized = GRN_TRUE; + if (grn_obj_cast(ctx, point1, &point1_, GRN_FALSE)) { goto exit; } + point1 = &point1_; + } else if ((GRN_DB_SHORT_TEXT <= domain1 && domain1 <= GRN_DB_LONG_TEXT) && + (GRN_DB_SHORT_TEXT <= domain2 && domain2 <= GRN_DB_LONG_TEXT)) { + GRN_OBJ_INIT(&point1_, GRN_BULK, 0, GRN_DB_WGS84_GEO_POINT); + point1_initialized = GRN_TRUE; + if (grn_obj_cast(ctx, point1, &point1_, GRN_FALSE)) { goto exit; } + point1 = &point1_; + + GRN_OBJ_INIT(&point2_, GRN_BULK, 0, GRN_DB_WGS84_GEO_POINT); + point2_initialized = GRN_TRUE; + if (grn_obj_cast(ctx, point2, &point2_, GRN_FALSE)) { goto exit; } + point2 = &point2_; + } else { + goto exit; + } + d = grn_geo_distance_rectangle_raw(ctx, + GRN_GEO_POINT_VALUE_RAW(point1), + GRN_GEO_POINT_VALUE_RAW(point2)); +exit : + if (point1_initialized) { + GRN_OBJ_FIN(ctx, &point1_); + } + if (point2_initialized) { + GRN_OBJ_FIN(ctx, &point2_); + } + return d; +} + +double +grn_geo_distance_sphere(grn_ctx *ctx, grn_obj *point1, grn_obj *point2) +{ + double d = 0; + grn_bool point2_initialized = GRN_FALSE; + grn_obj point2_; + grn_id domain = point1->header.domain; + if (domain == GRN_DB_TOKYO_GEO_POINT || domain == GRN_DB_WGS84_GEO_POINT) { + if (point2->header.domain != domain) { + GRN_OBJ_INIT(&point2_, GRN_BULK, 0, domain); + point2_initialized = GRN_TRUE; + if (grn_obj_cast(ctx, point2, &point2_, GRN_FALSE)) { goto exit; } + point2 = &point2_; + } + d = grn_geo_distance_sphere_raw(ctx, + GRN_GEO_POINT_VALUE_RAW(point1), + GRN_GEO_POINT_VALUE_RAW(point2)); + } else { + /* todo */ + } +exit : + if (point2_initialized) { + GRN_OBJ_FIN(ctx, &point2_); + } + return d; +} + +double +grn_geo_distance_ellipsoid(grn_ctx *ctx, grn_obj *point1, grn_obj *point2) +{ + double d = 0; + grn_bool point2_initialized = GRN_FALSE; + grn_obj point2_; + grn_id domain = point1->header.domain; + if (domain == GRN_DB_TOKYO_GEO_POINT || domain == GRN_DB_WGS84_GEO_POINT) { + if (point2->header.domain != domain) { + GRN_OBJ_INIT(&point2_, GRN_BULK, 0, domain); + point2_initialized = GRN_TRUE; + if (grn_obj_cast(ctx, point2, &point2_, GRN_FALSE)) { goto exit; } + point2 = &point2_; + } + if (domain == GRN_DB_TOKYO_GEO_POINT) { + d = grn_geo_distance_ellipsoid_raw_tokyo(ctx, + GRN_GEO_POINT_VALUE_RAW(point1), + GRN_GEO_POINT_VALUE_RAW(point2)); + } else { + d = grn_geo_distance_ellipsoid_raw_wgs84(ctx, + GRN_GEO_POINT_VALUE_RAW(point1), + GRN_GEO_POINT_VALUE_RAW(point2)); + } + } else { + /* todo */ + } +exit : + if (point2_initialized) { + GRN_OBJ_FIN(ctx, &point2_); + } + return d; +} diff --git a/storage/mroonga/vendor/groonga/lib/grn.h b/storage/mroonga/vendor/groonga/lib/grn.h new file mode 100644 index 00000000..17a8c4e6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn.h @@ -0,0 +1,759 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#ifdef HAVE_CONFIG_H +# include +#endif /* HAVE_CONFIG_H */ + +#ifdef WIN32 +# ifdef __GNUC__ +# define __MINGW_MSVC_COMPAT_WARNINGS +# endif /* __GNUC__ */ + +# ifdef __GNUC__ +# include +# define GRN_MINIMUM_WINDOWS_VERSION WindowsVista +# else /* __GNUC__ */ +# define GRN_MINIMUM_WINDOWS_VERSION 0x0600 /* Vista */ +# endif /* __GNUC__ */ + +# ifdef WINVER +# undef WINVER +# endif /* WINVER */ +# define WINVER GRN_MINIMUM_WINDOWS_VERSION +# ifdef _WIN32_WINNT +# undef _WIN32_WINNT +# endif /* _WIN32_WINNT */ +# define _WIN32_WINNT GRN_MINIMUM_WINDOWS_VERSION +# ifdef NTDDI_VERSION +# undef NTDDI_VERSION +# endif /* NTDDI_VERSION */ +# define NTDDI_VERSION GRN_MINIMUM_WINDOWS_VERSION + +# ifdef WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +# endif /* WIN32_LEAN_AND_MEAN */ +#endif /* WIN32 */ + +#ifdef __cplusplus +# define __STDC_LIMIT_MACROS +#endif + +#include +#include + +#include + +#ifdef HAVE_SYS_PARAM_H +# include +#endif /* HAVE_SYS_PARAM_H */ + +#ifdef HAVE_SYS_MMAN_H +# include +#endif /* HAVE_SYS_MMAN_H */ + +#ifdef HAVE_SYS_TIME_H +# include +#endif /* HAVE_SYS_TIME_H */ + +#ifdef HAVE_SYS_RESOURCE_H +# include +#endif /* HAVE_SYS_RESOURCE_H */ + +#ifdef WIN32 +# define GRN_API __declspec(dllexport) +# ifdef GROONGA_MAIN +# define GRN_VAR __declspec(dllimport) +# else +# define GRN_VAR __declspec(dllexport) extern +# endif /* GROONGA_MAIN */ +#else +# define GRN_API +# define GRN_VAR extern +#endif + +#ifdef WIN32 +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include + +# ifndef __GNUC__ +# define PATH_MAX (MAX_PATH - 1) +# ifndef __cplusplus +# define inline _inline +# endif +# endif + +# ifndef __GNUC__ +typedef SSIZE_T ssize_t; +typedef int pid_t; +typedef int64_t off64_t; +# endif + +# undef MSG_WAITALL +# define MSG_WAITALL 0 /* before Vista, not supported... */ +# define SHUT_RDWR SD_BOTH + +typedef SOCKET grn_sock; +# define grn_sock_close(sock) closesocket(sock) + +# define CALLBACK __stdcall + +# ifndef __GNUC__ +# include +# include +# include +# endif + +#else /* WIN32 */ + +# define GROONGA_API + +# ifdef HAVE_UNISTD_H +# include +# endif /* HAVE_UNISTD_H */ + +# ifndef __off64_t_defined +typedef off_t off64_t; +# endif + +# ifndef PATH_MAX +# if defined(MAXPATHLEN) +# define PATH_MAX MAXPATHLEN +# else /* MAXPATHLEN */ +# define PATH_MAX 1024 +# endif /* MAXPATHLEN */ +# endif /* PATH_MAX */ +# ifndef INT_LEAST8_MAX +typedef char int_least8_t; +# endif /* INT_LEAST8_MAX */ +# ifndef UINT_LEAST8_MAX +typedef unsigned char uint_least8_t; +# endif /* UINT_LEAST8_MAX */ +typedef int grn_sock; +# define grn_sock_close(sock) close(sock) +# define CALLBACK + +#endif /* WIN32 */ + +#ifndef INT8_MAX +# define INT8_MAX (127) +#endif /* INT8_MAX */ + +#ifndef INT8_MIN +# define INT8_MIN (-128) +#endif /* INT8_MIN */ + +#ifndef INT16_MAX +# define INT16_MAX (32767) +#endif /* INT16_MAX */ + +#ifndef INT16_MIN +# define INT16_MIN (-32768) +#endif /* INT16_MIN */ + +#ifndef INT32_MAX +# define INT32_MAX (2147483647) +#endif /* INT32_MAX */ + +#ifndef INT32_MIN +# define INT32_MIN (-2147483648) +#endif /* INT32_MIN */ + +#ifndef UINT32_MAX +# define UINT32_MAX (4294967295) +#endif /* UINT32_MAX */ + +#ifndef INT64_MAX +# define INT64_MAX (9223372036854775807) +#endif /* INT64_MAX */ + +#ifndef INT64_MIN +# define INT64_MIN (-9223372036854775808) +#endif /* INT64_MIN */ + + +#ifdef WIN32 +# define grn_lseek(fd, offset, whence) _lseeki64(fd, offset, whence) +#else /* WIN32 */ +# define grn_lseek(fd, offset, whence) lseek(fd, offset, whence) +#endif /* WIN32 */ + + +#ifdef HAVE_PTHREAD_H +# include +typedef pthread_t grn_thread; +typedef void * grn_thread_func_result; +# define GRN_THREAD_FUNC_RETURN_VALUE NULL +# define THREAD_CREATE(thread,func,arg) \ + (pthread_create(&(thread), NULL, (func), (arg))) +# define THREAD_JOIN(thread) (pthread_join(thread, NULL)) +typedef pthread_mutex_t grn_mutex; +# define MUTEX_INIT(m) pthread_mutex_init(&m, NULL) +# define MUTEX_LOCK(m) pthread_mutex_lock(&m) +# define MUTEX_LOCK_CHECK(m) (MUTEX_LOCK(m) == 0) +# define MUTEX_UNLOCK(m) pthread_mutex_unlock(&m) +# define MUTEX_FIN(m) pthread_mutex_destroy(&m) +# ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED +# define MUTEX_INIT_SHARED(m) do {\ + pthread_mutexattr_t mutexattr;\ + pthread_mutexattr_init(&mutexattr);\ + pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED);\ + pthread_mutex_init(&m, &mutexattr);\ +} while (0) +# else +# define MUTEX_INIT_SHARED MUTEX_INIT +# endif /* HAVE_PTHREAD_MUTEXATTR_SETPSHARED */ + +typedef pthread_mutex_t grn_critical_section; +# define CRITICAL_SECTION_INIT(cs) pthread_mutex_init(&(cs), NULL) +# define CRITICAL_SECTION_ENTER(cs) pthread_mutex_lock(&(cs)) +# define CRITICAL_SECTION_LEAVE(cs) pthread_mutex_unlock(&(cs)) +# define CRITICAL_SECTION_FIN(cs) + +typedef pthread_cond_t grn_cond; +# define COND_INIT(c) pthread_cond_init(&c, NULL) +# define COND_SIGNAL(c) pthread_cond_signal(&c) +# define COND_WAIT(c,m) pthread_cond_wait(&c, &m) +# define COND_BROADCAST(c) pthread_cond_broadcast(&c) +# ifdef HAVE_PTHREAD_CONDATTR_SETPSHARED +# define COND_INIT_SHARED(c) do {\ + pthread_condattr_t condattr;\ + pthread_condattr_init(&condattr);\ + pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED);\ + pthread_cond_init(&c, &condattr);\ +} while (0) +# else +# define COND_INIT_SHARED COND_INIT +# endif /* HAVE_PTHREAD_CONDATTR_SETPSHARE */ +# define COND_FIN(c) pthread_cond_destroy(&c) + +typedef pthread_key_t grn_thread_key; +# define THREAD_KEY_CREATE(key, destr) pthread_key_create(key, destr) +# define THREAD_KEY_DELETE(key) pthread_key_delete(key) +# define THREAD_SETSPECIFIC(key, value) pthread_setspecific(key, value) +# define THREAD_GETSPECIFIC(key) pthread_getspecific(key) + +#if defined(USE_UYIELD) + extern int grn_uyield_count; + #define GRN_TEST_YIELD() do {\ + if (((++grn_uyield_count) & (0x20 - 1)) == 0) {\ + sched_yield();\ + if (grn_uyield_count > 0x1000) {\ + grn_uyield_count = (uint32_t)time(NULL) % 0x1000;\ + }\ + }\ + } while (0) + + #undef assert + #define assert(assert_expr) do {\ + if (!(assert_expr)){\ + fprintf(stderr, "assertion failed: %s\n", #assert_expr);\ + abort();\ + }\ + GRN_TEST_YIELD();\ + } while (0) + + #define if (if_cond) \ + if ((((++grn_uyield_count) & (0x100 - 1)) != 0 || (sched_yield() * 0) == 0) && (if_cond)) + #define while(while_cond) \ + while ((((++grn_uyield_count) & (0x100 - 1)) != 0 || (sched_yield() * 0) == 0) && (while_cond)) + + #if !defined(_POSIX_PRIORITY_SCHEDULING) + #define sched_yield() grn_nanosleep(1000000 * 20) + #endif +# else /* USE_UYIELD */ + #define GRN_TEST_YIELD() do {} while (0) +# endif /* USE_UYIELD */ + +#else /* HAVE_PTHREAD_H */ + +/* todo */ +typedef int grn_thread_key; +# define THREAD_KEY_CREATE(key,destr) +# define THREAD_KEY_DELETE(key) +# define THREAD_SETSPECIFIC(key) +# define THREAD_GETSPECIFIC(key,value) + +# ifdef WIN32 +typedef uintptr_t grn_thread; +typedef unsigned int grn_thread_func_result; +# define GRN_THREAD_FUNC_RETURN_VALUE 0 +# define THREAD_CREATE(thread,func,arg) \ + (((thread)=_beginthreadex(NULL, 0, (func), (arg), 0, NULL)) == (grn_thread)0) +# define THREAD_JOIN(thread) \ + (WaitForSingleObject((HANDLE)(thread), INFINITE) == WAIT_FAILED) +typedef HANDLE grn_mutex; +# define MUTEX_INIT(m) ((m) = CreateMutex(0, FALSE, NULL)) +# define MUTEX_LOCK(m) WaitForSingleObject((m), INFINITE) +# define MUTEX_LOCK_CHECK(m) (MUTEX_LOCK(m) == WAIT_OBJECT_0) +# define MUTEX_UNLOCK(m) ReleaseMutex(m) +# define MUTEX_FIN(m) CloseHandle(m) +typedef CRITICAL_SECTION grn_critical_section; +# define CRITICAL_SECTION_INIT(cs) InitializeCriticalSection(&(cs)) +# define CRITICAL_SECTION_ENTER(cs) EnterCriticalSection(&(cs)) +# define CRITICAL_SECTION_LEAVE(cs) LeaveCriticalSection(&(cs)) +# define CRITICAL_SECTION_FIN(cs) DeleteCriticalSection(&(cs)) + +typedef struct +{ + int waiters_count_; + HANDLE waiters_count_lock_; + HANDLE sema_; + HANDLE waiters_done_; + size_t was_broadcast_; +} grn_cond; + +# define COND_INIT(c) do { \ + (c).waiters_count_ = 0; \ + (c).sema_ = CreateSemaphore(NULL, 0, 0x7fffffff, NULL); \ + MUTEX_INIT((c).waiters_count_lock_); \ + (c).waiters_done_ = CreateEvent(NULL, FALSE, FALSE, NULL); \ +} while (0) + +# define COND_SIGNAL(c) do { \ + MUTEX_LOCK((c).waiters_count_lock_); \ + { \ + int have_waiters = (c).waiters_count_ > 0; \ + MUTEX_UNLOCK((c).waiters_count_lock_); \ + if (have_waiters) { \ + ReleaseSemaphore((c).sema_, 1, 0); \ + } \ + } \ +} while (0) + +# define COND_BROADCAST(c) do { \ + MUTEX_LOCK((c).waiters_count_lock_); \ + { \ + int have_waiters = (c).waiters_count_ > 0; \ + if ((c).waiters_count_ > 0) { \ + (c).was_broadcast_ = 1; \ + have_waiters = 1; \ + } \ + if (have_waiters) { \ + ReleaseSemaphore((c).sema_, (c).waiters_count_, 0); \ + MUTEX_UNLOCK((c).waiters_count_lock_); \ + WaitForSingleObject((c).waiters_done_, INFINITE); \ + (c).was_broadcast_ = 0; \ + } \ + else { \ + MUTEX_UNLOCK((c).waiters_count_lock_); \ + } \ + } \ +} while (0) + +# define COND_WAIT(c,m) do { \ + MUTEX_LOCK((c).waiters_count_lock_); \ + (c).waiters_count_++; \ + MUTEX_UNLOCK((c).waiters_count_lock_); \ + SignalObjectAndWait((m), (c).sema_, INFINITE, FALSE); \ + MUTEX_LOCK((c).waiters_count_lock_); \ + (c).waiters_count_--; \ + { \ + int last_waiter = (c).was_broadcast_ && (c).waiters_count_ == 0; \ + MUTEX_UNLOCK((c).waiters_count_lock_); \ + if (last_waiter) { \ + SignalObjectAndWait((c).waiters_done_, (m), INFINITE, FALSE); \ + } \ + else { \ + WaitForSingleObject((m), FALSE); \ + } \ + } \ +} while (0) + +# define COND_FIN(c) do { \ + CloseHandle((c).waiters_done_); \ + MUTEX_FIN((c).waiters_count_lock_); \ + CloseHandle((c).sema_); \ +} while (0) + +# else /* WIN32 */ +/* todo */ +typedef int grn_cond; +# define COND_INIT(c) ((c) = 0) +# define COND_SIGNAL(c) +# define COND_WAIT(c,m) do { \ + MUTEX_UNLOCK(m); \ + grn_nanosleep(1000000); \ + MUTEX_LOCK(m); \ +} while (0) +# define COND_FIN(c) +/* todo : must be enhanced! */ + +# endif /* WIN32 */ + +# define MUTEX_INIT_SHARED MUTEX_INIT +# define COND_INIT_SHARED COND_INIT + +# define GRN_TEST_YIELD() do {} while (0) + +#endif /* HAVE_PTHREAD_H */ + +#define MUTEX_LOCK_ENSURE(ctx_, mutex) do { \ + grn_ctx *ctx__ = (ctx_); \ + do { \ + grn_ctx *ctx = ctx__; \ + if (MUTEX_LOCK_CHECK(mutex)) { \ + break; \ + } \ + if (ctx) { \ + SERR("MUTEX_LOCK"); \ + } \ + grn_nanosleep(1000000); \ + } while (GRN_TRUE); \ +} while (GRN_FALSE) + +/* format string for printf */ +#ifdef HAVE_INTTYPES_H +# include +# define GRN_FMT_INT32D PRId32 +# define GRN_FMT_INT32U PRIu32 +# define GRN_FMT_INT64D PRId64 +# define GRN_FMT_INT64U PRIu64 +#else /* HAVE_INTTYPES_H */ +# ifdef WIN32 +# define GRN_FMT_INT32D "I32d" +# define GRN_FMT_INT32U "I32u" +# define GRN_FMT_INT64D "I64d" +# define GRN_FMT_INT64U "I64u" +# else /* WIN32 */ +# define GRN_FMT_INT32D "d" +# define GRN_FMT_INT32U "u" +# ifdef __x86_64__ +# define GRN_FMT_INT64D "ld" +# define GRN_FMT_INT64U "lu" +# else /* __x86_64__ */ +# define GRN_FMT_INT64D "lld" +# define GRN_FMT_INT64U "llu" +# endif /* __x86_64__ */ +# endif /* WIN32 */ +#endif /* HAVE_INTTYPES_H */ + +#ifdef WIN32 +# define GRN_FMT_LLD "I64d" +# define GRN_FMT_LLU "I64u" +# define GRN_FMT_SIZE "Iu" +# define GRN_FMT_SSIZE "Id" +# ifdef WIN64 +# define GRN_FMT_SOCKET GRN_FMT_INT64U +# define GRN_FMT_DWORD "lu" +# else /* WIN64 */ +# define GRN_FMT_SOCKET GRN_FMT_INT32U +# define GRN_FMT_DWORD "u" +# endif /* WIN64 */ +# define GRN_FMT_OFF64_T GRN_FMT_LLD +#else /* WIN32 */ +# define GRN_FMT_LLD "lld" +# define GRN_FMT_LLU "llu" +# define GRN_FMT_SIZE "zu" +# define GRN_FMT_SSIZE "zd" +# define GRN_FMT_SOCKET "d" +# define GRN_FMT_OFF64_T "jd" +#endif /* WIN32 */ + +#ifdef __GNUC__ +# if (defined(__i386__) || defined(__x86_64__)) /* ATOMIC ADD */ +/* + * GRN_ATOMIC_ADD_EX() performs { r = *p; *p += i; } atomically. + */ +# define GRN_ATOMIC_ADD_EX(p, i, r) \ + __asm__ __volatile__ ("lock xaddl %0, %1" : "=r"(r), "+m"(*p) : "0"(i)) +/* + * GRN_BIT_SCAN_REV() finds the most significant 1 bit of `v'. Then, `r' is set + * to the index of the found bit. Note that `v' must not be 0. + */ +# define GRN_BIT_SCAN_REV(v, r) \ + __asm__ __volatile__ ("bsrl %1, %%eax; movl %%eax, %0" : "=r"(r) : "r"(v) : "%eax") +/* + * GRN_BIT_SCAN_REV0() is similar to GRN_BIT_SCAN_REV() but if `v' is 0, `r' is + * set to 0. + */ +# define GRN_BIT_SCAN_REV0(v, r) \ + __asm__ __volatile__ ("bsrl %1, %%eax; cmovzl %1, %%eax; movl %%eax, %0" : "=r"(r) : "r"(v) : "%eax", "cc") +# elif (defined(__PPC__) || defined(__ppc__)) /* ATOMIC ADD */ +# define GRN_ATOMIC_ADD_EX(p,i,r) \ + __asm__ __volatile__ ("\n1:\n\tlwarx %0, 0, %1\n\tadd %0, %0, %2\n\tstwcx. %0, 0, %1\n\tbne- 1b\n\tsub %0, %0, %2" : "=&r" (r) : "r" (p), "r" (i) : "cc", "memory") +/* todo */ +# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) +# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) +# elif (defined(__sun) && defined(__SVR4)) /* ATOMIC ADD */ +# include +# define GRN_ATOMIC_ADD_EX(p,i,r) \ + (r = atomic_add_32_nv(p, i) - i) +/* todo */ +# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) +# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) +# elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */ +# define GRN_ATOMIC_ADD_EX(p,i,r) \ + (r = __atomic_fetch_add(p, i, __ATOMIC_SEQ_CST)) +# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) +# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) +# else /* ATOMIC ADD */ +/* todo */ +# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) +# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) +# endif /* ATOMIC ADD */ + +# ifdef __i386__ /* ATOMIC 64BIT SET */ +# define GRN_SET_64BIT(p,v) \ + __asm__ __volatile__ ("\txchgl %%esi, %%ebx\n1:\n\tmovl (%0), %%eax\n\tmovl 4(%0), %%edx\n\tlock; cmpxchg8b (%0)\n\tjnz 1b\n\txchgl %%ebx, %%esi" : : "D"(p), "S"(*(((uint32_t *)&(v))+0)), "c"(*(((uint32_t *)&(v))+1)) : "ax", "dx", "memory") +# elif defined(__x86_64__) /* ATOMIC 64BIT SET */ +# define GRN_SET_64BIT(p,v) \ + (*(p) = (v)) +# elif (defined(__sun) && defined(__SVR4)) /* ATOMIC 64BIT SET */ +/* todo */ +# define GRN_SET_64BIT(p,v) \ + (void)atomic_swap_64(p, v) +# elif defined(__ATOMIC_SEQ_CST) /* GCC atomic builtins */ +# define GRN_SET_64BIT(p,v) \ + __atomic_store_n(p, v, __ATOMIC_SEQ_CST) +# else +# warning Need atomic 64bit operation support. The current implementation may break data. +# define GRN_SET_64BIT(p,v) \ + (*(p) = (v)) +# endif /* ATOMIC 64BIT SET */ + +#elif (defined(WIN32) || defined (_WIN64)) /* __GNUC__ */ + +# define GRN_ATOMIC_ADD_EX(p,i,r) \ + ((r) = InterlockedExchangeAdd((p), (i))) +# if defined(_WIN64) /* ATOMIC 64BIT SET */ +# define GRN_SET_64BIT(p,v) \ + (*(p) = (v)) +# else /* ATOMIC 64BIT SET */ +# define GRN_SET_64BIT(p,v) do {\ + uint32_t v1, v2; \ + uint64_t *p2= (p); \ + v1 = *(((uint32_t *)&(v))+0);\ + v2 = *(((uint32_t *)&(v))+1);\ + __asm _set_loop: \ + __asm mov esi, p2 \ + __asm mov ebx, v1 \ + __asm mov ecx, v2 \ + __asm mov eax, dword ptr [esi] \ + __asm mov edx, dword ptr [esi + 4] \ + __asm lock cmpxchg8b qword ptr [esi] \ + __asm jnz _set_loop \ +} while (0) +/* TODO: use _InterlockedCompareExchange64 or inline asm */ +# endif /* ATOMIC 64BIT SET */ + +/* todo */ +# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) +# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) + +#else /* __GNUC__ */ + +# if (defined(__sun) && defined(__SVR4)) /* ATOMIC ADD */ +# define __FUNCTION__ "" +# include +# define GRN_ATOMIC_ADD_EX(p,i,r) \ + (r = atomic_add_32_nv(p, i) - i) +/* todo */ +# define GRN_SET_64BIT(p,v) \ + (void)atomic_swap_64(p, v) +# endif /* ATOMIC ADD */ +/* todo */ +# define GRN_BIT_SCAN_REV(v,r) for (r = 31; r && !((1 << r) & v); r--) +# define GRN_BIT_SCAN_REV0(v,r) GRN_BIT_SCAN_REV(v,r) + +#endif /* __GNUC__ */ + +typedef uint8_t byte; + +#define GRN_ID_WIDTH 30 + +#ifdef __GNUC__ +inline static int +grn_str_greater(const uint8_t *ap, uint32_t as, const uint8_t *bp, uint32_t bs) +{ + for (;; ap++, bp++, as--, bs--) { + if (!as) { return 0; } + if (!bs) { return 1; } + if (*ap < *bp) { return 0; } + if (*ap > *bp) { return 1; } + } +} +#else /* __GNUC__ */ +# define grn_str_greater(ap,as,bp,bs)\ + (((as) > (bs)) ? (memcmp((ap), (bp), (bs)) >= 0) : (memcmp((ap), (bp), (as)) > 0)) +#endif /* __GNUC__ */ + +#ifdef WORDS_BIGENDIAN +# define grn_hton(buf,key,size) do {\ + uint32_t size_ = (uint32_t)size;\ + uint8_t *buf_ = (uint8_t *)buf;\ + uint8_t *key_ = (uint8_t *)key;\ + while (size_--) { *buf_++ = *key_++; }\ +} while (0) +# define grn_ntohi(buf,key,size) do {\ + uint32_t size_ = (uint32_t)size;\ + uint8_t *buf_ = (uint8_t *)buf;\ + uint8_t *key_ = (uint8_t *)key;\ + if (size_) { *buf_++ = 0x80 ^ *key_++; size_--; }\ + while (size_) { *buf_++ = *key_++; size_--; }\ +} while (0) +#else /* WORDS_BIGENDIAN */ +# define grn_hton(buf,key,size) do {\ + uint32_t size_ = (uint32_t)size;\ + uint8_t *buf_ = (uint8_t *)buf;\ + uint8_t *key_ = (uint8_t *)key + size;\ + while (size_--) { *buf_++ = *(--key_); }\ +} while (0) +# define grn_ntohi(buf,key,size) do {\ + uint32_t size_ = (uint32_t)size;\ + uint8_t *buf_ = (uint8_t *)buf;\ + uint8_t *key_ = (uint8_t *)key + size;\ + while (size_ > 1) { *buf_++ = *(--key_); size_--; }\ + if (size_) { *buf_ = 0x80 ^ *(--key_); } \ +} while (0) +#endif /* WORDS_BIGENDIAN */ +#define grn_ntoh(buf,key,size) grn_hton(buf,key,size) + +#ifndef __GNUC_PREREQ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif /* defined(__GNUC__) && defined(__GNUC_MINOR__) */ +#endif /* __GNUC_PREREQ */ + +#ifdef _MSC_VER +# define grn_bswap_uint64(in, out) ((out) = _byteswap_uint64(in)) +#else /* _MSC_VER */ +# if defined(__GNUC__) && __GNUC_PREREQ(4, 3) +# define grn_bswap_uint64(in, out) ((out) = __builtin_bswap64(in)) +# else /* defined(__GNUC__) && __GNUC_PREREQ(4, 3) */ +# define grn_bswap_uint64(in, out) do {\ + uint64_t temp_ = (in);\ + (out) = (temp_ << 56) |\ + ((temp_ & (0xFFULL << 8)) << 40) |\ + ((temp_ & (0xFFULL << 16)) << 24) |\ + ((temp_ & (0xFFULL << 24)) << 8) |\ + ((temp_ & (0xFFULL << 32)) >> 8) |\ + ((temp_ & (0xFFULL << 40)) >> 24) |\ + ((temp_ & (0xFFULL << 48)) >> 40) |\ + (temp_ >> 56);\ +} while (0) +# endif /* __GNUC__ */ +#endif /* _MSC_VER */ + +#ifdef WORDS_BIGENDIAN +# define grn_hton_uint64(in, out) ((out) = (in)) +#else /* WORDS_BIGENDIAN */ +# define grn_hton_uint64(in, out) grn_bswap_uint64(in, out) +#endif /* WORDS_BIGENDIAN */ +#define grn_ntoh_uint64(in, out) grn_hton_uint64(in, out) + +#define grn_gton(keybuf,key,size) do {\ + const grn_geo_point *point_ = (const grn_geo_point *)key;\ + uint64_t la_ = (uint32_t)point_->latitude;\ + uint64_t lo_ = (uint32_t)point_->longitude;\ + uint64_t result_;\ + la_ = (la_ | (la_ << 16)) & 0x0000FFFF0000FFFFULL;\ + la_ = (la_ | (la_ << 8)) & 0x00FF00FF00FF00FFULL;\ + la_ = (la_ | (la_ << 4)) & 0x0F0F0F0F0F0F0F0FULL;\ + la_ = (la_ | (la_ << 2)) & 0x3333333333333333ULL;\ + la_ = (la_ | (la_ << 1)) & 0x5555555555555555ULL;\ + lo_ = (lo_ | (lo_ << 16)) & 0x0000FFFF0000FFFFULL;\ + lo_ = (lo_ | (lo_ << 8)) & 0x00FF00FF00FF00FFULL;\ + lo_ = (lo_ | (lo_ << 4)) & 0x0F0F0F0F0F0F0F0FULL;\ + lo_ = (lo_ | (lo_ << 2)) & 0x3333333333333333ULL;\ + lo_ = (lo_ | (lo_ << 1)) & 0x5555555555555555ULL;\ + result_ = (la_ << 1) | lo_;\ + grn_hton_uint64(result_, result_);\ + grn_memcpy(keybuf, &result_, sizeof(result_));\ +} while (0) + +#define grn_ntog(keybuf,key,size) do {\ + grn_geo_point *point_ = (grn_geo_point *)keybuf;\ + uint64_t key_ = *(const uint64_t *)key;\ + uint64_t la_, lo_;\ + grn_ntoh_uint64(key_, key_);\ + la_ = (key_ >> 1) & 0x5555555555555555ULL;\ + lo_ = key_ & 0x5555555555555555ULL;\ + la_ = (la_ | (la_ >> 1)) & 0x3333333333333333ULL;\ + la_ = (la_ | (la_ >> 2)) & 0x0F0F0F0F0F0F0F0FULL;\ + la_ = (la_ | (la_ >> 4)) & 0x00FF00FF00FF00FFULL;\ + la_ = (la_ | (la_ >> 8)) & 0x0000FFFF0000FFFFULL;\ + la_ = (la_ | (la_ >> 16)) & 0x00000000FFFFFFFFULL;\ + lo_ = (lo_ | (lo_ >> 1)) & 0x3333333333333333ULL;\ + lo_ = (lo_ | (lo_ >> 2)) & 0x0F0F0F0F0F0F0F0FULL;\ + lo_ = (lo_ | (lo_ >> 4)) & 0x00FF00FF00FF00FFULL;\ + lo_ = (lo_ | (lo_ >> 8)) & 0x0000FFFF0000FFFFULL;\ + lo_ = (lo_ | (lo_ >> 16)) & 0x00000000FFFFFFFFULL;\ + point_->latitude = la_;\ + point_->longitude = lo_;\ +} while (0) + +#ifdef HAVE__STRTOUI64 +# define strtoull(nptr,endptr,base) _strtoui64(nptr,endptr,base) +#endif /* HAVE__STRTOUI64 */ + +#ifdef USE_FUTEX +# include +# include + +# define GRN_FUTEX_WAIT(p) do {\ + int err;\ + struct timespec timeout = {1, 0};\ + while (1) {\ + if (!(err = syscall(SYS_futex, p, FUTEX_WAIT, *p, &timeout))) {\ + break;\ + }\ + if (err == ETIMEDOUT) {\ + GRN_LOG(ctx, GRN_LOG_CRIT, "timeout in GRN_FUTEX_WAIT(%p)", p);\ + break;\ + } else if (err != EWOULDBLOCK) {\ + GRN_LOG(ctx, GRN_LOG_CRIT, "error %d in GRN_FUTEX_WAIT(%p)", err);\ + break;\ + }\ + }\ +} while(0) + +# define GRN_FUTEX_WAKE(p) syscall(SYS_futex, p, FUTEX_WAKE, 1) +#else /* USE_FUTEX */ +# define GRN_FUTEX_WAIT(p) grn_nanosleep(1000000) +# define GRN_FUTEX_WAKE(p) +#endif /* USE_FUTEX */ + +#ifndef HOST_NAME_MAX +# ifdef _POSIX_HOST_NAME_MAX +# define HOST_NAME_MAX _POSIX_HOST_NAME_MAX +# else /* POSIX_HOST_NAME_MAX */ +# define HOST_NAME_MAX 128 +# endif /* POSIX_HOST_NAME_MAX */ +#endif /* HOST_NAME_MAX */ + +#define GRN_NEXT_ADDR(p) (((byte *)(p)) + sizeof(*(p))) + +GRN_API void grn_sleep(uint32_t seconds); +GRN_API void grn_nanosleep(uint64_t nanoseconds); + +#include diff --git a/storage/mroonga/vendor/groonga/lib/grn_alloc.h b/storage/mroonga/vendor/groonga/lib/grn_alloc.h new file mode 100644 index 00000000..c9059113 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_alloc.h @@ -0,0 +1,163 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_alloc_init_from_env(void); + +void grn_alloc_init_ctx_impl(grn_ctx *ctx); +void grn_alloc_fin_ctx_impl(grn_ctx *ctx); + +void grn_alloc_info_init(void); +void grn_alloc_info_fin(void); + +void grn_alloc_info_dump(grn_ctx *ctx); +void grn_alloc_info_free(grn_ctx *ctx); + +#define GRN_MALLOC(s) grn_malloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_CALLOC(s) grn_calloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_REALLOC(p,s) grn_realloc(ctx,p,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_STRDUP(s) grn_strdup(ctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GMALLOC(s) grn_malloc(&grn_gctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GCALLOC(s) grn_calloc(&grn_gctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GREALLOC(p,s) grn_realloc(&grn_gctx,p,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GSTRDUP(s) grn_strdup(&grn_gctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_FREE(p) grn_free(ctx,p,__FILE__,__LINE__,__FUNCTION__) +#define GRN_MALLOCN(t,n) ((t *)(GRN_MALLOC(sizeof(t) * (n)))) +#define GRN_GFREE(p) grn_free(&grn_gctx,p,__FILE__,__LINE__,__FUNCTION__) +#define GRN_GMALLOCN(t,n) ((t *)(GRN_GMALLOC(sizeof(t) * (n)))) + +#define GRN_CTX_ALLOC(ctx,s) grn_ctx_calloc(ctx,s,__FILE__,__LINE__,__FUNCTION__) +#define GRN_CTX_FREE(ctx,p) grn_ctx_free(ctx,p,__FILE__,__LINE__,__FUNCTION__) +#define GRN_CTX_ALLOC_L(ctx,s) grn_ctx_alloc_lifo(ctx,s,f,__FILE__,__LINE__,__FUNCTION__) +#define GRN_CTX_FREE_L(ctx,p) grn_ctx_free_lifo(ctx,p,__FILE__,__LINE__,__FUNCTION__) + +void *grn_ctx_malloc(grn_ctx *ctx, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(2); +void *grn_ctx_calloc(grn_ctx *ctx, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(2); +void *grn_ctx_realloc(grn_ctx *ctx, + void *ptr, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(3); +char *grn_ctx_strdup(grn_ctx *ctx, const char *s, + const char* file, int line, const char *func); +void grn_ctx_free(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func); +void *grn_ctx_alloc_lifo(grn_ctx *ctx, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(2); +void grn_ctx_free_lifo(grn_ctx *ctx, void *ptr, + const char* file, int line, const char *func); + +#ifdef USE_DYNAMIC_MALLOC_CHANGE +typedef void *(*grn_malloc_func) (grn_ctx *ctx, size_t size, + const char *file, int line, const char *func); +typedef void *(*grn_calloc_func) (grn_ctx *ctx, size_t size, + const char *file, int line, const char *func); +typedef void *(*grn_realloc_func) (grn_ctx *ctx, void *ptr, size_t size, + const char *file, int line, const char *func); +typedef char *(*grn_strdup_func) (grn_ctx *ctx, const char *string, + const char *file, int line, const char *func); +typedef void (*grn_free_func) (grn_ctx *ctx, void *ptr, + const char *file, int line, const char *func); +grn_malloc_func grn_ctx_get_malloc(grn_ctx *ctx); +void grn_ctx_set_malloc(grn_ctx *ctx, grn_malloc_func malloc_func); +grn_calloc_func grn_ctx_get_calloc(grn_ctx *ctx); +void grn_ctx_set_calloc(grn_ctx *ctx, grn_calloc_func calloc_func); +grn_realloc_func grn_ctx_get_realloc(grn_ctx *ctx); +void grn_ctx_set_realloc(grn_ctx *ctx, grn_realloc_func realloc_func); +grn_strdup_func grn_ctx_get_strdup(grn_ctx *ctx); +void grn_ctx_set_strdup(grn_ctx *ctx, grn_strdup_func strdup_func); +grn_free_func grn_ctx_get_free(grn_ctx *ctx); +void grn_ctx_set_free(grn_ctx *ctx, grn_free_func free_func); + +void *grn_malloc(grn_ctx *ctx, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(2); +void *grn_calloc(grn_ctx *ctx, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(2); +void *grn_realloc(grn_ctx *ctx, + void *ptr, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(3); +char *grn_strdup(grn_ctx *ctx, const char *s, const char* file, int line, const char *func); +void grn_free(grn_ctx *ctx, void *ptr, const char *file, int line, const char *func); +#else +# define grn_malloc grn_malloc_default +# define grn_calloc grn_calloc_default +# define grn_realloc grn_realloc_default +# define grn_strdup grn_strdup_default +# define grn_free grn_free_default +#endif + +GRN_API void *grn_malloc_default(grn_ctx *ctx, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(2); +void *grn_calloc_default(grn_ctx *ctx, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(2); +void *grn_realloc_default(grn_ctx *ctx, + void *ptr, + size_t size, + const char *file, + int line, + const char *func) GRN_ATTRIBUTE_ALLOC_SIZE(3); +GRN_API char *grn_strdup_default(grn_ctx *ctx, const char *s, const char* file, int line, const char *func); +GRN_API void grn_free_default(grn_ctx *ctx, void *ptr, const char* file, int line, const char *func); + +#ifdef USE_FAIL_MALLOC +int grn_fail_malloc_check(size_t size, const char *file, int line, const char *func); +void *grn_malloc_fail(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); +void *grn_calloc_fail(grn_ctx *ctx, size_t size, const char* file, int line, const char *func); +void *grn_realloc_fail(grn_ctx *ctx, void *ptr, size_t size, const char* file, int line, const char *func); +char *grn_strdup_fail(grn_ctx *ctx, const char *s, const char* file, int line, const char *func); +#endif + +int grn_alloc_count(void); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_cache.h b/storage/mroonga/vendor/groonga/lib/grn_cache.h new file mode 100644 index 00000000..a0cb9c37 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_cache.h @@ -0,0 +1,49 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_CACHE_MAX_KEY_SIZE GRN_HASH_MAX_KEY_SIZE_LARGE + +typedef struct { + uint32_t nentries; + uint32_t max_nentries; + uint32_t nfetches; + uint32_t nhits; +} grn_cache_statistics; + +void grn_cache_init(void); +grn_rc grn_cache_fetch(grn_ctx *ctx, grn_cache *cache, + const char *str, uint32_t str_size, + grn_obj *output); +void grn_cache_update(grn_ctx *ctx, grn_cache *cache, + const char *str, uint32_t str_size, grn_obj *value); +void grn_cache_expire(grn_cache *cache, int32_t size); +void grn_cache_fin(void); +void grn_cache_get_statistics(grn_ctx *ctx, grn_cache *cache, + grn_cache_statistics *statistics); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_com.h b/storage/mroonga/vendor/groonga/lib/grn_com.h new file mode 100644 index 00000000..505e87a5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_com.h @@ -0,0 +1,250 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_str.h" +#include "grn_hash.h" + +#ifdef HAVE_NETDB_H +#include +#endif /* HAVE_NETDB_H */ + +#ifdef __cplusplus +extern "C" { +#endif + +/******* grn_com_queue ********/ + +typedef struct _grn_com_queue grn_com_queue; +typedef struct _grn_com_queue_entry grn_com_queue_entry; + +#define GRN_COM_QUEUE_BINSIZE (0x100) + +struct _grn_com_queue_entry { + grn_obj obj; + struct _grn_com_queue_entry *next; +}; + +struct _grn_com_queue { + grn_com_queue_entry *bins[GRN_COM_QUEUE_BINSIZE]; + grn_com_queue_entry *next; + grn_com_queue_entry **tail; + uint8_t first; + uint8_t last; + grn_critical_section cs; +}; + +#define GRN_COM_QUEUE_INIT(q) do {\ + (q)->next = NULL;\ + (q)->tail = &(q)->next;\ + (q)->first = 0;\ + (q)->last = 0;\ + CRITICAL_SECTION_INIT((q)->cs);\ +} while (0) + +#define GRN_COM_QUEUE_EMPTYP(q) (((q)->first == (q)->last) && !(q)->next) + +GRN_API grn_rc grn_com_queue_enque(grn_ctx *ctx, grn_com_queue *q, grn_com_queue_entry *e); +GRN_API grn_com_queue_entry *grn_com_queue_deque(grn_ctx *ctx, grn_com_queue *q); + +/******* grn_com ********/ + +#ifdef USE_SELECT +# ifdef HAVE_SYS_SELECT_H +# include +# endif /* HAVE_SYS_SELECT_H */ +# define GRN_COM_POLLIN 1 +# define GRN_COM_POLLOUT 2 +#else /* USE_SELECT */ +# ifdef USE_EPOLL +# include +# define GRN_COM_POLLIN EPOLLIN +# define GRN_COM_POLLOUT EPOLLOUT +# else /* USE_EPOLL */ +# ifdef USE_KQUEUE +# include +# define GRN_COM_POLLIN EVFILT_READ +# define GRN_COM_POLLOUT EVFILT_WRITE +# else /* USE_KQUEUE */ +# include +# define GRN_COM_POLLIN POLLIN +# define GRN_COM_POLLOUT POLLOUT +# endif /* USE_KQUEUE */ +# endif /* USE_EPOLL */ +#endif /* USE_SELECT */ + +typedef struct _grn_com grn_com; +typedef struct _grn_com_event grn_com_event; +typedef struct _grn_com_addr grn_com_addr; +typedef void grn_com_callback(grn_ctx *ctx, grn_com_event *, grn_com *); +typedef void grn_msg_handler(grn_ctx *ctx, grn_obj *msg); + +enum { + grn_com_ok = 0, + grn_com_emem, + grn_com_erecv_head, + grn_com_erecv_body, + grn_com_eproto, +}; + +struct _grn_com_addr { + uint32_t addr; + uint16_t port; + uint16_t sid; +}; + +struct _grn_com { + grn_sock fd; + int events; + uint16_t sid; + uint8_t has_sid; + uint8_t closed; + grn_com_queue new_; + grn_com_event *ev; + void *opaque; + grn_bool accepting; +}; + +struct _grn_com_event { + struct _grn_hash *hash; + int max_nevents; + grn_ctx *ctx; + grn_mutex mutex; + grn_cond cond; + grn_com_queue recv_old; + grn_msg_handler *msg_handler; + grn_com_addr curr_edge_id; + grn_com *acceptor; + void *opaque; +#ifndef USE_SELECT +#ifdef USE_EPOLL + int epfd; + struct epoll_event *events; +#else /* USE_EPOLL */ +#ifdef USE_KQUEUE + int kqfd; + struct kevent *events; +#else /* USE_KQUEUE */ + int dummy; /* dummy */ + struct pollfd *events; +#endif /* USE_KQUEUE */ +#endif /* USE_EPOLL */ +#endif /* USE_SELECT */ +}; + +grn_rc grn_com_init(void); +void grn_com_fin(void); +GRN_API grn_rc grn_com_event_init(grn_ctx *ctx, grn_com_event *ev, int max_nevents, int data_size); +GRN_API grn_rc grn_com_event_fin(grn_ctx *ctx, grn_com_event *ev); +GRN_API grn_rc grn_com_event_start_accept(grn_ctx *ctx, grn_com_event *ev); +grn_rc grn_com_event_stop_accept(grn_ctx *ctx, grn_com_event *ev); +grn_rc grn_com_event_add(grn_ctx *ctx, grn_com_event *ev, grn_sock fd, int events, grn_com **com); +grn_rc grn_com_event_mod(grn_ctx *ctx, grn_com_event *ev, grn_sock fd, int events, grn_com **com); +GRN_API grn_rc grn_com_event_del(grn_ctx *ctx, grn_com_event *ev, grn_sock fd); +GRN_API grn_rc grn_com_event_poll(grn_ctx *ctx, grn_com_event *ev, int timeout); +grn_rc grn_com_event_each(grn_ctx *ctx, grn_com_event *ev, grn_com_callback *func); + +/******* grn_com_gqtp ********/ + +#define GRN_COM_PROTO_HTTP 0x47 +#define GRN_COM_PROTO_GQTP 0xc7 +#define GRN_COM_PROTO_MBREQ 0x80 +#define GRN_COM_PROTO_MBRES 0x81 + +typedef struct _grn_com_header grn_com_header; + +struct _grn_com_header { + uint8_t proto; + uint8_t qtype; + uint16_t keylen; + uint8_t level; + uint8_t flags; + uint16_t status; + uint32_t size; + uint32_t opaque; + uint64_t cas; +}; + +GRN_API grn_com *grn_com_copen(grn_ctx *ctx, grn_com_event *ev, const char *dest, int port); +GRN_API grn_rc grn_com_sopen(grn_ctx *ctx, grn_com_event *ev, + const char *bind_address, int port, + grn_msg_handler *func, struct hostent *he); + +GRN_API void grn_com_close_(grn_ctx *ctx, grn_com *com); +GRN_API grn_rc grn_com_close(grn_ctx *ctx, grn_com *com); + +GRN_API grn_rc grn_com_send(grn_ctx *ctx, grn_com *cs, + grn_com_header *header, const char *body, uint32_t size, int flags); +grn_rc grn_com_recv(grn_ctx *ctx, grn_com *cs, grn_com_header *header, grn_obj *buf); +GRN_API grn_rc grn_com_send_http(grn_ctx *ctx, grn_com *cs, const char *path, uint32_t path_len, int flags); + +/******* grn_msg ********/ + +typedef struct _grn_msg grn_msg; + +struct _grn_msg { + grn_com_queue_entry qe; + union { + grn_com *peer; + grn_sock fd; + } u; + grn_ctx *ctx; + grn_com_queue *old; + grn_com_header header; + grn_com_addr edge_id; + grn_com *acceptor; +}; + +GRN_API grn_rc grn_msg_send(grn_ctx *ctx, grn_obj *msg, int flags); +GRN_API grn_obj *grn_msg_open_for_reply(grn_ctx *ctx, grn_obj *query, grn_com_queue *old); +GRN_API grn_obj *grn_msg_open(grn_ctx *ctx, grn_com *com, grn_com_queue *old); +GRN_API grn_rc grn_msg_set_property(grn_ctx *ctx, grn_obj *obj, + uint16_t status, uint32_t key_size, uint8_t extra_size); +GRN_API grn_rc grn_msg_close(grn_ctx *ctx, grn_obj *msg); + +/******* grn_edge ********/ + +#define GRN_EDGE_WORKER 0 +#define GRN_EDGE_COMMUNICATOR 1 + +typedef struct { + grn_com_queue_entry eq; + grn_ctx ctx; + grn_com_queue recv_new; + grn_com_queue send_old; + grn_com *com; + grn_com_addr *addr; + grn_msg *msg; + uint8_t stat; + uint8_t flags; + grn_id id; +} grn_edge; + +GRN_VAR grn_hash *grn_edges; +GRN_API void grn_edges_init(grn_ctx *ctx, void (*dispatcher)(grn_ctx *ctx, grn_edge *edge)); +GRN_API void grn_edges_fin(grn_ctx *ctx); +GRN_API grn_edge *grn_edges_add(grn_ctx *ctx, grn_com_addr *addr, int *added); +grn_edge *grn_edges_add_communicator(grn_ctx *ctx, grn_com_addr *addr); +GRN_API void grn_edges_delete(grn_ctx *ctx, grn_edge *edge); +void grn_edge_dispatch(grn_ctx *ctx, grn_edge *edge, grn_obj *msg); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_config.h b/storage/mroonga/vendor/groonga/lib/grn_config.h new file mode 100644 index 00000000..75e23a46 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_config.h @@ -0,0 +1,37 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_db.h" +#include "grn_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + grn_db_obj obj; + grn_hash_cursor *hash_cursor; +} grn_config_cursor; + +grn_rc grn_config_cursor_close(grn_ctx *ctx, grn_config_cursor *cursor); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_ctx.h b/storage/mroonga/vendor/groonga/lib/grn_ctx.h new file mode 100644 index 00000000..9e82785f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_ctx.h @@ -0,0 +1,501 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_error.h" + +#include + +#ifdef HAVE_SIGNAL_H +#include +#define GRN_BREAK_POINT raise(SIGTRAP) +#endif /* HAVE_SIGNAL_H */ + +#ifdef HAVE_EXECINFO_H +#include +#endif /* HAVE_EXECINFO_H */ + +#include "grn_io.h" +#include "grn_alloc.h" +#include "grn_time.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**** api in/out ****/ + +#define GRN_API_ENTER do {\ + if ((ctx)->seqno & 1) {\ + (ctx)->subno++;\ + } else {\ + (ctx)->errlvl = GRN_OK;\ + if ((ctx)->rc != GRN_CANCEL) {\ + (ctx)->rc = GRN_SUCCESS;\ + }\ + (ctx)->seqno++;\ + }\ + GRN_TEST_YIELD();\ +} while (0) + +/* CAUTION!! : pass only variables or constants as r */ +#define GRN_API_RETURN(r) do {\ + if (ctx->subno) {\ + ctx->subno--;\ + } else {\ + ctx->seqno++;\ + }\ + GRN_TEST_YIELD();\ + return r;\ +} while (0) + +/**** error handling ****/ + +#define GRN_EMERG GRN_LOG_EMERG +#define GRN_ALERT GRN_LOG_ALERT +#define GRN_CRIT GRN_LOG_CRIT +#define GRN_ERROR GRN_LOG_ERROR +#define GRN_WARN GRN_LOG_WARNING +#define GRN_OK GRN_LOG_NOTICE + +#define ERRCLR(ctx) do {\ + if (ctx) {\ + ((grn_ctx *)ctx)->errlvl = GRN_OK;\ + if (((grn_ctx *)ctx)->rc != GRN_CANCEL) {\ + ((grn_ctx *)ctx)->rc = GRN_SUCCESS;\ + ((grn_ctx *)ctx)->errbuf[0] = '\0';\ + }\ + }\ + errno = 0;\ + grn_gctx.errlvl = GRN_OK;\ + grn_gctx.rc = GRN_SUCCESS;\ +} while (0) + +#ifdef HAVE_BACKTRACE +#define BACKTRACE(ctx) ((ctx)->ntrace = (unsigned char)backtrace((ctx)->trace, 16)) +#else /* HAVE_BACKTRACE */ +#define BACKTRACE(ctx) +#endif /* HAVE_BACKTRACE */ + +GRN_API grn_bool grn_ctx_impl_should_log(grn_ctx *ctx); +GRN_API void grn_ctx_impl_set_current_error_message(grn_ctx *ctx); + +#ifdef HAVE_BACKTRACE +#define LOGTRACE(ctx,lvl) do {\ + int i;\ + char **p;\ + BACKTRACE(ctx);\ + p = backtrace_symbols((ctx)->trace, (ctx)->ntrace);\ + if (!p) {\ + GRN_LOG((ctx), lvl, "backtrace_symbols failed");\ + } else {\ + for (i = 0; i < (ctx)->ntrace; i++) {\ + GRN_LOG((ctx), lvl, "%s", p[i]);\ + }\ + free(p);\ + }\ +} while (0) +#else /* HAVE_BACKTRACE */ +#define LOGTRACE(ctx,msg) +#endif /* HAVE_BACKTRACE */ + +#define ERRSET(ctx,lvl,r,...) do {\ + grn_ctx *ctx_ = (grn_ctx *)ctx;\ + ctx_->errlvl = (lvl);\ + if (ctx_->rc != GRN_CANCEL) {\ + ctx_->rc = (r);\ + }\ + ctx_->errfile = __FILE__;\ + ctx_->errline = __LINE__;\ + ctx_->errfunc = __FUNCTION__;\ + grn_ctx_log(ctx, __VA_ARGS__);\ + if (grn_ctx_impl_should_log(ctx)) {\ + grn_ctx_impl_set_current_error_message(ctx);\ + GRN_LOG(ctx, lvl, __VA_ARGS__);\ + if (lvl <= GRN_LOG_ERROR) { LOGTRACE(ctx, lvl); }\ + }\ +} while (0) + +#define ERRP(ctx,lvl) \ + (((ctx) && ((grn_ctx *)(ctx))->errlvl <= (lvl)) || (grn_gctx.errlvl <= (lvl))) + +#ifdef ERR +# undef ERR +#endif /* ERR */ +#define CRIT(rc,...) ERRSET(ctx, GRN_CRIT, (rc), __VA_ARGS__) +#define ERR(rc,...) ERRSET(ctx, GRN_ERROR, (rc), __VA_ARGS__) +#define WARN(rc,...) ERRSET(ctx, GRN_WARN, (rc), __VA_ARGS__) +#define MERR(...) ERRSET(ctx, GRN_ALERT, GRN_NO_MEMORY_AVAILABLE, __VA_ARGS__) +#define ALERT(...) ERRSET(ctx, GRN_ALERT, GRN_SUCCESS, __VA_ARGS__) + +#define ERR_CAST(column, range, element) do {\ + grn_obj inspected;\ + char column_name[GRN_TABLE_MAX_KEY_SIZE];\ + int column_name_size;\ + char range_name[GRN_TABLE_MAX_KEY_SIZE];\ + int range_name_size;\ + GRN_TEXT_INIT(&inspected, 0);\ + grn_inspect(ctx, &inspected, element);\ + column_name_size = grn_obj_name(ctx, column, column_name,\ + GRN_TABLE_MAX_KEY_SIZE);\ + range_name_size = grn_obj_name(ctx, range, range_name,\ + GRN_TABLE_MAX_KEY_SIZE);\ + ERR(GRN_INVALID_ARGUMENT, "<%.*s>: failed to cast to <%.*s>: <%.*s>",\ + column_name_size, column_name,\ + range_name_size, range_name,\ + (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected));\ + GRN_OBJ_FIN(ctx, &inspected);\ +} while (0) + +#define USER_MESSAGE_SIZE 1024 + +#ifdef WIN32 + +#define SERR(...) do {\ + grn_rc rc;\ + int error_code;\ + const char *system_message;\ + char user_message[USER_MESSAGE_SIZE];\ + error_code = GetLastError();\ + system_message = grn_current_error_message();\ + rc = grn_windows_error_code_to_rc(error_code);\ + grn_snprintf(user_message,\ + USER_MESSAGE_SIZE, USER_MESSAGE_SIZE,\ + __VA_ARGS__);\ + ERR(rc, "system error[%d]: %s: %s",\ + error_code, system_message, user_message);\ +} while (0) + +#define SOERR(...) do {\ + grn_rc rc;\ + const char *m;\ + char user_message[USER_MESSAGE_SIZE];\ + int e = WSAGetLastError();\ + switch (e) {\ + case WSANOTINITIALISED :\ + rc = GRN_SOCKET_NOT_INITIALIZED;\ + m = "please call grn_com_init first";\ + break;\ + case WSAEFAULT :\ + rc = GRN_BAD_ADDRESS;\ + m = "bad address";\ + break;\ + case WSAEINVAL :\ + rc = GRN_INVALID_ARGUMENT;\ + m = "invalid argument";\ + break;\ + case WSAEMFILE :\ + rc = GRN_TOO_MANY_OPEN_FILES;\ + m = "too many sockets";\ + break;\ + case WSAEWOULDBLOCK :\ + rc = GRN_OPERATION_WOULD_BLOCK;\ + m = "operation would block";\ + break;\ + case WSAENOTSOCK :\ + rc = GRN_NOT_SOCKET;\ + m = "given fd is not socket fd";\ + break;\ + case WSAEOPNOTSUPP :\ + rc = GRN_OPERATION_NOT_SUPPORTED;\ + m = "operation is not supported";\ + break;\ + case WSAEADDRINUSE :\ + rc = GRN_ADDRESS_IS_IN_USE;\ + m = "address is already in use";\ + break;\ + case WSAEADDRNOTAVAIL :\ + rc = GRN_ADDRESS_IS_NOT_AVAILABLE;\ + m = "address is not available";\ + break;\ + case WSAENETDOWN :\ + rc = GRN_NETWORK_IS_DOWN;\ + m = "network is down";\ + break;\ + case WSAENOBUFS :\ + rc = GRN_NO_BUFFER;\ + m = "no buffer";\ + break;\ + case WSAEISCONN :\ + rc = GRN_SOCKET_IS_ALREADY_CONNECTED;\ + m = "socket is already connected";\ + break;\ + case WSAENOTCONN :\ + rc = GRN_SOCKET_IS_NOT_CONNECTED;\ + m = "socket is not connected";\ + break;\ + case WSAESHUTDOWN :\ + rc = GRN_SOCKET_IS_ALREADY_SHUTDOWNED;\ + m = "socket is already shutdowned";\ + break;\ + case WSAETIMEDOUT :\ + rc = GRN_OPERATION_TIMEOUT;\ + m = "connection time out";\ + break;\ + case WSAECONNREFUSED :\ + rc = GRN_CONNECTION_REFUSED;\ + m = "connection refused";\ + break;\ + case WSAEINTR :\ + rc = GRN_INTERRUPTED_FUNCTION_CALL;\ + m = "interrupted function call";\ + break;\ + default:\ + rc = GRN_UNKNOWN_ERROR;\ + m = "unknown error";\ + break;\ + }\ + grn_snprintf(user_message,\ + USER_MESSAGE_SIZE, USER_MESSAGE_SIZE,\ + __VA_ARGS__);\ + ERR(rc, "socket error[%d]: %s: %s",\ + e, m, user_message);\ +} while (0) + +#define ERRNO_ERR(...) do {\ + grn_rc rc;\ + int errno_keep = errno;\ + grn_bool show_errno = GRN_FALSE;\ + const char *system_message;\ + char user_message[USER_MESSAGE_SIZE];\ + system_message = grn_strerror(errno);\ + switch (errno_keep) {\ + case EPERM : rc = GRN_OPERATION_NOT_PERMITTED; break;\ + case ENOENT : rc = GRN_NO_SUCH_FILE_OR_DIRECTORY; break;\ + case ESRCH : rc = GRN_NO_SUCH_PROCESS; break;\ + case EINTR : rc = GRN_INTERRUPTED_FUNCTION_CALL; break;\ + case EIO : rc = GRN_INPUT_OUTPUT_ERROR; break;\ + case E2BIG : rc = GRN_ARG_LIST_TOO_LONG; break;\ + case ENOEXEC : rc = GRN_EXEC_FORMAT_ERROR; break;\ + case EBADF : rc = GRN_BAD_FILE_DESCRIPTOR; break;\ + case ECHILD : rc = GRN_NO_CHILD_PROCESSES; break;\ + case EAGAIN: rc = GRN_OPERATION_WOULD_BLOCK; break;\ + case ENOMEM : rc = GRN_NO_MEMORY_AVAILABLE; break;\ + case EACCES : rc = GRN_PERMISSION_DENIED; break;\ + case EFAULT : rc = GRN_BAD_ADDRESS; break;\ + case EEXIST : rc = GRN_FILE_EXISTS; break;\ + /* case EXDEV : */\ + case ENODEV : rc = GRN_NO_SUCH_DEVICE; break;\ + case ENOTDIR : rc = GRN_NOT_A_DIRECTORY; break;\ + case EISDIR : rc = GRN_IS_A_DIRECTORY; break;\ + case EINVAL : rc = GRN_INVALID_ARGUMENT; break;\ + case EMFILE : rc = GRN_TOO_MANY_OPEN_FILES; break;\ + case ENOTTY : rc = GRN_INAPPROPRIATE_I_O_CONTROL_OPERATION; break;\ + case EFBIG : rc = GRN_FILE_TOO_LARGE; break;\ + case ENOSPC : rc = GRN_NO_SPACE_LEFT_ON_DEVICE; break;\ + case ESPIPE : rc = GRN_INVALID_SEEK; break;\ + case EROFS : rc = GRN_READ_ONLY_FILE_SYSTEM; break;\ + case EMLINK : rc = GRN_TOO_MANY_LINKS; break;\ + case EPIPE : rc = GRN_BROKEN_PIPE; break;\ + case EDOM : rc = GRN_DOMAIN_ERROR; break;\ + case ERANGE : rc = GRN_RANGE_ERROR; break;\ + case EDEADLOCK : rc = GRN_RESOURCE_DEADLOCK_AVOIDED; break;\ + case ENAMETOOLONG : rc = GRN_FILENAME_TOO_LONG; break;\ + case EILSEQ : rc = GRN_ILLEGAL_BYTE_SEQUENCE; break;\ + /* case STRUNCATE : */\ + default :\ + rc = GRN_UNKNOWN_ERROR;\ + show_errno = GRN_TRUE;\ + break;\ + }\ + grn_snprintf(user_message,\ + USER_MESSAGE_SIZE, USER_MESSAGE_SIZE,\ + __VA_ARGS__);\ + if (show_errno) {\ + ERR(rc, "system call error[%d]: %s: %s",\ + errno_keep, system_message, user_message);\ + } else {\ + ERR(rc, "system call error: %s: %s",\ + system_message, user_message);\ + }\ +} while (0) + +#else /* WIN32 */ + +#define SERR(...) do {\ + grn_rc rc;\ + int errno_keep = errno;\ + grn_bool show_errno = GRN_FALSE;\ + const char *system_message = grn_current_error_message();\ + char user_message[USER_MESSAGE_SIZE];\ + switch (errno_keep) {\ + case ELOOP : rc = GRN_TOO_MANY_SYMBOLIC_LINKS; break;\ + case ENAMETOOLONG : rc = GRN_FILENAME_TOO_LONG; break;\ + case ENOENT : rc = GRN_NO_SUCH_FILE_OR_DIRECTORY; break;\ + case ENOMEM : rc = GRN_NO_MEMORY_AVAILABLE; break;\ + case ENOTDIR : rc = GRN_NOT_A_DIRECTORY; break;\ + case EPERM : rc = GRN_OPERATION_NOT_PERMITTED; break;\ + case ESRCH : rc = GRN_NO_SUCH_PROCESS; break;\ + case EINTR : rc = GRN_INTERRUPTED_FUNCTION_CALL; break;\ + case EIO : rc = GRN_INPUT_OUTPUT_ERROR; break;\ + case ENXIO : rc = GRN_NO_SUCH_DEVICE_OR_ADDRESS; break;\ + case E2BIG : rc = GRN_ARG_LIST_TOO_LONG; break;\ + case ENOEXEC : rc = GRN_EXEC_FORMAT_ERROR; break;\ + case EBADF : rc = GRN_BAD_FILE_DESCRIPTOR; break;\ + case ECHILD : rc = GRN_NO_CHILD_PROCESSES; break;\ + case EACCES : rc = GRN_PERMISSION_DENIED; break;\ + case EFAULT : rc = GRN_BAD_ADDRESS; break;\ + case EBUSY : rc = GRN_RESOURCE_BUSY; break;\ + case EEXIST : rc = GRN_FILE_EXISTS; break;\ + case ENODEV : rc = GRN_NO_SUCH_DEVICE; break;\ + case EISDIR : rc = GRN_IS_A_DIRECTORY; break;\ + case EINVAL : rc = GRN_INVALID_ARGUMENT; break;\ + case EMFILE : rc = GRN_TOO_MANY_OPEN_FILES; break;\ + case EFBIG : rc = GRN_FILE_TOO_LARGE; break;\ + case ENOSPC : rc = GRN_NO_SPACE_LEFT_ON_DEVICE; break;\ + case EROFS : rc = GRN_READ_ONLY_FILE_SYSTEM; break;\ + case EMLINK : rc = GRN_TOO_MANY_LINKS; break;\ + case EPIPE : rc = GRN_BROKEN_PIPE; break;\ + case EDOM : rc = GRN_DOMAIN_ERROR; break;\ + case ERANGE : rc = GRN_RANGE_ERROR; break;\ + case ENOTSOCK : rc = GRN_NOT_SOCKET; break;\ + case EADDRINUSE : rc = GRN_ADDRESS_IS_IN_USE; break;\ + case ENETDOWN : rc = GRN_NETWORK_IS_DOWN; break;\ + case ENOBUFS : rc = GRN_NO_BUFFER; break;\ + case EISCONN : rc = GRN_SOCKET_IS_ALREADY_CONNECTED; break;\ + case ENOTCONN : rc = GRN_SOCKET_IS_NOT_CONNECTED; break;\ + /*\ + case ESOCKTNOSUPPORT :\ + case EOPNOTSUPP :\ + case EPFNOSUPPORT :\ + */\ + case EPROTONOSUPPORT : rc = GRN_OPERATION_NOT_SUPPORTED; break;\ + case ESHUTDOWN : rc = GRN_SOCKET_IS_ALREADY_SHUTDOWNED; break;\ + case ETIMEDOUT : rc = GRN_OPERATION_TIMEOUT; break;\ + case ECONNREFUSED: rc = GRN_CONNECTION_REFUSED; break;\ + case EAGAIN: rc = GRN_OPERATION_WOULD_BLOCK; break;\ + default :\ + rc = GRN_UNKNOWN_ERROR;\ + show_errno = GRN_TRUE;\ + break;\ + }\ + grn_snprintf(user_message,\ + USER_MESSAGE_SIZE, USER_MESSAGE_SIZE,\ + __VA_ARGS__);\ + if (show_errno) {\ + ERR(rc, "system call error[%d]: %s: %s",\ + errno_keep, system_message, user_message);\ + } else {\ + ERR(rc, "system call error: %s: %s",\ + system_message, user_message);\ + }\ +} while (0) + +#define SOERR(...) SERR(__VA_ARGS__) + +#define ERRNO_ERR(...) SERR(__VA_ARGS__) + +#endif /* WIN32 */ + +#define GERR(rc,...) ERRSET(&grn_gctx, GRN_ERROR, (rc), __VA_ARGS__) +#define GMERR(...) ERRSET(&grn_gctx, GRN_ALERT, GRN_NO_MEMORY_AVAILABLE, __VA_ARGS__) + +#ifdef DEBUG +#define GRN_ASSERT(s) grn_assert(ctx,(s),__FILE__,__LINE__,__FUNCTION__) +#else +#define GRN_ASSERT(s) +#endif + +void grn_assert(grn_ctx *ctx, int cond, const char* file, int line, const char* func); + +/**** grn_ctx ****/ + +GRN_VAR grn_ctx grn_gctx; +extern int grn_pagesize; +extern grn_critical_section grn_glock; +extern uint32_t grn_gtick; +extern int grn_lock_timeout; + +#define GRN_CTX_ALLOCATED (0x80) +#define GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND (0x40) + +extern grn_timeval grn_starttime; + +GRN_API void grn_ctx_log(grn_ctx *ctx, const char *fmt, ...) GRN_ATTRIBUTE_PRINTF(2); +GRN_API void grn_ctx_logv(grn_ctx *ctx, const char *fmt, va_list ap); +void grn_ctx_loader_clear(grn_ctx *ctx); +void grn_log_reopen(grn_ctx *ctx); + +GRN_API grn_rc grn_ctx_sendv(grn_ctx *ctx, int argc, char **argv, int flags); +void grn_ctx_set_keep_command(grn_ctx *ctx, grn_obj *command); + +grn_content_type grn_get_ctype(grn_obj *var); +grn_content_type grn_content_type_parse(grn_ctx *ctx, + grn_obj *var, + grn_content_type default_value); + +/**** db_obj ****/ + +/* flag values used for grn_obj.header.impl_flags */ + +#define GRN_OBJ_ALLOCATED (0x01<<2) /* allocated by ctx */ +#define GRN_OBJ_EXPRVALUE (0x01<<3) /* value allocated by grn_expr */ +#define GRN_OBJ_EXPRCONST (0x01<<4) /* constant allocated by grn_expr */ + +typedef struct _grn_hook grn_hook; + +typedef struct { + grn_obj_header header; + grn_id range; /* table: type of subrecords, column: type of values */ + /* -- compatible with grn_accessor -- */ + grn_id id; + grn_obj *db; + grn_user_data user_data; + grn_proc_func *finalizer; + grn_hook *hooks[5]; + void *source; + uint32_t source_size; + uint32_t max_n_subrecs; + uint8_t subrec_size; + uint8_t subrec_offset; + uint8_t record_unit; + uint8_t subrec_unit; + union { + grn_table_group_flags group; + } flags; + // grn_obj_flags flags; +} grn_db_obj; + +#define GRN_DB_OBJ_SET_TYPE(db_obj,obj_type) do {\ + (db_obj)->obj.header.type = (obj_type);\ + (db_obj)->obj.header.impl_flags = 0;\ + (db_obj)->obj.header.flags = 0;\ + (db_obj)->obj.header.domain = GRN_ID_NIL;\ + (db_obj)->obj.id = GRN_ID_NIL;\ + (db_obj)->obj.user_data.ptr = NULL;\ + (db_obj)->obj.finalizer = NULL;\ + (db_obj)->obj.hooks[0] = NULL;\ + (db_obj)->obj.hooks[1] = NULL;\ + (db_obj)->obj.hooks[2] = NULL;\ + (db_obj)->obj.hooks[3] = NULL;\ + (db_obj)->obj.hooks[4] = NULL;\ + (db_obj)->obj.source = NULL;\ + (db_obj)->obj.source_size = 0;\ +} while (0) + +/**** receive handler ****/ + +GRN_API void grn_ctx_stream_out_func(grn_ctx *c, int flags, void *stream); + +grn_rc grn_db_init_builtin_procs(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h new file mode 100644 index 00000000..8f300f09 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl.h @@ -0,0 +1,237 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#ifndef GRN_CTX_H +# include "grn_ctx.h" +#endif /* GRN_CTX_H */ + +#ifndef GRN_COM_H +# include "grn_com.h" +#endif /* GRN_COM_H */ + +#include "grn_msgpack.h" + +#ifdef GRN_WITH_MRUBY +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/**** grn_expr ****/ + +#define GRN_EXPR_MISSING_NAME "expr_missing" + +/**** grn_ctx_impl ****/ + +#define GRN_CTX_INITED 0x00 +#define GRN_CTX_QUITTING 0x0f + +typedef enum { + GRN_LOADER_BEGIN = 0, + GRN_LOADER_TOKEN, + GRN_LOADER_STRING, + GRN_LOADER_SYMBOL, + GRN_LOADER_NUMBER, + GRN_LOADER_STRING_ESC, + GRN_LOADER_UNICODE0, + GRN_LOADER_UNICODE1, + GRN_LOADER_UNICODE2, + GRN_LOADER_UNICODE3, + GRN_LOADER_END +} grn_loader_stat; + +/* + * Status of target columns used in Format 1. + * Target columns are specified via --columns or the first array in a Format 1 + * JSON object. + */ +typedef enum { + GRN_LOADER_COLUMNS_UNSET = 0, /* Columns are not available. */ + GRN_LOADER_COLUMNS_SET, /* Columns are available. */ + GRN_LOADER_COLUMNS_BROKEN /* Columns are specified but broken. */ +} grn_loader_columns_status; + +typedef struct { + grn_obj values; + grn_obj level; + grn_obj columns; + grn_obj ids; + grn_obj return_codes; + grn_obj error_messages; + uint32_t emit_level; + int32_t id_offset; /* Position of _id in values or -1 if _id is N/A. */ + int32_t key_offset; /* Position of _key in values or -1 if _key is N/A. */ + grn_obj *table; + grn_obj *last; + grn_obj *ifexists; + grn_obj *each; + uint32_t unichar; + uint32_t values_size; + uint32_t nrecords; + grn_loader_stat stat; + grn_content_type input_type; + grn_loader_columns_status columns_status; + grn_rc rc; + char errbuf[GRN_CTX_MSGSIZE]; + grn_bool output_ids; + grn_bool output_errors; +} grn_loader; + +#define GRN_CTX_N_SEGMENTS 512 + +#ifdef USE_MEMORY_DEBUG +typedef struct _grn_alloc_info grn_alloc_info; +struct _grn_alloc_info +{ + void *address; + int freed; + size_t size; + char alloc_backtrace[4096]; + char free_backtrace[4096]; + char *file; + int line; + char *func; + grn_alloc_info *next; +}; +#endif + +typedef struct _grn_mrb_data grn_mrb_data; +struct _grn_mrb_data { + grn_bool initialized; +#ifdef GRN_WITH_MRUBY + mrb_state *state; + char base_directory[PATH_MAX]; + struct RClass *module; + struct RClass *object_class; + grn_hash *checked_procs; + grn_hash *registered_plugins; + struct { + grn_obj from; + grn_obj to; + } buffer; + struct { + struct RClass *time_class; + } builtin; + struct { + struct RClass *operator_class; + } groonga; +#endif +}; + +struct _grn_ctx_impl { + grn_encoding encoding; + + /* memory pool portion */ + int32_t lifoseg; + int32_t currseg; + grn_critical_section lock; + grn_io_mapinfo segs[GRN_CTX_N_SEGMENTS]; + +#ifdef USE_DYNAMIC_MALLOC_CHANGE + /* memory allocation portion */ + grn_malloc_func malloc_func; + grn_calloc_func calloc_func; + grn_realloc_func realloc_func; + grn_strdup_func strdup_func; + grn_free_func free_func; +#endif + +#ifdef USE_MEMORY_DEBUG + /* memory debug portion */ + grn_alloc_info *alloc_info; +#endif + + /* expression portion */ + grn_obj *stack[GRN_STACK_SIZE]; + uint32_t stack_curr; + grn_hash *expr_vars; + grn_obj *curr_expr; + grn_obj current_request_id; + void *current_request_timer_id; + void *parser; + grn_timeval tv; + + /* loader portion */ + grn_edge *edge; + grn_loader loader; + + /* plugin portion */ + const char *plugin_path; + + /* output portion */ + struct { + grn_obj *buf; + void (*func)(grn_ctx *, int, void *); + union { + void *ptr; + int fd; + uint32_t u32; + uint64_t u64; + } data; + grn_content_type type; + const char *mime_type; + grn_bool is_pretty; + grn_obj names; + grn_obj levels; +#ifdef GRN_WITH_MESSAGE_PACK + msgpack_packer msgpacker; +#endif + } output; + + struct { + int flags; + grn_command_version version; + struct { + grn_obj *command; + grn_command_version version; + } keep; + } command; + + /* match escalation portion */ + int64_t match_escalation_threshold; + + /* lifetime portion */ + grn_proc_func *finalizer; + + grn_obj *db; + grn_array *values; /* temporary objects */ + grn_pat *temporary_columns; + grn_hash *ios; /* IOs */ + grn_com *com; + unsigned int com_status; + + grn_obj query_log_buf; + + char previous_errbuf[GRN_CTX_MSGSIZE]; + unsigned int n_same_error_messages; + + grn_mrb_data mrb; + + struct { + grn_obj stack; + grn_obj *current; + } temporary_open_spaces; +}; + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h new file mode 100644 index 00000000..e3d619ab --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_ctx_impl_mrb.h @@ -0,0 +1,35 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_ctx_impl_mrb_init_from_env(void); +void grn_ctx_impl_mrb_init(grn_ctx *ctx); +void grn_ctx_impl_mrb_fin(grn_ctx *ctx); +GRN_API void grn_ctx_impl_mrb_ensure_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_dat.h b/storage/mroonga/vendor/groonga/lib/grn_dat.h new file mode 100644 index 00000000..7d0d0c8d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_dat.h @@ -0,0 +1,95 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2011-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _grn_dat { + grn_db_obj obj; + grn_io *io; + struct grn_dat_header *header; + uint32_t file_id; + grn_encoding encoding; + void *trie; + void *old_trie; + grn_obj *tokenizer; + grn_obj *normalizer; + grn_obj token_filters; + grn_critical_section lock; + grn_bool is_dirty; +}; + +struct grn_dat_header { + uint32_t flags; + grn_encoding encoding; + grn_id tokenizer; + uint32_t file_id; + grn_id normalizer; + uint32_t n_dirty_opens; + uint32_t reserved[234]; +}; + +struct _grn_dat_cursor { + grn_db_obj obj; + grn_dat *dat; + void *cursor; + const void *key; + grn_id curr_rec; +}; + +GRN_API grn_id grn_dat_curr_id(grn_ctx *ctx, grn_dat *dat); + +/* + Currently, grn_dat_truncate() is available if the grn_dat object is + associated with a file. + */ +GRN_API grn_rc grn_dat_truncate(grn_ctx *ctx, grn_dat *dat); + +GRN_API const char *_grn_dat_key(grn_ctx *ctx, grn_dat *dat, grn_id id, + uint32_t *key_size); +GRN_API grn_id grn_dat_next(grn_ctx *ctx, grn_dat *dat, grn_id id); +GRN_API grn_id grn_dat_at(grn_ctx *ctx, grn_dat *dat, grn_id id); + +GRN_API grn_rc grn_dat_clear_status_flags(grn_ctx *ctx, grn_dat *dat); + +/* + Currently, grn_dat_repair() is available if the grn_dat object is associated + with a file. + */ +GRN_API grn_rc grn_dat_repair(grn_ctx *ctx, grn_dat *dat); + +GRN_API grn_rc grn_dat_flush(grn_ctx *ctx, grn_dat *dat); + +grn_rc grn_dat_dirty(grn_ctx *ctx, grn_dat *dat); +grn_bool grn_dat_is_dirty(grn_ctx *ctx, grn_dat *dat); +grn_rc grn_dat_clean(grn_ctx *ctx, grn_dat *dat); +grn_rc grn_dat_clear_dirty(grn_ctx *ctx, grn_dat *dat); + +grn_bool grn_dat_is_corrupt(grn_ctx *ctx, grn_dat *dat); + +size_t grn_dat_get_disk_usage(grn_ctx *ctx, grn_dat *dat); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_db.h b/storage/mroonga/vendor/groonga/lib/grn_db.h new file mode 100644 index 00000000..d3a6b48b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_db.h @@ -0,0 +1,493 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" +#include "grn_store.h" +#include "grn_rset.h" + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_DB_DELIMITER '.' +#define GRN_DB_PSEUDO_COLUMN_PREFIX '_' + +#define GRN_N_RESERVED_TYPES 256 + +typedef struct _grn_db grn_db; +typedef struct _grn_proc grn_proc; + +struct _grn_db { + grn_db_obj obj; + grn_obj *keys; + grn_ja *specs; + grn_hash *config; + grn_tiny_array values; + grn_critical_section lock; +}; + +#define GRN_SERIALIZED_SPEC_INDEX_SPEC 0 +#define GRN_SERIALIZED_SPEC_INDEX_PATH 1 +#define GRN_SERIALIZED_SPEC_INDEX_SOURCE 2 +#define GRN_SERIALIZED_SPEC_INDEX_HOOK 3 +#define GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS 4 +#define GRN_SERIALIZED_SPEC_INDEX_EXPR 4 + +typedef struct { + grn_obj_header header; + grn_id range; +} grn_obj_spec; + +grn_bool grn_db_spec_unpack(grn_ctx *ctx, + grn_id id, + void *encoded_spec, + uint32_t encoded_spec_size, + grn_obj_spec **spec, + grn_obj *decoded_spec, + const char *error_message_tag); + +#define GRN_DB_SPEC_EACH_BEGIN(ctx, cursor, id, spec) do { \ + grn_obj *db = grn_ctx_db((ctx)); \ + grn_db *db_raw = (grn_db *)db; \ + grn_obj decoded_spec; \ + grn_io_win iw; \ + grn_bool iw_need_unref = GRN_FALSE; \ + GRN_OBJ_INIT(&decoded_spec, GRN_VECTOR, 0, GRN_DB_TEXT); \ + GRN_TABLE_EACH_BEGIN((ctx), db, cursor, id) { \ + void *encoded_spec; \ + uint32_t encoded_spec_size; \ + grn_bool success; \ + grn_obj_spec *spec; \ + \ + if (iw_need_unref) { \ + grn_ja_unref(ctx, &iw); \ + iw_need_unref = GRN_FALSE; \ + } \ + encoded_spec = grn_ja_ref((ctx), \ + db_raw->specs, \ + id, \ + &iw, \ + &encoded_spec_size); \ + if (!encoded_spec) { \ + continue; \ + } \ + iw_need_unref = GRN_TRUE; \ + \ + GRN_BULK_REWIND(&decoded_spec); \ + success = grn_db_spec_unpack(ctx, \ + id, \ + encoded_spec, \ + encoded_spec_size, \ + &spec, \ + &decoded_spec, \ + __FUNCTION__); \ + if (!success) { \ + continue; \ + } \ + +#define GRN_DB_SPEC_EACH_END(ctx, cursor) \ + } GRN_TABLE_EACH_END(ctx, cursor); \ + if (iw_need_unref) { \ + grn_ja_unref(ctx, &iw); \ + } \ + GRN_OBJ_FIN((ctx), &decoded_spec); \ +} while(GRN_FALSE) + +void grn_db_init_from_env(void); + +GRN_API grn_rc grn_db_close(grn_ctx *ctx, grn_obj *db); + +grn_obj *grn_db_keys(grn_obj *s); + +void grn_db_generate_pathname(grn_ctx *ctx, + grn_obj *db, + grn_id id, + char *buffer); + +grn_rc _grn_table_delete_by_id(grn_ctx *ctx, grn_obj *table, grn_id id, + grn_table_delete_optarg *optarg); + +grn_id grn_table_get_v(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, + void **value); +grn_id grn_table_add_v(grn_ctx *ctx, grn_obj *table, const void *key, int key_size, + void **value, int *added); +grn_id grn_table_add_by_key(grn_ctx *ctx, + grn_obj *table, + grn_obj *key, + int *added); +GRN_API grn_rc grn_table_get_info(grn_ctx *ctx, grn_obj *table, grn_table_flags *flags, + grn_encoding *encoding, grn_obj **tokenizer, + grn_obj **normalizer, + grn_obj **token_filters); +const char *_grn_table_key(grn_ctx *ctx, grn_obj *table, grn_id id, uint32_t *key_size); + +grn_rc grn_table_search(grn_ctx *ctx, grn_obj *table, + const void *key, uint32_t key_size, + grn_operator mode, grn_obj *res, grn_operator op); + +grn_rc grn_table_fuzzy_search(grn_ctx *ctx, grn_obj *table, + const void *key, uint32_t key_size, + grn_fuzzy_search_optarg *args, grn_obj *res, grn_operator op); + +grn_id grn_table_next(grn_ctx *ctx, grn_obj *table, grn_id id); + +int grn_table_get_key2(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *bulk); + +grn_table_cursor *grn_table_cursor_open_by_id(grn_ctx *ctx, grn_obj *table, + grn_id min, grn_id max, int flags); + +void grn_table_add_subrec(grn_obj *table, grn_rset_recinfo *ri, double score, + grn_rset_posinfo *pi, int dir); + +grn_obj *grn_obj_graft(grn_ctx *ctx, grn_obj *obj); + +grn_rc grn_column_name_(grn_ctx *ctx, grn_obj *obj, grn_obj *buf); + + +typedef enum { + PROC_INIT = 0, + PROC_NEXT, + PROC_FIN +} grn_proc_phase; + +struct _grn_type { + grn_db_obj obj; +}; + +#define GRN_TYPE_SIZE(type) ((type)->range) + +#define GRN_TABLE_SORT_GEO (0x02<<0) + +#define GRN_OBJ_TMP_OBJECT 0x80000000 +#define GRN_OBJ_TMP_COLUMN 0x40000000 + +#define GRN_DB_OBJP(obj) \ + (obj &&\ + ((GRN_SNIP == ((grn_db_obj *)obj)->header.type) ||\ + ((GRN_CURSOR_TABLE_HASH_KEY <= ((grn_db_obj *)obj)->header.type) &&\ + (((grn_db_obj *)obj)->header.type <= GRN_COLUMN_INDEX)))) + +#define GRN_OBJ_TABLEP(obj) \ + (obj &&\ + (GRN_TABLE_HASH_KEY <= ((grn_db_obj *)obj)->header.type) &&\ + (((grn_db_obj *)obj)->header.type <= GRN_DB)) + +#define GRN_OBJ_INDEX_COLUMNP(obj) \ + (obj &&\ + DB_OBJ(obj)->header.type == GRN_COLUMN_INDEX) + +#define GRN_OBJ_VECTOR_COLUMNP(obj) \ + (obj &&\ + DB_OBJ(obj)->header.type == GRN_COLUMN_VAR_SIZE &&\ + (DB_OBJ(obj)->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) + +#define GRN_OBJ_WEIGHT_VECTOR_COLUMNP(obj) \ + (GRN_OBJ_VECTOR_COLUMNP(obj) &&\ + (DB_OBJ(obj)->header.flags & GRN_OBJ_WITH_WEIGHT)) + +struct _grn_hook { + grn_hook *next; + grn_proc *proc; + uint32_t hld_size; +}; + +typedef struct _grn_proc_ctx grn_proc_ctx; + +struct _grn_proc_ctx { + grn_user_data user_data; + grn_proc *proc; + grn_obj *caller; + // grn_obj *obj; + grn_hook *hooks; + grn_hook *currh; + grn_proc_phase phase; + unsigned short nargs; + unsigned short offset; + grn_user_data data[16]; +}; + +struct _grn_proc { + grn_db_obj obj; + grn_obj name_buf; + grn_expr_var *vars; + uint32_t nvars; + /* -- compatible with grn_expr -- */ + grn_proc_type type; + grn_proc_func *funcs[3]; + + union { + struct { + grn_selector_func *selector; + grn_operator selector_op; + grn_bool is_stable; + } function; + struct { + grn_command_run_func *run; + } command; + struct { + grn_token_filter_init_func *init; + grn_token_filter_filter_func *filter; + grn_token_filter_fin_func *fin; + } token_filter; + struct { + grn_scorer_score_func *score; + } scorer; + grn_window_function_func *window_function; + } callbacks; + + void *user_data; + + grn_id module; + // uint32_t nargs; + // uint32_t nresults; + // grn_obj results[16]; +}; + +#define GRN_PROC_GET_VARS() (grn_proc_get_vars(ctx, user_data)) +#define GRN_PROC_GET_VAR(name) (grn_proc_get_var(ctx, user_data, name, strlen(name))) +#define GRN_PROC_GET_VAR_BY_OFFSET(offset) (grn_proc_get_var_by_offset(ctx, user_data, offset)) +#define GRN_PROC_GET_OR_ADD_VAR(name) (grn_proc_get_or_add_var(ctx, user_data, name, strlen(name))) +#define GRN_PROC_ALLOC(domain, flags) (grn_proc_alloc(ctx, user_data, domain, flags)) + +grn_obj *grn_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data); + +grn_obj *grn_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, + const char *name, unsigned int name_size); + +GRN_API grn_obj *grn_proc_get_var_by_offset(grn_ctx *ctx, grn_user_data *user_data, + unsigned int offset); +GRN_API grn_obj *grn_proc_get_or_add_var(grn_ctx *ctx, grn_user_data *user_data, + const char *name, unsigned int name_size); + +GRN_API grn_obj *grn_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, + grn_id domain, unsigned char flags); + +GRN_API grn_rc grn_proc_call(grn_ctx *ctx, grn_obj *proc, + int nargs, grn_obj *caller); + +grn_obj *grn_expr_get_or_add_var(grn_ctx *ctx, grn_obj *expr, + const char *name, unsigned int name_size); + + +typedef struct _grn_accessor grn_accessor; + +struct _grn_accessor { + grn_obj_header header; + grn_id range; + /* -- compatible with grn_db_obj -- */ + uint8_t action; + int offset; + grn_obj *obj; + grn_accessor *next; +}; + +enum { + GRN_ACCESSOR_VOID = 0, + GRN_ACCESSOR_GET_ID, + GRN_ACCESSOR_GET_KEY, + GRN_ACCESSOR_GET_VALUE, + GRN_ACCESSOR_GET_SCORE, + GRN_ACCESSOR_GET_NSUBRECS, + GRN_ACCESSOR_GET_MAX, + GRN_ACCESSOR_GET_MIN, + GRN_ACCESSOR_GET_SUM, + GRN_ACCESSOR_GET_AVG, + GRN_ACCESSOR_GET_COLUMN_VALUE, + GRN_ACCESSOR_GET_DB_OBJ, + GRN_ACCESSOR_LOOKUP, + GRN_ACCESSOR_FUNCALL +}; + +#define DB_OBJ(obj) ((grn_db_obj *)obj) + +GRN_API const char *grn_obj_get_value_(grn_ctx *ctx, grn_obj *obj, grn_id id, uint32_t *size); + +/* vector */ + +/* +typedef struct _grn_vector grn_vector; + +struct _grn_vector { + grn_obj str; + uint32_t *offsets; + int n_entries; +}; + +const char *grn_vector_fetch(grn_ctx *ctx, grn_obj *vector, int i, unsigned int *size); +int grn_vector_delimit(grn_ctx *ctx, grn_obj *vector); +int grn_vector_size(grn_ctx *ctx, grn_obj *vector); +*/ + +grn_rc grn_vector_delimit(grn_ctx *ctx, grn_obj *v, unsigned int weight, grn_id domain); +grn_rc grn_vector_decode(grn_ctx *ctx, grn_obj *v, const char *data, uint32_t data_size); + + +grn_rc grn_db_init_builtin_types(grn_ctx *ctx); + +/* flag value used for grn_obj.header.flags */ + +#define GRN_OBJ_CUSTOM_NAME (0x01<<12) /* db_obj which has custom name */ + +#define GRN_OBJ_RESOLVE(ctx,obj) \ + (((obj)->header.type != GRN_PTR)\ + ? (obj)\ + : GRN_PTR_VALUE(obj)\ + ? GRN_PTR_VALUE(obj)\ + : grn_ctx_at((ctx), (obj)->header.domain)) + +/* expr */ + +typedef struct _grn_expr grn_expr; + +#define GRN_EXPR_CODE_RELATIONAL_EXPRESSION (0x01) + +typedef struct { + grn_obj *value; + int32_t nargs; + grn_operator op; + uint8_t flags; + int32_t modify; +} grn_expr_code; + +#define GRN_EXPR_CONST_BLK_SIZE GRN_STACK_SIZE + +struct _grn_expr { + grn_db_obj obj; + grn_obj name_buf; + grn_expr_var *vars; + uint32_t nvars; + /* -- compatible with grn_proc -- */ + + uint16_t cacheable; + uint16_t taintable; + grn_obj **const_blks; + grn_obj *values; + grn_expr_code *codes; + uint32_t nconsts; + uint32_t values_curr; + uint32_t values_tail; + uint32_t values_size; + uint32_t codes_curr; + uint32_t codes_size; + + grn_obj objs; + grn_obj dfi; + grn_expr_code *code0; +}; + +grn_rc grn_expr_parser_close(grn_ctx *ctx); + +/** + * grn_table_open: + * @name: The table name to be opened. `NULL` means anonymous table. + * @path: The path of the table to be opened. + * + * Opens an existing table. The table is associated with @name in DB + * that is used by @ctx. grn_ctx_get() is better rather than this + * function when you want to open a permanent named table that is + * registered in DB. + **/ +GRN_API grn_obj *grn_table_open(grn_ctx *ctx, + const char *name, unsigned int name_size, + const char *path); + +/** + * grn_column_open: + * @table: The table for the opened column. + * @name: The column name to be opened. + * @path: The path of the column to be opened. + * @type: The type of the column value. + * + * Opens an existing permanent column. The column is associated with + * @name in @table. grn_ctx_get() is better rather than this function + * when you want to open a column of an permanent table in DB. + **/ +grn_obj *grn_column_open(grn_ctx *ctx, grn_obj *table, + const char *name, unsigned int name_size, + const char *path, grn_obj *type); + +/** + * grn_obj_path_rename: + * @old_path: The current file path. + * @new_path: The new file path. + * + * It renames object's path that is stored in @old_path to @new_path. + **/ +grn_rc grn_obj_path_rename(grn_ctx *ctx, const char *old_path, const char *new_path); + +grn_rc grn_db_check_name(grn_ctx *ctx, const char *name, unsigned int name_size); +#define GRN_DB_CHECK_NAME_ERR(error_context, name, name_size) \ + ERR(GRN_INVALID_ARGUMENT,\ + "%s name can't start with '%c' and contains only 0-9, A-Z, a-z, #, @, - or _: <%.*s>",\ + error_context, GRN_DB_PSEUDO_COLUMN_PREFIX, name_size, name) + +#define GRN_DB_P(s) ((s) && ((grn_db *)s)->obj.header.type == GRN_DB) +#define GRN_DB_PERSISTENT_P(s) (((grn_db *)s)->specs) + +#define GRN_OBJ_GET_VALUE_IMD (0xffffffffU) + +grn_rc grn_db_obj_init(grn_ctx *ctx, grn_obj *db, grn_id id, grn_db_obj *obj); + +#define GRN_ACCESSORP(obj) \ + ((obj) && (((grn_obj *)(obj))->header.type == GRN_ACCESSOR)) + +grn_id grn_obj_register(grn_ctx *ctx, grn_obj *db, const char *name, unsigned int name_size); +int grn_obj_is_persistent(grn_ctx *ctx, grn_obj *obj); +void grn_obj_spec_save(grn_ctx *ctx, grn_db_obj *obj); + +grn_rc grn_obj_reinit_for(grn_ctx *ctx, grn_obj *obj, grn_obj *domain_obj); + +void grn_expr_pack(grn_ctx *ctx, grn_obj *buf, grn_obj *expr); +GRN_API grn_rc grn_expr_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *expr); +grn_hash *grn_expr_get_vars(grn_ctx *ctx, grn_obj *expr, unsigned int *nvars); +grn_obj *grn_expr_open(grn_ctx *ctx, grn_obj_spec *spec, const uint8_t *p, const uint8_t *pe); + +GRN_API grn_rc grn_table_group_with_range_gap(grn_ctx *ctx, grn_obj *table, + grn_table_sort_key *group_key, + grn_obj *result_set, + uint32_t range_gap); + +GRN_API grn_rc grn_column_filter(grn_ctx *ctx, grn_obj *column, + grn_operator op, + grn_obj *value, grn_obj *result_set, + grn_operator set_op); + +typedef struct { + grn_id target; + unsigned int section; +} grn_obj_default_set_value_hook_data; + +grn_obj *grn_obj_default_set_value_hook(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data); + +grn_rc grn_pvector_fin(grn_ctx *ctx, grn_obj *obj); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_ecmascript.c b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.c new file mode 100644 index 00000000..cfabcc91 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.c @@ -0,0 +1,2542 @@ +/* +** 2000-05-29 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** Driver template for the LEMON parser generator. +** +** The "lemon" program processes an LALR(1) input grammar file, then uses +** this template to construct a parser. The "lemon" program inserts text +** at each "%%" line. Also, any "P-a-r-s-e" identifer prefix (without the +** interstitial "-" characters) contained in this template is changed into +** the value of the %name directive from the grammar. Otherwise, the content +** of this template is copied straight through into the generate parser +** source file. +** +** The following is the concatenation of all %include directives from the +** input grammar file: +*/ +#include +/************ Begin %include sections from the grammar ************************/ +#line 4 "grn_ecmascript.lemon" + +#ifdef assert +# undef assert +#endif +#define assert GRN_ASSERT +#line 34 "grn_ecmascript.c" +/**************** End of %include directives **********************************/ +/* These constants specify the various numeric values for terminal symbols +** in a format understandable to "makeheaders". This section is blank unless +** "lemon" is run with the "-m" command-line option. +***************** Begin makeheaders token definitions *************************/ +/**************** End makeheaders token definitions ***************************/ + +/* The next sections is a series of control #defines. +** various aspects of the generated parser. +** YYCODETYPE is the data type used to store the integer codes +** that represent terminal and non-terminal symbols. +** "unsigned char" is used if there are fewer than +** 256 symbols. Larger types otherwise. +** YYNOCODE is a number of type YYCODETYPE that is not used for +** any terminal or nonterminal symbol. +** YYFALLBACK If defined, this indicates that one or more tokens +** (also known as: "terminal symbols") have fall-back +** values which should be used if the original symbol +** would not parse. This permits keywords to sometimes +** be used as identifiers, for example. +** YYACTIONTYPE is the data type used for "action codes" - numbers +** that indicate what to do in response to the next +** token. +** grn_expr_parserTOKENTYPE is the data type used for minor type for terminal +** symbols. Background: A "minor type" is a semantic +** value associated with a terminal or non-terminal +** symbols. For example, for an "ID" terminal symbol, +** the minor type might be the name of the identifier. +** Each non-terminal can have a different minor type. +** Terminal symbols all have the same minor type, though. +** This macros defines the minor type for terminal +** symbols. +** YYMINORTYPE is the data type used for all minor types. +** This is typically a union of many types, one of +** which is grn_expr_parserTOKENTYPE. The entry in the union +** for terminal symbols is called "yy0". +** YYSTACKDEPTH is the maximum depth of the parser's stack. If +** zero the stack is dynamically sized using realloc() +** grn_expr_parserARG_SDECL A static variable declaration for the %extra_argument +** grn_expr_parserARG_PDECL A parameter declaration for the %extra_argument +** grn_expr_parserARG_STORE Code to store %extra_argument into yypParser +** grn_expr_parserARG_FETCH Code to extract %extra_argument from yypParser +** YYERRORSYMBOL is the code number of the error symbol. If not +** defined, then do no error processing. +** YYNSTATE the combined number of states. +** YYNRULE the number of rules in the grammar +** YY_MAX_SHIFT Maximum value for shift actions +** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions +** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions +** YY_MIN_REDUCE Maximum value for reduce actions +** YY_ERROR_ACTION The yy_action[] code for syntax error +** YY_ACCEPT_ACTION The yy_action[] code for accept +** YY_NO_ACTION The yy_action[] code for no-op +*/ +#ifndef INTERFACE +# define INTERFACE 1 +#endif +/************* Begin control #defines *****************************************/ +#define YYCODETYPE unsigned char +#define YYNOCODE 115 +#define YYACTIONTYPE unsigned short int +#define grn_expr_parserTOKENTYPE int +typedef union { + int yyinit; + grn_expr_parserTOKENTYPE yy0; + void * yy217; +} YYMINORTYPE; +#ifndef YYSTACKDEPTH +#define YYSTACKDEPTH 100 +#endif +#define grn_expr_parserARG_SDECL efs_info *efsi ; +#define grn_expr_parserARG_PDECL , efs_info *efsi +#define grn_expr_parserARG_FETCH efs_info *efsi = yypParser->efsi +#define grn_expr_parserARG_STORE yypParser->efsi = efsi +#define YYNSTATE 145 +#define YYNRULE 136 +#define YY_MAX_SHIFT 144 +#define YY_MIN_SHIFTREDUCE 232 +#define YY_MAX_SHIFTREDUCE 367 +#define YY_MIN_REDUCE 368 +#define YY_MAX_REDUCE 503 +#define YY_ERROR_ACTION 504 +#define YY_ACCEPT_ACTION 505 +#define YY_NO_ACTION 506 +/************* End control #defines *******************************************/ + +/* Define the yytestcase() macro to be a no-op if is not already defined +** otherwise. +** +** Applications can choose to define yytestcase() in the %include section +** to a macro that can assist in verifying code coverage. For production +** code the yytestcase() macro should be turned off. But it is useful +** for testing. +*/ +#ifndef yytestcase +# define yytestcase(X) +#endif + + +/* Next are the tables used to determine what action to take based on the +** current state and lookahead token. These tables are used to implement +** functions that take a state number and lookahead value and return an +** action integer. +** +** Suppose the action integer is N. Then the action is determined as +** follows +** +** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead +** token onto the stack and goto state N. +** +** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then +** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE. +** +** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE +** and YY_MAX_REDUCE +** +** N == YY_ERROR_ACTION A syntax error has occurred. +** +** N == YY_ACCEPT_ACTION The parser accepts its input. +** +** N == YY_NO_ACTION No such action. Denotes unused +** slots in the yy_action[] table. +** +** The action table is constructed as a single large table named yy_action[]. +** Given state S and lookahead X, the action is computed as either: +** +** (A) N = yy_action[ yy_shift_ofst[S] + X ] +** (B) N = yy_default[S] +** +** The (A) formula is preferred. The B formula is used instead if: +** (1) The yy_shift_ofst[S]+X value is out of range, or +** (2) yy_lookahead[yy_shift_ofst[S]+X] is not equal to X, or +** (3) yy_shift_ofst[S] equal YY_SHIFT_USE_DFLT. +** (Implementation note: YY_SHIFT_USE_DFLT is chosen so that +** YY_SHIFT_USE_DFLT+X will be out of range for all possible lookaheads X. +** Hence only tests (1) and (2) need to be evaluated.) +** +** The formulas above are for computing the action when the lookahead is +** a terminal symbol. If the lookahead is a non-terminal (as occurs after +** a reduce action) then the yy_reduce_ofst[] array is used in place of +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of +** YY_SHIFT_USE_DFLT. +** +** The following are the tables generated in this section: +** +** yy_action[] A single table containing all actions. +** yy_lookahead[] A table containing the lookahead for each entry in +** yy_action. Used to detect hash collisions. +** yy_shift_ofst[] For each state, the offset into yy_action for +** shifting terminals. +** yy_reduce_ofst[] For each state, the offset into yy_action for +** shifting non-terminals after a reduce. +** yy_default[] Default action for each state. +** +*********** Begin parsing tables **********************************************/ +#define YY_ACTTAB_COUNT (1794) +static const YYACTIONTYPE yy_action[] = { + /* 0 */ 3, 72, 115, 115, 136, 131, 323, 2, 363, 54, + /* 10 */ 83, 129, 1, 232, 71, 505, 79, 112, 10, 241, + /* 20 */ 79, 75, 112, 112, 91, 126, 125, 139, 138, 137, + /* 30 */ 120, 88, 103, 116, 104, 104, 104, 91, 75, 241, + /* 40 */ 241, 75, 75, 323, 74, 457, 84, 83, 144, 9, + /* 50 */ 236, 71, 66, 65, 53, 52, 51, 69, 68, 67, + /* 60 */ 64, 63, 61, 60, 59, 348, 349, 350, 351, 352, + /* 70 */ 4, 127, 70, 58, 57, 75, 127, 127, 91, 126, + /* 80 */ 125, 139, 138, 137, 120, 88, 103, 116, 104, 104, + /* 90 */ 104, 91, 75, 78, 456, 75, 75, 78, 76, 115, + /* 100 */ 115, 136, 235, 323, 2, 499, 54, 83, 129, 1, + /* 110 */ 5, 71, 78, 118, 110, 82, 78, 75, 118, 118, + /* 120 */ 91, 126, 125, 139, 138, 137, 120, 88, 103, 116, + /* 130 */ 104, 104, 104, 91, 75, 315, 133, 75, 75, 7, + /* 140 */ 300, 62, 77, 346, 73, 110, 133, 362, 136, 66, + /* 150 */ 65, 299, 343, 239, 69, 68, 67, 64, 63, 61, + /* 160 */ 60, 59, 348, 349, 350, 351, 352, 4, 50, 49, + /* 170 */ 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, + /* 180 */ 38, 37, 31, 30, 66, 65, 312, 56, 55, 69, + /* 190 */ 68, 67, 64, 63, 61, 60, 59, 348, 349, 350, + /* 200 */ 351, 352, 4, 111, 238, 313, 75, 314, 314, 91, + /* 210 */ 126, 125, 139, 138, 137, 120, 88, 103, 116, 104, + /* 220 */ 104, 104, 91, 75, 36, 35, 75, 75, 7, 237, + /* 230 */ 62, 6, 346, 73, 309, 240, 357, 28, 75, 87, + /* 240 */ 87, 91, 126, 125, 139, 138, 137, 120, 88, 103, + /* 250 */ 116, 104, 104, 104, 91, 75, 304, 234, 75, 75, + /* 260 */ 11, 87, 7, 23, 62, 233, 346, 73, 297, 298, + /* 270 */ 357, 7, 356, 66, 65, 346, 73, 130, 69, 68, + /* 280 */ 67, 64, 63, 61, 60, 59, 348, 349, 350, 351, + /* 290 */ 352, 4, 354, 7, 8, 62, 135, 346, 73, 345, + /* 300 */ 317, 356, 32, 29, 316, 132, 28, 66, 65, 364, + /* 310 */ 24, 34, 69, 68, 67, 64, 63, 61, 60, 59, + /* 320 */ 348, 349, 350, 351, 352, 4, 353, 26, 355, 348, + /* 330 */ 349, 350, 351, 352, 4, 33, 25, 370, 66, 65, + /* 340 */ 370, 370, 370, 69, 68, 67, 64, 63, 61, 60, + /* 350 */ 59, 348, 349, 350, 351, 352, 4, 75, 314, 314, + /* 360 */ 91, 126, 125, 139, 138, 137, 120, 88, 103, 116, + /* 370 */ 104, 104, 104, 91, 75, 370, 370, 75, 75, 370, + /* 380 */ 370, 370, 370, 370, 370, 311, 28, 370, 370, 370, + /* 390 */ 370, 75, 306, 306, 91, 126, 125, 139, 138, 137, + /* 400 */ 120, 88, 103, 116, 104, 104, 104, 91, 75, 370, + /* 410 */ 370, 75, 75, 370, 370, 370, 370, 370, 114, 118, + /* 420 */ 370, 370, 370, 75, 118, 118, 91, 126, 125, 139, + /* 430 */ 138, 137, 120, 88, 103, 116, 104, 104, 104, 91, + /* 440 */ 75, 121, 303, 75, 75, 75, 121, 121, 91, 126, + /* 450 */ 125, 139, 138, 137, 120, 88, 103, 116, 104, 104, + /* 460 */ 104, 91, 75, 370, 370, 75, 75, 370, 7, 370, + /* 470 */ 62, 127, 346, 73, 370, 75, 127, 127, 91, 126, + /* 480 */ 125, 139, 138, 137, 120, 88, 103, 116, 104, 104, + /* 490 */ 104, 91, 75, 455, 370, 75, 75, 7, 370, 62, + /* 500 */ 370, 346, 73, 370, 370, 370, 370, 370, 370, 28, + /* 510 */ 370, 370, 370, 66, 65, 370, 370, 370, 69, 68, + /* 520 */ 67, 64, 63, 61, 60, 59, 348, 349, 128, 351, + /* 530 */ 352, 4, 370, 370, 370, 370, 370, 370, 370, 370, + /* 540 */ 370, 370, 66, 65, 370, 370, 370, 69, 68, 67, + /* 550 */ 64, 63, 61, 60, 59, 348, 349, 350, 351, 352, + /* 560 */ 4, 75, 360, 360, 91, 126, 125, 139, 138, 137, + /* 570 */ 120, 88, 103, 116, 104, 104, 104, 91, 75, 370, + /* 580 */ 370, 75, 75, 75, 359, 359, 91, 126, 125, 139, + /* 590 */ 138, 137, 120, 88, 103, 116, 104, 104, 104, 91, + /* 600 */ 75, 370, 370, 75, 75, 75, 254, 254, 91, 126, + /* 610 */ 125, 139, 138, 137, 120, 88, 103, 116, 104, 104, + /* 620 */ 104, 91, 75, 370, 370, 75, 75, 75, 253, 253, + /* 630 */ 91, 126, 125, 139, 138, 137, 120, 88, 103, 116, + /* 640 */ 104, 104, 104, 91, 75, 370, 370, 75, 75, 75, + /* 650 */ 252, 252, 91, 126, 125, 139, 138, 137, 120, 88, + /* 660 */ 103, 116, 104, 104, 104, 91, 75, 370, 370, 75, + /* 670 */ 75, 75, 251, 251, 91, 126, 125, 139, 138, 137, + /* 680 */ 120, 88, 103, 116, 104, 104, 104, 91, 75, 370, + /* 690 */ 370, 75, 75, 75, 250, 250, 91, 126, 125, 139, + /* 700 */ 138, 137, 120, 88, 103, 116, 104, 104, 104, 91, + /* 710 */ 75, 370, 370, 75, 75, 75, 249, 249, 91, 126, + /* 720 */ 125, 139, 138, 137, 120, 88, 103, 116, 104, 104, + /* 730 */ 104, 91, 75, 370, 370, 75, 75, 75, 248, 248, + /* 740 */ 91, 126, 125, 139, 138, 137, 120, 88, 103, 116, + /* 750 */ 104, 104, 104, 91, 75, 370, 370, 75, 75, 75, + /* 760 */ 247, 247, 91, 126, 125, 139, 138, 137, 120, 88, + /* 770 */ 103, 116, 104, 104, 104, 91, 75, 370, 370, 75, + /* 780 */ 75, 75, 246, 246, 91, 126, 125, 139, 138, 137, + /* 790 */ 120, 88, 103, 116, 104, 104, 104, 91, 75, 370, + /* 800 */ 370, 75, 75, 75, 245, 245, 91, 126, 125, 139, + /* 810 */ 138, 137, 120, 88, 103, 116, 104, 104, 104, 91, + /* 820 */ 75, 370, 370, 75, 75, 75, 244, 244, 91, 126, + /* 830 */ 125, 139, 138, 137, 120, 88, 103, 116, 104, 104, + /* 840 */ 104, 91, 75, 370, 370, 75, 75, 75, 307, 307, + /* 850 */ 91, 126, 125, 139, 138, 137, 120, 88, 103, 116, + /* 860 */ 104, 104, 104, 91, 75, 370, 370, 75, 75, 75, + /* 870 */ 302, 302, 91, 126, 125, 139, 138, 137, 120, 88, + /* 880 */ 103, 116, 104, 104, 104, 91, 75, 370, 370, 75, + /* 890 */ 75, 75, 255, 255, 91, 126, 125, 139, 138, 137, + /* 900 */ 120, 88, 103, 116, 104, 104, 104, 91, 75, 370, + /* 910 */ 370, 75, 75, 75, 143, 143, 91, 126, 125, 139, + /* 920 */ 138, 137, 120, 88, 103, 116, 104, 104, 104, 91, + /* 930 */ 75, 370, 370, 75, 75, 75, 243, 243, 91, 126, + /* 940 */ 125, 139, 138, 137, 120, 88, 103, 116, 104, 104, + /* 950 */ 104, 91, 75, 370, 370, 75, 75, 75, 242, 242, + /* 960 */ 91, 126, 125, 139, 138, 137, 120, 88, 103, 116, + /* 970 */ 104, 104, 104, 91, 75, 370, 75, 75, 75, 122, + /* 980 */ 370, 113, 139, 138, 137, 120, 88, 103, 116, 104, + /* 990 */ 104, 104, 122, 75, 370, 75, 75, 75, 122, 370, + /* 1000 */ 370, 134, 138, 137, 120, 88, 103, 116, 104, 104, + /* 1010 */ 104, 122, 75, 370, 75, 75, 75, 122, 370, 370, + /* 1020 */ 142, 138, 137, 120, 88, 103, 116, 104, 104, 104, + /* 1030 */ 122, 75, 370, 75, 75, 75, 122, 370, 370, 370, + /* 1040 */ 141, 137, 120, 88, 103, 116, 104, 104, 104, 122, + /* 1050 */ 75, 370, 75, 75, 75, 122, 370, 370, 370, 370, + /* 1060 */ 140, 120, 88, 103, 116, 104, 104, 104, 122, 75, + /* 1070 */ 370, 370, 75, 75, 370, 370, 370, 370, 27, 22, + /* 1080 */ 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, + /* 1090 */ 75, 370, 370, 122, 370, 370, 370, 370, 370, 124, + /* 1100 */ 88, 103, 116, 104, 104, 104, 122, 75, 370, 370, + /* 1110 */ 75, 75, 75, 370, 370, 122, 370, 370, 370, 370, + /* 1120 */ 297, 298, 89, 103, 116, 104, 104, 104, 122, 75, + /* 1130 */ 370, 75, 75, 75, 122, 370, 370, 370, 370, 370, + /* 1140 */ 370, 90, 103, 116, 104, 104, 104, 122, 75, 370, + /* 1150 */ 370, 75, 75, 370, 370, 86, 85, 81, 80, 323, + /* 1160 */ 74, 324, 84, 83, 144, 9, 454, 71, 370, 86, + /* 1170 */ 85, 81, 80, 323, 74, 370, 84, 83, 144, 9, + /* 1180 */ 370, 71, 370, 75, 370, 370, 122, 370, 370, 370, + /* 1190 */ 370, 370, 370, 370, 92, 116, 104, 104, 104, 122, + /* 1200 */ 75, 370, 370, 75, 75, 75, 370, 370, 122, 370, + /* 1210 */ 370, 370, 370, 370, 370, 370, 93, 116, 104, 104, + /* 1220 */ 104, 122, 75, 370, 370, 75, 75, 75, 370, 370, + /* 1230 */ 122, 370, 370, 370, 370, 370, 370, 370, 94, 116, + /* 1240 */ 104, 104, 104, 122, 75, 370, 75, 75, 75, 122, + /* 1250 */ 370, 370, 370, 370, 370, 370, 370, 95, 116, 104, + /* 1260 */ 104, 104, 122, 75, 370, 75, 75, 75, 122, 370, + /* 1270 */ 370, 370, 370, 370, 370, 370, 96, 116, 104, 104, + /* 1280 */ 104, 122, 75, 370, 75, 75, 75, 122, 370, 370, + /* 1290 */ 370, 370, 370, 370, 370, 97, 116, 104, 104, 104, + /* 1300 */ 122, 75, 370, 75, 75, 75, 122, 370, 370, 370, + /* 1310 */ 370, 370, 370, 370, 98, 116, 104, 104, 104, 122, + /* 1320 */ 75, 370, 75, 75, 75, 122, 370, 370, 370, 370, + /* 1330 */ 370, 370, 370, 99, 116, 104, 104, 104, 122, 75, + /* 1340 */ 370, 75, 75, 75, 122, 370, 370, 370, 370, 370, + /* 1350 */ 370, 370, 100, 116, 104, 104, 104, 122, 75, 370, + /* 1360 */ 75, 75, 75, 122, 370, 370, 370, 370, 370, 370, + /* 1370 */ 370, 101, 116, 104, 104, 104, 122, 75, 370, 75, + /* 1380 */ 75, 75, 122, 370, 370, 370, 370, 370, 370, 370, + /* 1390 */ 102, 116, 104, 104, 104, 122, 75, 370, 75, 75, + /* 1400 */ 75, 122, 370, 370, 370, 370, 370, 370, 370, 105, + /* 1410 */ 116, 104, 104, 104, 122, 75, 370, 75, 75, 75, + /* 1420 */ 122, 370, 370, 370, 370, 370, 370, 370, 107, 116, + /* 1430 */ 104, 104, 104, 122, 75, 370, 75, 75, 75, 122, + /* 1440 */ 370, 370, 370, 370, 370, 370, 370, 109, 116, 104, + /* 1450 */ 104, 104, 122, 75, 370, 75, 75, 75, 122, 370, + /* 1460 */ 370, 370, 370, 370, 370, 370, 370, 117, 104, 104, + /* 1470 */ 104, 122, 75, 370, 75, 75, 75, 122, 370, 370, + /* 1480 */ 370, 370, 370, 370, 370, 370, 119, 104, 104, 104, + /* 1490 */ 122, 75, 370, 75, 75, 75, 122, 370, 370, 370, + /* 1500 */ 237, 75, 370, 370, 122, 123, 104, 104, 104, 122, + /* 1510 */ 75, 370, 370, 75, 75, 293, 293, 122, 75, 370, + /* 1520 */ 75, 75, 75, 122, 370, 370, 370, 370, 370, 370, + /* 1530 */ 370, 370, 370, 106, 106, 106, 122, 75, 370, 75, + /* 1540 */ 75, 75, 122, 370, 370, 370, 370, 370, 370, 370, + /* 1550 */ 370, 370, 108, 108, 108, 122, 75, 370, 75, 75, + /* 1560 */ 75, 122, 370, 370, 370, 370, 370, 370, 370, 370, + /* 1570 */ 370, 370, 285, 285, 122, 75, 370, 75, 75, 75, + /* 1580 */ 122, 370, 370, 370, 370, 75, 370, 370, 122, 370, + /* 1590 */ 370, 284, 284, 122, 75, 370, 370, 75, 75, 296, + /* 1600 */ 296, 122, 75, 370, 75, 75, 75, 122, 370, 370, + /* 1610 */ 370, 370, 370, 370, 370, 370, 370, 370, 295, 295, + /* 1620 */ 122, 75, 370, 75, 75, 75, 122, 370, 370, 370, + /* 1630 */ 370, 370, 370, 370, 370, 370, 370, 294, 294, 122, + /* 1640 */ 75, 370, 75, 75, 75, 122, 370, 370, 370, 370, + /* 1650 */ 370, 370, 370, 370, 370, 370, 293, 293, 122, 75, + /* 1660 */ 370, 75, 75, 75, 122, 370, 370, 370, 370, 75, + /* 1670 */ 370, 370, 122, 370, 370, 292, 292, 122, 75, 370, + /* 1680 */ 370, 75, 75, 291, 291, 122, 75, 370, 75, 75, + /* 1690 */ 75, 122, 370, 370, 370, 370, 370, 370, 370, 370, + /* 1700 */ 370, 370, 290, 290, 122, 75, 370, 75, 75, 75, + /* 1710 */ 122, 370, 370, 370, 370, 370, 370, 370, 370, 370, + /* 1720 */ 370, 289, 289, 122, 75, 370, 75, 75, 75, 122, + /* 1730 */ 370, 370, 370, 370, 370, 370, 370, 370, 370, 370, + /* 1740 */ 288, 288, 122, 75, 370, 75, 75, 75, 122, 370, + /* 1750 */ 370, 370, 370, 75, 370, 370, 122, 370, 370, 287, + /* 1760 */ 287, 122, 75, 370, 370, 75, 75, 286, 286, 122, + /* 1770 */ 75, 370, 75, 75, 75, 122, 370, 370, 370, 370, + /* 1780 */ 370, 370, 370, 370, 370, 370, 283, 283, 122, 75, + /* 1790 */ 370, 370, 75, 75, +}; +static const YYCODETYPE yy_lookahead[] = { + /* 0 */ 1, 2, 107, 108, 109, 12, 7, 8, 68, 10, + /* 10 */ 11, 12, 13, 82, 15, 77, 78, 79, 105, 83, + /* 20 */ 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, + /* 30 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 103, + /* 40 */ 104, 103, 104, 7, 8, 0, 10, 11, 12, 13, + /* 50 */ 82, 15, 53, 54, 50, 51, 52, 58, 59, 60, + /* 60 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + /* 70 */ 71, 79, 55, 56, 57, 83, 84, 85, 86, 87, + /* 80 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + /* 90 */ 98, 99, 100, 78, 0, 103, 104, 82, 53, 107, + /* 100 */ 108, 109, 82, 7, 8, 30, 10, 11, 12, 13, + /* 110 */ 16, 15, 78, 79, 81, 11, 82, 83, 84, 85, + /* 120 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 130 */ 96, 97, 98, 99, 100, 112, 113, 103, 104, 8, + /* 140 */ 14, 10, 16, 12, 13, 112, 113, 108, 109, 53, + /* 150 */ 54, 101, 102, 82, 58, 59, 60, 61, 62, 63, + /* 160 */ 64, 65, 66, 67, 68, 69, 70, 71, 36, 37, + /* 170 */ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + /* 180 */ 48, 49, 3, 4, 53, 54, 55, 53, 54, 58, + /* 190 */ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + /* 200 */ 69, 70, 71, 80, 82, 74, 83, 84, 85, 86, + /* 210 */ 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + /* 220 */ 97, 98, 99, 100, 34, 35, 103, 104, 8, 82, + /* 230 */ 10, 8, 12, 13, 111, 14, 16, 16, 83, 84, + /* 240 */ 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + /* 250 */ 95, 96, 97, 98, 99, 100, 9, 82, 103, 104, + /* 260 */ 105, 106, 8, 16, 10, 82, 12, 13, 59, 60, + /* 270 */ 16, 8, 16, 53, 54, 12, 13, 41, 58, 59, + /* 280 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + /* 290 */ 70, 71, 72, 8, 71, 10, 73, 12, 13, 9, + /* 300 */ 68, 16, 31, 5, 66, 55, 16, 53, 54, 12, + /* 310 */ 30, 33, 58, 59, 60, 61, 62, 63, 64, 65, + /* 320 */ 66, 67, 68, 69, 70, 71, 72, 29, 72, 66, + /* 330 */ 67, 68, 69, 70, 71, 32, 30, 114, 53, 54, + /* 340 */ 114, 114, 114, 58, 59, 60, 61, 62, 63, 64, + /* 350 */ 65, 66, 67, 68, 69, 70, 71, 83, 84, 85, + /* 360 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 370 */ 96, 97, 98, 99, 100, 114, 114, 103, 104, 114, + /* 380 */ 114, 114, 114, 114, 114, 111, 16, 114, 114, 114, + /* 390 */ 114, 83, 84, 85, 86, 87, 88, 89, 90, 91, + /* 400 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 114, + /* 410 */ 114, 103, 104, 114, 114, 114, 114, 114, 110, 79, + /* 420 */ 114, 114, 114, 83, 84, 85, 86, 87, 88, 89, + /* 430 */ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + /* 440 */ 100, 79, 72, 103, 104, 83, 84, 85, 86, 87, + /* 450 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + /* 460 */ 98, 99, 100, 114, 114, 103, 104, 114, 8, 114, + /* 470 */ 10, 79, 12, 13, 114, 83, 84, 85, 86, 87, + /* 480 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + /* 490 */ 98, 99, 100, 0, 114, 103, 104, 8, 114, 10, + /* 500 */ 114, 12, 13, 114, 114, 114, 114, 114, 114, 16, + /* 510 */ 114, 114, 114, 53, 54, 114, 114, 114, 58, 59, + /* 520 */ 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, + /* 530 */ 70, 71, 114, 114, 114, 114, 114, 114, 114, 114, + /* 540 */ 114, 114, 53, 54, 114, 114, 114, 58, 59, 60, + /* 550 */ 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + /* 560 */ 71, 83, 84, 85, 86, 87, 88, 89, 90, 91, + /* 570 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 114, + /* 580 */ 114, 103, 104, 83, 84, 85, 86, 87, 88, 89, + /* 590 */ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + /* 600 */ 100, 114, 114, 103, 104, 83, 84, 85, 86, 87, + /* 610 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + /* 620 */ 98, 99, 100, 114, 114, 103, 104, 83, 84, 85, + /* 630 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 640 */ 96, 97, 98, 99, 100, 114, 114, 103, 104, 83, + /* 650 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + /* 660 */ 94, 95, 96, 97, 98, 99, 100, 114, 114, 103, + /* 670 */ 104, 83, 84, 85, 86, 87, 88, 89, 90, 91, + /* 680 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 114, + /* 690 */ 114, 103, 104, 83, 84, 85, 86, 87, 88, 89, + /* 700 */ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + /* 710 */ 100, 114, 114, 103, 104, 83, 84, 85, 86, 87, + /* 720 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + /* 730 */ 98, 99, 100, 114, 114, 103, 104, 83, 84, 85, + /* 740 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 750 */ 96, 97, 98, 99, 100, 114, 114, 103, 104, 83, + /* 760 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + /* 770 */ 94, 95, 96, 97, 98, 99, 100, 114, 114, 103, + /* 780 */ 104, 83, 84, 85, 86, 87, 88, 89, 90, 91, + /* 790 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 114, + /* 800 */ 114, 103, 104, 83, 84, 85, 86, 87, 88, 89, + /* 810 */ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + /* 820 */ 100, 114, 114, 103, 104, 83, 84, 85, 86, 87, + /* 830 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + /* 840 */ 98, 99, 100, 114, 114, 103, 104, 83, 84, 85, + /* 850 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 860 */ 96, 97, 98, 99, 100, 114, 114, 103, 104, 83, + /* 870 */ 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, + /* 880 */ 94, 95, 96, 97, 98, 99, 100, 114, 114, 103, + /* 890 */ 104, 83, 84, 85, 86, 87, 88, 89, 90, 91, + /* 900 */ 92, 93, 94, 95, 96, 97, 98, 99, 100, 114, + /* 910 */ 114, 103, 104, 83, 84, 85, 86, 87, 88, 89, + /* 920 */ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + /* 930 */ 100, 114, 114, 103, 104, 83, 84, 85, 86, 87, + /* 940 */ 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, + /* 950 */ 98, 99, 100, 114, 114, 103, 104, 83, 84, 85, + /* 960 */ 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + /* 970 */ 96, 97, 98, 99, 100, 114, 83, 103, 104, 86, + /* 980 */ 114, 88, 89, 90, 91, 92, 93, 94, 95, 96, + /* 990 */ 97, 98, 99, 100, 114, 83, 103, 104, 86, 114, + /* 1000 */ 114, 89, 90, 91, 92, 93, 94, 95, 96, 97, + /* 1010 */ 98, 99, 100, 114, 83, 103, 104, 86, 114, 114, + /* 1020 */ 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + /* 1030 */ 99, 100, 114, 83, 103, 104, 86, 114, 114, 114, + /* 1040 */ 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, + /* 1050 */ 100, 114, 83, 103, 104, 86, 114, 114, 114, 114, + /* 1060 */ 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + /* 1070 */ 114, 114, 103, 104, 114, 114, 114, 114, 17, 18, + /* 1080 */ 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + /* 1090 */ 83, 114, 114, 86, 114, 114, 114, 114, 114, 92, + /* 1100 */ 93, 94, 95, 96, 97, 98, 99, 100, 114, 114, + /* 1110 */ 103, 104, 83, 114, 114, 86, 114, 114, 114, 114, + /* 1120 */ 59, 60, 93, 94, 95, 96, 97, 98, 99, 100, + /* 1130 */ 114, 83, 103, 104, 86, 114, 114, 114, 114, 114, + /* 1140 */ 114, 93, 94, 95, 96, 97, 98, 99, 100, 114, + /* 1150 */ 114, 103, 104, 114, 114, 3, 4, 5, 6, 7, + /* 1160 */ 8, 9, 10, 11, 12, 13, 0, 15, 114, 3, + /* 1170 */ 4, 5, 6, 7, 8, 114, 10, 11, 12, 13, + /* 1180 */ 114, 15, 114, 83, 114, 114, 86, 114, 114, 114, + /* 1190 */ 114, 114, 114, 114, 94, 95, 96, 97, 98, 99, + /* 1200 */ 100, 114, 114, 103, 104, 83, 114, 114, 86, 114, + /* 1210 */ 114, 114, 114, 114, 114, 114, 94, 95, 96, 97, + /* 1220 */ 98, 99, 100, 114, 114, 103, 104, 83, 114, 114, + /* 1230 */ 86, 114, 114, 114, 114, 114, 114, 114, 94, 95, + /* 1240 */ 96, 97, 98, 99, 100, 114, 83, 103, 104, 86, + /* 1250 */ 114, 114, 114, 114, 114, 114, 114, 94, 95, 96, + /* 1260 */ 97, 98, 99, 100, 114, 83, 103, 104, 86, 114, + /* 1270 */ 114, 114, 114, 114, 114, 114, 94, 95, 96, 97, + /* 1280 */ 98, 99, 100, 114, 83, 103, 104, 86, 114, 114, + /* 1290 */ 114, 114, 114, 114, 114, 94, 95, 96, 97, 98, + /* 1300 */ 99, 100, 114, 83, 103, 104, 86, 114, 114, 114, + /* 1310 */ 114, 114, 114, 114, 94, 95, 96, 97, 98, 99, + /* 1320 */ 100, 114, 83, 103, 104, 86, 114, 114, 114, 114, + /* 1330 */ 114, 114, 114, 94, 95, 96, 97, 98, 99, 100, + /* 1340 */ 114, 83, 103, 104, 86, 114, 114, 114, 114, 114, + /* 1350 */ 114, 114, 94, 95, 96, 97, 98, 99, 100, 114, + /* 1360 */ 83, 103, 104, 86, 114, 114, 114, 114, 114, 114, + /* 1370 */ 114, 94, 95, 96, 97, 98, 99, 100, 114, 83, + /* 1380 */ 103, 104, 86, 114, 114, 114, 114, 114, 114, 114, + /* 1390 */ 94, 95, 96, 97, 98, 99, 100, 114, 83, 103, + /* 1400 */ 104, 86, 114, 114, 114, 114, 114, 114, 114, 94, + /* 1410 */ 95, 96, 97, 98, 99, 100, 114, 83, 103, 104, + /* 1420 */ 86, 114, 114, 114, 114, 114, 114, 114, 94, 95, + /* 1430 */ 96, 97, 98, 99, 100, 114, 83, 103, 104, 86, + /* 1440 */ 114, 114, 114, 114, 114, 114, 114, 94, 95, 96, + /* 1450 */ 97, 98, 99, 100, 114, 83, 103, 104, 86, 114, + /* 1460 */ 114, 114, 114, 114, 114, 114, 114, 95, 96, 97, + /* 1470 */ 98, 99, 100, 114, 83, 103, 104, 86, 114, 114, + /* 1480 */ 114, 114, 114, 114, 114, 114, 95, 96, 97, 98, + /* 1490 */ 99, 100, 114, 83, 103, 104, 86, 114, 114, 114, + /* 1500 */ 82, 83, 114, 114, 86, 95, 96, 97, 98, 99, + /* 1510 */ 100, 114, 114, 103, 104, 97, 98, 99, 100, 114, + /* 1520 */ 83, 103, 104, 86, 114, 114, 114, 114, 114, 114, + /* 1530 */ 114, 114, 114, 96, 97, 98, 99, 100, 114, 83, + /* 1540 */ 103, 104, 86, 114, 114, 114, 114, 114, 114, 114, + /* 1550 */ 114, 114, 96, 97, 98, 99, 100, 114, 83, 103, + /* 1560 */ 104, 86, 114, 114, 114, 114, 114, 114, 114, 114, + /* 1570 */ 114, 114, 97, 98, 99, 100, 114, 83, 103, 104, + /* 1580 */ 86, 114, 114, 114, 114, 83, 114, 114, 86, 114, + /* 1590 */ 114, 97, 98, 99, 100, 114, 114, 103, 104, 97, + /* 1600 */ 98, 99, 100, 114, 83, 103, 104, 86, 114, 114, + /* 1610 */ 114, 114, 114, 114, 114, 114, 114, 114, 97, 98, + /* 1620 */ 99, 100, 114, 83, 103, 104, 86, 114, 114, 114, + /* 1630 */ 114, 114, 114, 114, 114, 114, 114, 97, 98, 99, + /* 1640 */ 100, 114, 83, 103, 104, 86, 114, 114, 114, 114, + /* 1650 */ 114, 114, 114, 114, 114, 114, 97, 98, 99, 100, + /* 1660 */ 114, 83, 103, 104, 86, 114, 114, 114, 114, 83, + /* 1670 */ 114, 114, 86, 114, 114, 97, 98, 99, 100, 114, + /* 1680 */ 114, 103, 104, 97, 98, 99, 100, 114, 83, 103, + /* 1690 */ 104, 86, 114, 114, 114, 114, 114, 114, 114, 114, + /* 1700 */ 114, 114, 97, 98, 99, 100, 114, 83, 103, 104, + /* 1710 */ 86, 114, 114, 114, 114, 114, 114, 114, 114, 114, + /* 1720 */ 114, 97, 98, 99, 100, 114, 83, 103, 104, 86, + /* 1730 */ 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, + /* 1740 */ 97, 98, 99, 100, 114, 83, 103, 104, 86, 114, + /* 1750 */ 114, 114, 114, 83, 114, 114, 86, 114, 114, 97, + /* 1760 */ 98, 99, 100, 114, 114, 103, 104, 97, 98, 99, + /* 1770 */ 100, 114, 83, 103, 104, 86, 114, 114, 114, 114, + /* 1780 */ 114, 114, 114, 114, 114, 114, 97, 98, 99, 100, + /* 1790 */ 114, 114, 103, 104, +}; +#define YY_SHIFT_USE_DFLT (1794) +#define YY_SHIFT_COUNT (144) +#define YY_SHIFT_MIN (-60) +#define YY_SHIFT_MAX (1166) +static const short yy_shift_ofst[] = { + /* 0 */ -1, 460, 96, 131, 285, 131, 489, 489, 489, 489, + /* 10 */ 220, 254, 489, 489, 489, 489, 489, 489, 489, 489, + /* 20 */ 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, + /* 30 */ 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, + /* 40 */ 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, + /* 50 */ 489, 489, 489, 489, 96, 489, 489, 489, 489, 489, + /* 60 */ 489, 489, 489, 489, 489, 489, 489, 489, 489, 489, + /* 70 */ 489, 263, -7, -60, 36, 223, -7, -60, 1152, 1166, + /* 80 */ 36, 36, 36, 36, 36, 36, 36, 256, 132, 132, + /* 90 */ 132, 1061, 4, 4, 4, 4, 4, 4, 4, 4, + /* 100 */ 4, 4, 4, 4, 17, 4, 17, 4, 17, 4, + /* 110 */ 45, 94, 493, 179, 247, 126, 134, 134, 290, 134, + /* 120 */ 190, 370, 209, 134, 190, 179, 298, 221, 75, 104, + /* 130 */ 232, 236, 238, 250, 271, 297, 280, 278, 303, 271, + /* 140 */ 278, 303, 271, 306, 104, +}; +#define YY_REDUCE_USE_DFLT (-106) +#define YY_REDUCE_COUNT (87) +#define YY_REDUCE_MIN (-105) +#define YY_REDUCE_MAX (1689) +static const short yy_reduce_ofst[] = { + /* 0 */ -62, -8, 34, 123, 155, 274, 308, 340, 362, 392, + /* 10 */ 478, 500, 522, 544, 566, 588, 610, 632, 654, 676, + /* 20 */ 698, 720, 742, 764, 786, 808, 830, 852, 874, 893, + /* 30 */ 912, 931, 950, 969, 1007, 1029, 1048, 1100, 1122, 1144, + /* 40 */ 1163, 1182, 1201, 1220, 1239, 1258, 1277, 1296, 1315, 1334, + /* 50 */ 1353, 1372, 1391, 1410, 1418, 1437, 1456, 1475, 1494, 1502, + /* 60 */ 1521, 1540, 1559, 1578, 1586, 1605, 1624, 1643, 1662, 1670, + /* 70 */ 1689, -64, 33, -105, 15, 50, 23, 39, -69, -69, + /* 80 */ -32, 20, 71, 122, 147, 175, 183, -87, +}; +static const YYACTIONTYPE yy_default[] = { + /* 0 */ 504, 437, 504, 444, 504, 446, 441, 504, 504, 504, + /* 10 */ 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + /* 20 */ 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + /* 30 */ 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + /* 40 */ 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + /* 50 */ 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + /* 60 */ 504, 504, 504, 504, 504, 504, 504, 504, 504, 504, + /* 70 */ 504, 504, 501, 437, 504, 477, 504, 504, 504, 504, + /* 80 */ 504, 504, 504, 504, 504, 504, 504, 504, 469, 399, + /* 90 */ 398, 475, 413, 412, 411, 410, 409, 408, 407, 406, + /* 100 */ 405, 404, 403, 470, 472, 402, 418, 401, 417, 400, + /* 110 */ 504, 504, 504, 392, 504, 504, 471, 416, 504, 415, + /* 120 */ 468, 504, 475, 414, 397, 464, 463, 504, 486, 482, + /* 130 */ 504, 504, 504, 503, 394, 504, 504, 467, 466, 465, + /* 140 */ 396, 395, 393, 504, 504, +}; +/********** End of lemon-generated parsing tables *****************************/ + +/* The next table maps tokens (terminal symbols) into fallback tokens. +** If a construct like the following: +** +** %fallback ID X Y Z. +** +** appears in the grammar, then ID becomes a fallback token for X, Y, +** and Z. Whenever one of the tokens X, Y, or Z is input to the parser +** but it does not parse, the type of the token is changed to ID and +** the parse is retried before an error is thrown. +** +** This feature can be used, for example, to cause some keywords in a language +** to revert to identifiers if they keyword does not apply in the context where +** it appears. +*/ +#ifdef YYFALLBACK +static const YYCODETYPE yyFallback[] = { +}; +#endif /* YYFALLBACK */ + +/* The following structure represents a single element of the +** parser's stack. Information stored includes: +** +** + The state number for the parser at this level of the stack. +** +** + The value of the token stored at this level of the stack. +** (In other words, the "major" token.) +** +** + The semantic value stored at this level of the stack. This is +** the information used by the action routines in the grammar. +** It is sometimes called the "minor" token. +** +** After the "shift" half of a SHIFTREDUCE action, the stateno field +** actually contains the reduce action for the second half of the +** SHIFTREDUCE. +*/ +struct yyStackEntry { + YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */ + YYCODETYPE major; /* The major token value. This is the code + ** number for the token at this stack level */ + YYMINORTYPE minor; /* The user-supplied minor token value. This + ** is the value of the token */ +}; +typedef struct yyStackEntry yyStackEntry; + +/* The state of the parser is completely contained in an instance of +** the following structure */ +struct yyParser { + yyStackEntry *yytos; /* Pointer to top element of the stack */ +#ifdef YYTRACKMAXSTACKDEPTH + int yyhwm; /* High-water mark of the stack */ +#endif +#ifndef YYNOERRORRECOVERY + int yyerrcnt; /* Shifts left before out of the error */ +#endif + grn_expr_parserARG_SDECL /* A place to hold %extra_argument */ +#if YYSTACKDEPTH<=0 + int yystksz; /* Current side of the stack */ + yyStackEntry *yystack; /* The parser's stack */ + yyStackEntry yystk0; /* First stack entry */ +#else + yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */ +#endif +}; +typedef struct yyParser yyParser; + +#ifndef NDEBUG +#include +static FILE *yyTraceFILE = 0; +static char *yyTracePrompt = 0; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* +** Turn parser tracing on by giving a stream to which to write the trace +** and a prompt to preface each trace message. Tracing is turned off +** by making either argument NULL +** +** Inputs: +**
    +**
  • A FILE* to which trace output should be written. +** If NULL, then tracing is turned off. +**
  • A prefix string written at the beginning of every +** line of trace output. If NULL, then tracing is +** turned off. +**
+** +** Outputs: +** None. +*/ +void grn_expr_parserTrace(FILE *TraceFILE, char *zTracePrompt){ + yyTraceFILE = TraceFILE; + yyTracePrompt = zTracePrompt; + if( yyTraceFILE==0 ) yyTracePrompt = 0; + else if( yyTracePrompt==0 ) yyTraceFILE = 0; +} +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing shifts, the names of all terminals and nonterminals +** are required. The following table supplies these names */ +static const char *const yyTokenName[] = { + "$", "START_OUTPUT_COLUMNS", "START_ADJUSTER", "LOGICAL_AND", + "LOGICAL_AND_NOT", "LOGICAL_OR", "NEGATIVE", "QSTRING", + "PARENL", "PARENR", "ADJUST", "RELATIVE_OP", + "IDENTIFIER", "BRACEL", "BRACER", "EVAL", + "COMMA", "ASSIGN", "STAR_ASSIGN", "SLASH_ASSIGN", + "MOD_ASSIGN", "PLUS_ASSIGN", "MINUS_ASSIGN", "SHIFTL_ASSIGN", + "SHIFTR_ASSIGN", "SHIFTRR_ASSIGN", "AND_ASSIGN", "XOR_ASSIGN", + "OR_ASSIGN", "QUESTION", "COLON", "BITWISE_OR", + "BITWISE_XOR", "BITWISE_AND", "EQUAL", "NOT_EQUAL", + "LESS", "GREATER", "LESS_EQUAL", "GREATER_EQUAL", + "IN", "MATCH", "NEAR", "NEAR2", + "SIMILAR", "TERM_EXTRACT", "LCP", "PREFIX", + "SUFFIX", "REGEXP", "SHIFTL", "SHIFTR", + "SHIFTRR", "PLUS", "MINUS", "STAR", + "SLASH", "MOD", "DELETE", "INCR", + "DECR", "NOT", "BITWISE_NOT", "EXACT", + "PARTIAL", "UNSPLIT", "DECIMAL", "HEX_INTEGER", + "STRING", "BOOLEAN", "NULL", "BRACKETL", + "BRACKETR", "DOT", "NONEXISTENT_COLUMN", "error", + "suppress_unused_variable_warning", "input", "query", "expression", + "output_columns", "adjuster", "query_element", "primary_expression", + "assignment_expression", "conditional_expression", "lefthand_side_expression", "logical_or_expression", + "logical_and_expression", "bitwise_or_expression", "bitwise_xor_expression", "bitwise_and_expression", + "equality_expression", "relational_expression", "shift_expression", "additive_expression", + "multiplicative_expression", "unary_expression", "postfix_expression", "call_expression", + "member_expression", "arguments", "member_expression_part", "object_literal", + "array_literal", "elision", "element_list", "property_name_and_value_list", + "property_name_and_value", "property_name", "argument_list", "output_column", + "adjust_expression", "adjust_match_expression", +}; +#endif /* NDEBUG */ + +#ifndef NDEBUG +/* For tracing reduce actions, the names of all rules are required. +*/ +static const char *const yyRuleName[] = { + /* 0 */ "query ::= query query_element", + /* 1 */ "query ::= query LOGICAL_AND query_element", + /* 2 */ "query ::= query LOGICAL_AND_NOT query_element", + /* 3 */ "query ::= query LOGICAL_OR query_element", + /* 4 */ "query ::= query NEGATIVE query_element", + /* 5 */ "query_element ::= ADJUST query_element", + /* 6 */ "query_element ::= RELATIVE_OP query_element", + /* 7 */ "query_element ::= IDENTIFIER RELATIVE_OP query_element", + /* 8 */ "query_element ::= BRACEL expression BRACER", + /* 9 */ "query_element ::= EVAL primary_expression", + /* 10 */ "expression ::= expression COMMA assignment_expression", + /* 11 */ "assignment_expression ::= lefthand_side_expression ASSIGN assignment_expression", + /* 12 */ "assignment_expression ::= lefthand_side_expression STAR_ASSIGN assignment_expression", + /* 13 */ "assignment_expression ::= lefthand_side_expression SLASH_ASSIGN assignment_expression", + /* 14 */ "assignment_expression ::= lefthand_side_expression MOD_ASSIGN assignment_expression", + /* 15 */ "assignment_expression ::= lefthand_side_expression PLUS_ASSIGN assignment_expression", + /* 16 */ "assignment_expression ::= lefthand_side_expression MINUS_ASSIGN assignment_expression", + /* 17 */ "assignment_expression ::= lefthand_side_expression SHIFTL_ASSIGN assignment_expression", + /* 18 */ "assignment_expression ::= lefthand_side_expression SHIFTR_ASSIGN assignment_expression", + /* 19 */ "assignment_expression ::= lefthand_side_expression SHIFTRR_ASSIGN assignment_expression", + /* 20 */ "assignment_expression ::= lefthand_side_expression AND_ASSIGN assignment_expression", + /* 21 */ "assignment_expression ::= lefthand_side_expression XOR_ASSIGN assignment_expression", + /* 22 */ "assignment_expression ::= lefthand_side_expression OR_ASSIGN assignment_expression", + /* 23 */ "conditional_expression ::= logical_or_expression QUESTION assignment_expression COLON assignment_expression", + /* 24 */ "logical_or_expression ::= logical_or_expression LOGICAL_OR logical_and_expression", + /* 25 */ "logical_and_expression ::= logical_and_expression LOGICAL_AND bitwise_or_expression", + /* 26 */ "logical_and_expression ::= logical_and_expression LOGICAL_AND_NOT bitwise_or_expression", + /* 27 */ "bitwise_or_expression ::= bitwise_or_expression BITWISE_OR bitwise_xor_expression", + /* 28 */ "bitwise_xor_expression ::= bitwise_xor_expression BITWISE_XOR bitwise_and_expression", + /* 29 */ "bitwise_and_expression ::= bitwise_and_expression BITWISE_AND equality_expression", + /* 30 */ "equality_expression ::= equality_expression EQUAL relational_expression", + /* 31 */ "equality_expression ::= equality_expression NOT_EQUAL relational_expression", + /* 32 */ "relational_expression ::= relational_expression LESS shift_expression", + /* 33 */ "relational_expression ::= relational_expression GREATER shift_expression", + /* 34 */ "relational_expression ::= relational_expression LESS_EQUAL shift_expression", + /* 35 */ "relational_expression ::= relational_expression GREATER_EQUAL shift_expression", + /* 36 */ "relational_expression ::= relational_expression IN shift_expression", + /* 37 */ "relational_expression ::= relational_expression MATCH shift_expression", + /* 38 */ "relational_expression ::= relational_expression NEAR shift_expression", + /* 39 */ "relational_expression ::= relational_expression NEAR2 shift_expression", + /* 40 */ "relational_expression ::= relational_expression SIMILAR shift_expression", + /* 41 */ "relational_expression ::= relational_expression TERM_EXTRACT shift_expression", + /* 42 */ "relational_expression ::= relational_expression LCP shift_expression", + /* 43 */ "relational_expression ::= relational_expression PREFIX shift_expression", + /* 44 */ "relational_expression ::= relational_expression SUFFIX shift_expression", + /* 45 */ "relational_expression ::= relational_expression REGEXP shift_expression", + /* 46 */ "shift_expression ::= shift_expression SHIFTL additive_expression", + /* 47 */ "shift_expression ::= shift_expression SHIFTR additive_expression", + /* 48 */ "shift_expression ::= shift_expression SHIFTRR additive_expression", + /* 49 */ "additive_expression ::= additive_expression PLUS multiplicative_expression", + /* 50 */ "additive_expression ::= additive_expression MINUS multiplicative_expression", + /* 51 */ "multiplicative_expression ::= multiplicative_expression STAR unary_expression", + /* 52 */ "multiplicative_expression ::= multiplicative_expression SLASH unary_expression", + /* 53 */ "multiplicative_expression ::= multiplicative_expression MOD unary_expression", + /* 54 */ "unary_expression ::= DELETE unary_expression", + /* 55 */ "unary_expression ::= INCR unary_expression", + /* 56 */ "unary_expression ::= DECR unary_expression", + /* 57 */ "unary_expression ::= PLUS unary_expression", + /* 58 */ "unary_expression ::= MINUS unary_expression", + /* 59 */ "unary_expression ::= NOT unary_expression", + /* 60 */ "unary_expression ::= BITWISE_NOT unary_expression", + /* 61 */ "unary_expression ::= ADJUST unary_expression", + /* 62 */ "unary_expression ::= EXACT unary_expression", + /* 63 */ "unary_expression ::= PARTIAL unary_expression", + /* 64 */ "unary_expression ::= UNSPLIT unary_expression", + /* 65 */ "postfix_expression ::= lefthand_side_expression INCR", + /* 66 */ "postfix_expression ::= lefthand_side_expression DECR", + /* 67 */ "call_expression ::= member_expression arguments", + /* 68 */ "object_literal ::= BRACEL property_name_and_value_list BRACER", + /* 69 */ "property_name_and_value_list ::=", + /* 70 */ "property_name_and_value ::= property_name COLON assignment_expression", + /* 71 */ "member_expression_part ::= BRACKETL expression BRACKETR", + /* 72 */ "arguments ::= PARENL argument_list PARENR", + /* 73 */ "argument_list ::=", + /* 74 */ "argument_list ::= assignment_expression", + /* 75 */ "argument_list ::= argument_list COMMA assignment_expression", + /* 76 */ "output_columns ::=", + /* 77 */ "output_columns ::= output_column", + /* 78 */ "output_columns ::= output_columns COMMA", + /* 79 */ "output_columns ::= output_columns COMMA output_column", + /* 80 */ "output_column ::= STAR", + /* 81 */ "output_column ::= NONEXISTENT_COLUMN", + /* 82 */ "output_column ::= assignment_expression", + /* 83 */ "adjuster ::= adjuster PLUS adjust_expression", + /* 84 */ "adjust_expression ::= adjust_match_expression STAR DECIMAL", + /* 85 */ "adjust_match_expression ::= IDENTIFIER MATCH STRING", + /* 86 */ "input ::= query", + /* 87 */ "input ::= expression", + /* 88 */ "input ::= START_OUTPUT_COLUMNS output_columns", + /* 89 */ "input ::= START_ADJUSTER adjuster", + /* 90 */ "query ::= query_element", + /* 91 */ "query_element ::= QSTRING", + /* 92 */ "query_element ::= PARENL query PARENR", + /* 93 */ "expression ::= assignment_expression", + /* 94 */ "assignment_expression ::= conditional_expression", + /* 95 */ "conditional_expression ::= logical_or_expression", + /* 96 */ "logical_or_expression ::= logical_and_expression", + /* 97 */ "logical_and_expression ::= bitwise_or_expression", + /* 98 */ "bitwise_or_expression ::= bitwise_xor_expression", + /* 99 */ "bitwise_xor_expression ::= bitwise_and_expression", + /* 100 */ "bitwise_and_expression ::= equality_expression", + /* 101 */ "equality_expression ::= relational_expression", + /* 102 */ "relational_expression ::= shift_expression", + /* 103 */ "shift_expression ::= additive_expression", + /* 104 */ "additive_expression ::= multiplicative_expression", + /* 105 */ "multiplicative_expression ::= unary_expression", + /* 106 */ "unary_expression ::= postfix_expression", + /* 107 */ "postfix_expression ::= lefthand_side_expression", + /* 108 */ "lefthand_side_expression ::= call_expression", + /* 109 */ "lefthand_side_expression ::= member_expression", + /* 110 */ "member_expression ::= primary_expression", + /* 111 */ "member_expression ::= member_expression member_expression_part", + /* 112 */ "primary_expression ::= object_literal", + /* 113 */ "primary_expression ::= PARENL expression PARENR", + /* 114 */ "primary_expression ::= IDENTIFIER", + /* 115 */ "primary_expression ::= array_literal", + /* 116 */ "primary_expression ::= DECIMAL", + /* 117 */ "primary_expression ::= HEX_INTEGER", + /* 118 */ "primary_expression ::= STRING", + /* 119 */ "primary_expression ::= BOOLEAN", + /* 120 */ "primary_expression ::= NULL", + /* 121 */ "array_literal ::= BRACKETL elision BRACKETR", + /* 122 */ "array_literal ::= BRACKETL element_list elision BRACKETR", + /* 123 */ "array_literal ::= BRACKETL element_list BRACKETR", + /* 124 */ "elision ::= COMMA", + /* 125 */ "elision ::= elision COMMA", + /* 126 */ "element_list ::= assignment_expression", + /* 127 */ "element_list ::= elision assignment_expression", + /* 128 */ "element_list ::= element_list elision assignment_expression", + /* 129 */ "property_name_and_value_list ::= property_name_and_value", + /* 130 */ "property_name_and_value_list ::= property_name_and_value_list COMMA property_name_and_value", + /* 131 */ "property_name ::= STRING", + /* 132 */ "member_expression_part ::= DOT IDENTIFIER", + /* 133 */ "adjuster ::=", + /* 134 */ "adjuster ::= adjust_expression", + /* 135 */ "adjust_expression ::= adjust_match_expression", +}; +#endif /* NDEBUG */ + + +#if YYSTACKDEPTH<=0 +/* +** Try to increase the size of the parser stack. Return the number +** of errors. Return 0 on success. +*/ +static int yyGrowStack(yyParser *p){ + int newSize; + int idx; + yyStackEntry *pNew; + + newSize = p->yystksz*2 + 100; + idx = p->yytos ? (int)(p->yytos - p->yystack) : 0; + if( p->yystack==&p->yystk0 ){ + pNew = malloc(newSize*sizeof(pNew[0])); + if( pNew ) pNew[0] = p->yystk0; + }else{ + pNew = realloc(p->yystack, newSize*sizeof(pNew[0])); + } + if( pNew ){ + p->yystack = pNew; + p->yytos = &p->yystack[idx]; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n", + yyTracePrompt, p->yystksz, newSize); + } +#endif + p->yystksz = newSize; + } + return pNew==0; +} +#endif + +/* Datatype of the argument to the memory allocated passed as the +** second argument to grn_expr_parserAlloc() below. This can be changed by +** putting an appropriate #define in the %include section of the input +** grammar. +*/ +#ifndef YYMALLOCARGTYPE +# define YYMALLOCARGTYPE size_t +#endif + +/* Initialize a new parser that has already been allocated. +*/ +void grn_expr_parserInit(void *yypParser){ + yyParser *pParser = (yyParser*)yypParser; +#ifdef YYTRACKMAXSTACKDEPTH + pParser->yyhwm = 0; +#endif +#if YYSTACKDEPTH<=0 + pParser->yytos = NULL; + pParser->yystack = NULL; + pParser->yystksz = 0; + if( yyGrowStack(pParser) ){ + pParser->yystack = &pParser->yystk0; + pParser->yystksz = 1; + } +#endif +#ifndef YYNOERRORRECOVERY + pParser->yyerrcnt = -1; +#endif + pParser->yytos = pParser->yystack; + pParser->yystack[0].stateno = 0; + pParser->yystack[0].major = 0; +} + +#ifndef grn_expr_parser_ENGINEALWAYSONSTACK +/* +** This function allocates a new parser. +** The only argument is a pointer to a function which works like +** malloc. +** +** Inputs: +** A pointer to the function used to allocate memory. +** +** Outputs: +** A pointer to a parser. This pointer is used in subsequent calls +** to grn_expr_parser and grn_expr_parserFree. +*/ +void *grn_expr_parserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){ + yyParser *pParser; + pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) ); + if( pParser ) grn_expr_parserInit(pParser); + return pParser; +} +#endif /* grn_expr_parser_ENGINEALWAYSONSTACK */ + + +/* The following function deletes the "minor type" or semantic value +** associated with a symbol. The symbol can be either a terminal +** or nonterminal. "yymajor" is the symbol code, and "yypminor" is +** a pointer to the value to be deleted. The code used to do the +** deletions is derived from the %destructor and/or %token_destructor +** directives of the input grammar. +*/ +static void yy_destructor( + yyParser *yypParser, /* The parser */ + YYCODETYPE yymajor, /* Type code for object to destroy */ + YYMINORTYPE *yypminor /* The object to be destroyed */ +){ + grn_expr_parserARG_FETCH; + switch( yymajor ){ + /* Here is inserted the actions which take place when a + ** terminal or non-terminal is destroyed. This can happen + ** when the symbol is popped from the stack during a + ** reduce or during error processing or when a parser is + ** being destroyed before it is finished parsing. + ** + ** Note: during a reduce, the only symbols destroyed are those + ** which appear on the RHS of the rule, but which are *not* used + ** inside the C code. + */ +/********* Begin destructor definitions ***************************************/ + case 76: /* suppress_unused_variable_warning */ +{ +#line 14 "grn_ecmascript.lemon" + + (void)efsi; + +#line 1006 "grn_ecmascript.c" +} + break; +/********* End destructor definitions *****************************************/ + default: break; /* If no destructor action specified: do nothing */ + } +} + +/* +** Pop the parser's stack once. +** +** If there is a destructor routine associated with the token which +** is popped from the stack, then call it. +*/ +static void yy_pop_parser_stack(yyParser *pParser){ + yyStackEntry *yytos; + assert( pParser->yytos!=0 ); + assert( pParser->yytos > pParser->yystack ); + yytos = pParser->yytos--; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sPopping %s\n", + yyTracePrompt, + yyTokenName[yytos->major]); + } +#endif + yy_destructor(pParser, yytos->major, &yytos->minor); +} + +/* +** Clear all secondary memory allocations from the parser +*/ +void grn_expr_parserFinalize(void *p){ + yyParser *pParser = (yyParser*)p; + while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser); +#if YYSTACKDEPTH<=0 + if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack); +#endif +} + +#ifndef grn_expr_parser_ENGINEALWAYSONSTACK +/* +** Deallocate and destroy a parser. Destructors are called for +** all stack elements before shutting the parser down. +** +** If the YYPARSEFREENEVERNULL macro exists (for example because it +** is defined in a %include section of the input grammar) then it is +** assumed that the input pointer is never NULL. +*/ +void grn_expr_parserFree( + void *p, /* The parser to be deleted */ + void (*freeProc)(void*) /* Function used to reclaim memory */ +){ +#ifndef YYPARSEFREENEVERNULL + if( p==0 ) return; +#endif + grn_expr_parserFinalize(p); + (*freeProc)(p); +} +#endif /* grn_expr_parser_ENGINEALWAYSONSTACK */ + +/* +** Return the peak depth of the stack for a parser. +*/ +#ifdef YYTRACKMAXSTACKDEPTH +int grn_expr_parserStackPeak(void *p){ + yyParser *pParser = (yyParser*)p; + return pParser->yyhwm; +} +#endif + +/* +** Find the appropriate action for a parser given the terminal +** look-ahead token iLookAhead. +*/ +static unsigned int yy_find_shift_action( + yyParser *pParser, /* The parser */ + YYCODETYPE iLookAhead /* The look-ahead token */ +){ + int i; + int stateno = pParser->yytos->stateno; + + if( stateno>=YY_MIN_REDUCE ) return stateno; + assert( stateno <= YY_SHIFT_COUNT ); + do{ + i = yy_shift_ofst[stateno]; + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ +#ifdef YYFALLBACK + YYCODETYPE iFallback; /* Fallback token */ + if( iLookAhead %s\n", + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]); + } +#endif + assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */ + iLookAhead = iFallback; + continue; + } +#endif +#ifdef YYWILDCARD + { + int j = i - iLookAhead + YYWILDCARD; + if( +#if YY_SHIFT_MIN+YYWILDCARD<0 + j>=0 && +#endif +#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT + j0 + ){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n", + yyTracePrompt, yyTokenName[iLookAhead], + yyTokenName[YYWILDCARD]); + } +#endif /* NDEBUG */ + return yy_action[j]; + } + } +#endif /* YYWILDCARD */ + return yy_default[stateno]; + }else{ + return yy_action[i]; + } + }while(1); +} + +/* +** Find the appropriate action for a parser given the non-terminal +** look-ahead token iLookAhead. +*/ +static int yy_find_reduce_action( + int stateno, /* Current state number */ + YYCODETYPE iLookAhead /* The look-ahead token */ +){ + int i; +#ifdef YYERRORSYMBOL + if( stateno>YY_REDUCE_COUNT ){ + return yy_default[stateno]; + } +#else + assert( stateno<=YY_REDUCE_COUNT ); +#endif + i = yy_reduce_ofst[stateno]; + assert( i!=YY_REDUCE_USE_DFLT ); + assert( iLookAhead!=YYNOCODE ); + i += iLookAhead; +#ifdef YYERRORSYMBOL + if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){ + return yy_default[stateno]; + } +#else + assert( i>=0 && iyytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will execute if the parser + ** stack every overflows */ +/******** Begin %stack_overflow code ******************************************/ +/******** End %stack_overflow code ********************************************/ + grn_expr_parserARG_STORE; /* Suppress warning about unused %extra_argument var */ +} + +/* +** Print tracing information for a SHIFT action +*/ +#ifndef NDEBUG +static void yyTraceShift(yyParser *yypParser, int yyNewState){ + if( yyTraceFILE ){ + if( yyNewStateyytos->major], + yyNewState); + }else{ + fprintf(yyTraceFILE,"%sShift '%s'\n", + yyTracePrompt,yyTokenName[yypParser->yytos->major]); + } + } +} +#else +# define yyTraceShift(X,Y) +#endif + +/* +** Perform a shift action. +*/ +static void yy_shift( + yyParser *yypParser, /* The parser to be shifted */ + int yyNewState, /* The new state to shift in */ + int yyMajor, /* The major token to shift in */ + grn_expr_parserTOKENTYPE yyMinor /* The minor token to shift in */ +){ + yyStackEntry *yytos; + yypParser->yytos++; +#ifdef YYTRACKMAXSTACKDEPTH + if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ + yypParser->yyhwm++; + assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) ); + } +#endif +#if YYSTACKDEPTH>0 + if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH] ){ + yypParser->yytos--; + yyStackOverflow(yypParser); + return; + } +#else + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz] ){ + if( yyGrowStack(yypParser) ){ + yypParser->yytos--; + yyStackOverflow(yypParser); + return; + } + } +#endif + if( yyNewState > YY_MAX_SHIFT ){ + yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } + yytos = yypParser->yytos; + yytos->stateno = (YYACTIONTYPE)yyNewState; + yytos->major = (YYCODETYPE)yyMajor; + yytos->minor.yy0 = yyMinor; + yyTraceShift(yypParser, yyNewState); +} + +/* The following table contains information about every rule that +** is used during the reduce. +*/ +static const struct { + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */ + unsigned char nrhs; /* Number of right-hand side symbols in the rule */ +} yyRuleInfo[] = { + { 78, 2 }, + { 78, 3 }, + { 78, 3 }, + { 78, 3 }, + { 78, 3 }, + { 82, 2 }, + { 82, 2 }, + { 82, 3 }, + { 82, 3 }, + { 82, 2 }, + { 79, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 84, 3 }, + { 85, 5 }, + { 87, 3 }, + { 88, 3 }, + { 88, 3 }, + { 89, 3 }, + { 90, 3 }, + { 91, 3 }, + { 92, 3 }, + { 92, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 93, 3 }, + { 94, 3 }, + { 94, 3 }, + { 94, 3 }, + { 95, 3 }, + { 95, 3 }, + { 96, 3 }, + { 96, 3 }, + { 96, 3 }, + { 97, 2 }, + { 97, 2 }, + { 97, 2 }, + { 97, 2 }, + { 97, 2 }, + { 97, 2 }, + { 97, 2 }, + { 97, 2 }, + { 97, 2 }, + { 97, 2 }, + { 97, 2 }, + { 98, 2 }, + { 98, 2 }, + { 99, 2 }, + { 103, 3 }, + { 107, 0 }, + { 108, 3 }, + { 102, 3 }, + { 101, 3 }, + { 110, 0 }, + { 110, 1 }, + { 110, 3 }, + { 80, 0 }, + { 80, 1 }, + { 80, 2 }, + { 80, 3 }, + { 111, 1 }, + { 111, 1 }, + { 111, 1 }, + { 81, 3 }, + { 112, 3 }, + { 113, 3 }, + { 77, 1 }, + { 77, 1 }, + { 77, 2 }, + { 77, 2 }, + { 78, 1 }, + { 82, 1 }, + { 82, 3 }, + { 79, 1 }, + { 84, 1 }, + { 85, 1 }, + { 87, 1 }, + { 88, 1 }, + { 89, 1 }, + { 90, 1 }, + { 91, 1 }, + { 92, 1 }, + { 93, 1 }, + { 94, 1 }, + { 95, 1 }, + { 96, 1 }, + { 97, 1 }, + { 98, 1 }, + { 86, 1 }, + { 86, 1 }, + { 100, 1 }, + { 100, 2 }, + { 83, 1 }, + { 83, 3 }, + { 83, 1 }, + { 83, 1 }, + { 83, 1 }, + { 83, 1 }, + { 83, 1 }, + { 83, 1 }, + { 83, 1 }, + { 104, 3 }, + { 104, 4 }, + { 104, 3 }, + { 105, 1 }, + { 105, 2 }, + { 106, 1 }, + { 106, 2 }, + { 106, 3 }, + { 107, 1 }, + { 107, 3 }, + { 109, 1 }, + { 102, 2 }, + { 81, 0 }, + { 81, 1 }, + { 112, 1 }, +}; + +static void yy_accept(yyParser*); /* Forward Declaration */ + +/* +** Perform a reduce action and the shift that must immediately +** follow the reduce. +*/ +static void yy_reduce( + yyParser *yypParser, /* The parser */ + unsigned int yyruleno /* Number of the rule by which to reduce */ +){ + int yygoto; /* The next state */ + int yyact; /* The next action */ + yyStackEntry *yymsp; /* The top of the parser's stack */ + int yysize; /* Amount to pop the stack */ + grn_expr_parserARG_FETCH; + yymsp = yypParser->yytos; +#ifndef NDEBUG + if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){ + yysize = yyRuleInfo[yyruleno].nrhs; + fprintf(yyTraceFILE, "%sReduce [%s], go to state %d.\n", yyTracePrompt, + yyRuleName[yyruleno], yymsp[-yysize].stateno); + } +#endif /* NDEBUG */ + + /* Check that the stack is large enough to grow by a single entry + ** if the RHS of the rule is empty. This ensures that there is room + ** enough on the stack to push the LHS value */ + if( yyRuleInfo[yyruleno].nrhs==0 ){ +#ifdef YYTRACKMAXSTACKDEPTH + if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){ + yypParser->yyhwm++; + assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack)); + } +#endif +#if YYSTACKDEPTH>0 + if( yypParser->yytos>=&yypParser->yystack[YYSTACKDEPTH-1] ){ + yyStackOverflow(yypParser); + return; + } +#else + if( yypParser->yytos>=&yypParser->yystack[yypParser->yystksz-1] ){ + if( yyGrowStack(yypParser) ){ + yyStackOverflow(yypParser); + return; + } + yymsp = yypParser->yytos; + } +#endif + } + + switch( yyruleno ){ + /* Beginning here are the reduction cases. A typical example + ** follows: + ** case 0: + ** #line + ** { ... } // User supplied code + ** #line + ** break; + */ +/********** Begin reduce actions **********************************************/ + YYMINORTYPE yylhsminor; + case 0: /* query ::= query query_element */ +#line 53 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, grn_int32_value_at(&efsi->op_stack, -1), 2); +} +#line 1462 "grn_ecmascript.c" + break; + case 1: /* query ::= query LOGICAL_AND query_element */ + case 25: /* logical_and_expression ::= logical_and_expression LOGICAL_AND bitwise_or_expression */ yytestcase(yyruleno==25); +#line 56 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND, 2); +} +#line 1470 "grn_ecmascript.c" + break; + case 2: /* query ::= query LOGICAL_AND_NOT query_element */ + case 26: /* logical_and_expression ::= logical_and_expression LOGICAL_AND_NOT bitwise_or_expression */ yytestcase(yyruleno==26); +#line 59 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_NOT, 2); +} +#line 1478 "grn_ecmascript.c" + break; + case 3: /* query ::= query LOGICAL_OR query_element */ + case 24: /* logical_or_expression ::= logical_or_expression LOGICAL_OR logical_and_expression */ yytestcase(yyruleno==24); +#line 62 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR, 2); +} +#line 1486 "grn_ecmascript.c" + break; + case 4: /* query ::= query NEGATIVE query_element */ +#line 65 "grn_ecmascript.lemon" +{ + int weight; + GRN_INT32_POP(&efsi->weight_stack, weight); + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 2); +} +#line 1495 "grn_ecmascript.c" + break; + case 5: /* query_element ::= ADJUST query_element */ +#line 74 "grn_ecmascript.lemon" +{ + int weight; + GRN_INT32_POP(&efsi->weight_stack, weight); +} +#line 1503 "grn_ecmascript.c" + break; + case 6: /* query_element ::= RELATIVE_OP query_element */ +#line 78 "grn_ecmascript.lemon" +{ + int mode; + GRN_INT32_POP(&efsi->mode_stack, mode); +} +#line 1511 "grn_ecmascript.c" + break; + case 7: /* query_element ::= IDENTIFIER RELATIVE_OP query_element */ +#line 82 "grn_ecmascript.lemon" +{ + int mode; + grn_obj *c; + GRN_PTR_POP(&efsi->column_stack, c); + GRN_INT32_POP(&efsi->mode_stack, mode); + switch (mode) { + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + { + int max_interval; + GRN_INT32_POP(&efsi->max_interval_stack, max_interval); + } + break; + case GRN_OP_SIMILAR : + { + int similarity_threshold; + GRN_INT32_POP(&efsi->similarity_threshold_stack, similarity_threshold); + } + break; + default : + break; + } +} +#line 1538 "grn_ecmascript.c" + break; + case 8: /* query_element ::= BRACEL expression BRACER */ + case 9: /* query_element ::= EVAL primary_expression */ yytestcase(yyruleno==9); +#line 105 "grn_ecmascript.lemon" +{ + efsi->flags = efsi->default_flags; +} +#line 1546 "grn_ecmascript.c" + break; + case 10: /* expression ::= expression COMMA assignment_expression */ +#line 113 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2); +} +#line 1553 "grn_ecmascript.c" + break; + case 11: /* assignment_expression ::= lefthand_side_expression ASSIGN assignment_expression */ +#line 118 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ASSIGN, 2); +} +#line 1560 "grn_ecmascript.c" + break; + case 12: /* assignment_expression ::= lefthand_side_expression STAR_ASSIGN assignment_expression */ +#line 121 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR_ASSIGN, 2); +} +#line 1567 "grn_ecmascript.c" + break; + case 13: /* assignment_expression ::= lefthand_side_expression SLASH_ASSIGN assignment_expression */ +#line 124 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH_ASSIGN, 2); +} +#line 1574 "grn_ecmascript.c" + break; + case 14: /* assignment_expression ::= lefthand_side_expression MOD_ASSIGN assignment_expression */ +#line 127 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD_ASSIGN, 2); +} +#line 1581 "grn_ecmascript.c" + break; + case 15: /* assignment_expression ::= lefthand_side_expression PLUS_ASSIGN assignment_expression */ +#line 130 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS_ASSIGN, 2); +} +#line 1588 "grn_ecmascript.c" + break; + case 16: /* assignment_expression ::= lefthand_side_expression MINUS_ASSIGN assignment_expression */ +#line 133 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS_ASSIGN, 2); +} +#line 1595 "grn_ecmascript.c" + break; + case 17: /* assignment_expression ::= lefthand_side_expression SHIFTL_ASSIGN assignment_expression */ +#line 136 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL_ASSIGN, 2); +} +#line 1602 "grn_ecmascript.c" + break; + case 18: /* assignment_expression ::= lefthand_side_expression SHIFTR_ASSIGN assignment_expression */ +#line 139 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR_ASSIGN, 2); +} +#line 1609 "grn_ecmascript.c" + break; + case 19: /* assignment_expression ::= lefthand_side_expression SHIFTRR_ASSIGN assignment_expression */ +#line 142 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR_ASSIGN, 2); +} +#line 1616 "grn_ecmascript.c" + break; + case 20: /* assignment_expression ::= lefthand_side_expression AND_ASSIGN assignment_expression */ +#line 145 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_ASSIGN, 2); +} +#line 1623 "grn_ecmascript.c" + break; + case 21: /* assignment_expression ::= lefthand_side_expression XOR_ASSIGN assignment_expression */ +#line 148 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_XOR_ASSIGN, 2); +} +#line 1630 "grn_ecmascript.c" + break; + case 22: /* assignment_expression ::= lefthand_side_expression OR_ASSIGN assignment_expression */ +#line 151 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR_ASSIGN, 2); +} +#line 1637 "grn_ecmascript.c" + break; + case 23: /* conditional_expression ::= logical_or_expression QUESTION assignment_expression COLON assignment_expression */ +#line 156 "grn_ecmascript.lemon" +{ + grn_expr *e = (grn_expr *)efsi->e; + e->codes[yymsp[-3].minor.yy0].nargs = yymsp[-1].minor.yy0 - yymsp[-3].minor.yy0; + e->codes[yymsp[-1].minor.yy0].nargs = e->codes_curr - yymsp[-1].minor.yy0 - 1; +} +#line 1646 "grn_ecmascript.c" + break; + case 27: /* bitwise_or_expression ::= bitwise_or_expression BITWISE_OR bitwise_xor_expression */ +#line 176 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_OR, 2); +} +#line 1653 "grn_ecmascript.c" + break; + case 28: /* bitwise_xor_expression ::= bitwise_xor_expression BITWISE_XOR bitwise_and_expression */ +#line 181 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_XOR, 2); +} +#line 1660 "grn_ecmascript.c" + break; + case 29: /* bitwise_and_expression ::= bitwise_and_expression BITWISE_AND equality_expression */ +#line 186 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_AND, 2); +} +#line 1667 "grn_ecmascript.c" + break; + case 30: /* equality_expression ::= equality_expression EQUAL relational_expression */ +#line 191 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EQUAL, 2); +} +#line 1674 "grn_ecmascript.c" + break; + case 31: /* equality_expression ::= equality_expression NOT_EQUAL relational_expression */ +#line 194 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT_EQUAL, 2); +} +#line 1681 "grn_ecmascript.c" + break; + case 32: /* relational_expression ::= relational_expression LESS shift_expression */ +#line 199 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS, 2); +} +#line 1688 "grn_ecmascript.c" + break; + case 33: /* relational_expression ::= relational_expression GREATER shift_expression */ +#line 202 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER, 2); +} +#line 1695 "grn_ecmascript.c" + break; + case 34: /* relational_expression ::= relational_expression LESS_EQUAL shift_expression */ +#line 205 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS_EQUAL, 2); +} +#line 1702 "grn_ecmascript.c" + break; + case 35: /* relational_expression ::= relational_expression GREATER_EQUAL shift_expression */ +#line 208 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER_EQUAL, 2); +} +#line 1709 "grn_ecmascript.c" + break; + case 36: /* relational_expression ::= relational_expression IN shift_expression */ +#line 211 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_IN, 2); +} +#line 1716 "grn_ecmascript.c" + break; + case 37: /* relational_expression ::= relational_expression MATCH shift_expression */ + case 85: /* adjust_match_expression ::= IDENTIFIER MATCH STRING */ yytestcase(yyruleno==85); +#line 214 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MATCH, 2); +} +#line 1724 "grn_ecmascript.c" + break; + case 38: /* relational_expression ::= relational_expression NEAR shift_expression */ +#line 217 "grn_ecmascript.lemon" +{ + { + int max_interval; + GRN_INT32_POP(&efsi->max_interval_stack, max_interval); + grn_expr_append_const_int(efsi->ctx, efsi->e, max_interval, + GRN_OP_PUSH, 1); + } + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR, 3); +} +#line 1737 "grn_ecmascript.c" + break; + case 39: /* relational_expression ::= relational_expression NEAR2 shift_expression */ +#line 226 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR2, 2); +} +#line 1744 "grn_ecmascript.c" + break; + case 40: /* relational_expression ::= relational_expression SIMILAR shift_expression */ +#line 229 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SIMILAR, 2); +} +#line 1751 "grn_ecmascript.c" + break; + case 41: /* relational_expression ::= relational_expression TERM_EXTRACT shift_expression */ +#line 232 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_TERM_EXTRACT, 2); +} +#line 1758 "grn_ecmascript.c" + break; + case 42: /* relational_expression ::= relational_expression LCP shift_expression */ +#line 235 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LCP, 2); +} +#line 1765 "grn_ecmascript.c" + break; + case 43: /* relational_expression ::= relational_expression PREFIX shift_expression */ +#line 238 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PREFIX, 2); +} +#line 1772 "grn_ecmascript.c" + break; + case 44: /* relational_expression ::= relational_expression SUFFIX shift_expression */ +#line 241 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SUFFIX, 2); +} +#line 1779 "grn_ecmascript.c" + break; + case 45: /* relational_expression ::= relational_expression REGEXP shift_expression */ +#line 244 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_REGEXP, 2); +} +#line 1786 "grn_ecmascript.c" + break; + case 46: /* shift_expression ::= shift_expression SHIFTL additive_expression */ +#line 249 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL, 2); +} +#line 1793 "grn_ecmascript.c" + break; + case 47: /* shift_expression ::= shift_expression SHIFTR additive_expression */ +#line 252 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR, 2); +} +#line 1800 "grn_ecmascript.c" + break; + case 48: /* shift_expression ::= shift_expression SHIFTRR additive_expression */ +#line 255 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR, 2); +} +#line 1807 "grn_ecmascript.c" + break; + case 49: /* additive_expression ::= additive_expression PLUS multiplicative_expression */ + case 83: /* adjuster ::= adjuster PLUS adjust_expression */ yytestcase(yyruleno==83); +#line 260 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 2); +} +#line 1815 "grn_ecmascript.c" + break; + case 50: /* additive_expression ::= additive_expression MINUS multiplicative_expression */ +#line 263 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 2); +} +#line 1822 "grn_ecmascript.c" + break; + case 51: /* multiplicative_expression ::= multiplicative_expression STAR unary_expression */ + case 84: /* adjust_expression ::= adjust_match_expression STAR DECIMAL */ yytestcase(yyruleno==84); +#line 268 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR, 2); +} +#line 1830 "grn_ecmascript.c" + break; + case 52: /* multiplicative_expression ::= multiplicative_expression SLASH unary_expression */ +#line 271 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH, 2); +} +#line 1837 "grn_ecmascript.c" + break; + case 53: /* multiplicative_expression ::= multiplicative_expression MOD unary_expression */ +#line 274 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD, 2); +} +#line 1844 "grn_ecmascript.c" + break; + case 54: /* unary_expression ::= DELETE unary_expression */ +#line 279 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DELETE, 1); +} +#line 1851 "grn_ecmascript.c" + break; + case 55: /* unary_expression ::= INCR unary_expression */ +#line 282 "grn_ecmascript.lemon" +{ + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_expr_dfi *dfi_; + unsigned int const_p; + + dfi_ = grn_expr_dfi_pop(e); + const_p = CONSTP(dfi_->code->value); + grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); + if (const_p) { + ERR(GRN_SYNTAX_ERROR, + "constant can't be incremented: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR, 1); + } +} +#line 1872 "grn_ecmascript.c" + break; + case 56: /* unary_expression ::= DECR unary_expression */ +#line 299 "grn_ecmascript.lemon" +{ + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_expr_dfi *dfi_; + unsigned int const_p; + + dfi_ = grn_expr_dfi_pop(e); + const_p = CONSTP(dfi_->code->value); + grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); + if (const_p) { + ERR(GRN_SYNTAX_ERROR, + "constant can't be decremented: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR, 1); + } +} +#line 1893 "grn_ecmascript.c" + break; + case 57: /* unary_expression ::= PLUS unary_expression */ +#line 316 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 1); +} +#line 1900 "grn_ecmascript.c" + break; + case 58: /* unary_expression ::= MINUS unary_expression */ +#line 319 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 1); +} +#line 1907 "grn_ecmascript.c" + break; + case 59: /* unary_expression ::= NOT unary_expression */ +#line 322 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT, 1); +} +#line 1914 "grn_ecmascript.c" + break; + case 60: /* unary_expression ::= BITWISE_NOT unary_expression */ +#line 325 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_NOT, 1); +} +#line 1921 "grn_ecmascript.c" + break; + case 61: /* unary_expression ::= ADJUST unary_expression */ +#line 328 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 1); +} +#line 1928 "grn_ecmascript.c" + break; + case 62: /* unary_expression ::= EXACT unary_expression */ +#line 331 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EXACT, 1); +} +#line 1935 "grn_ecmascript.c" + break; + case 63: /* unary_expression ::= PARTIAL unary_expression */ +#line 334 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PARTIAL, 1); +} +#line 1942 "grn_ecmascript.c" + break; + case 64: /* unary_expression ::= UNSPLIT unary_expression */ +#line 337 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_UNSPLIT, 1); +} +#line 1949 "grn_ecmascript.c" + break; + case 65: /* postfix_expression ::= lefthand_side_expression INCR */ +#line 342 "grn_ecmascript.lemon" +{ + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_expr_dfi *dfi_; + unsigned int const_p; + + dfi_ = grn_expr_dfi_pop(e); + const_p = CONSTP(dfi_->code->value); + grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); + if (const_p) { + ERR(GRN_SYNTAX_ERROR, + "constant can't be incremented: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR_POST, 1); + } +} +#line 1970 "grn_ecmascript.c" + break; + case 66: /* postfix_expression ::= lefthand_side_expression DECR */ +#line 359 "grn_ecmascript.lemon" +{ + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_expr_dfi *dfi_; + unsigned int const_p; + + dfi_ = grn_expr_dfi_pop(e); + const_p = CONSTP(dfi_->code->value); + grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); + if (const_p) { + ERR(GRN_SYNTAX_ERROR, + "constant can't be decremented: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR_POST, 1); + } +} +#line 1991 "grn_ecmascript.c" + break; + case 67: /* call_expression ::= member_expression arguments */ +#line 380 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_CALL, yymsp[0].minor.yy0); +} +#line 1998 "grn_ecmascript.c" + break; + case 68: /* object_literal ::= BRACEL property_name_and_value_list BRACER */ +#line 408 "grn_ecmascript.lemon" +{ + grn_ctx *ctx = efsi->ctx; + grn_expr_take_obj(ctx, efsi->e, (grn_obj *)(efsi->object_literal)); + grn_expr_append_obj(ctx, efsi->e, (grn_obj *)(efsi->object_literal), + GRN_OP_PUSH, 1); + efsi->object_literal = NULL; +} +#line 2009 "grn_ecmascript.c" + break; + case 69: /* property_name_and_value_list ::= */ +#line 416 "grn_ecmascript.lemon" +{ + grn_ctx *ctx = efsi->ctx; + + efsi->object_literal = + grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj), + GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY); + if (!efsi->object_literal) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "couldn't create hash table for parsing object literal: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } +} +#line 2025 "grn_ecmascript.c" + break; + case 70: /* property_name_and_value ::= property_name COLON assignment_expression */ +#line 431 "grn_ecmascript.lemon" +{ + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_obj *property = e->codes[e->codes_curr - 3].value; + grn_obj *value = e->codes[e->codes_curr - 1].value; + + if (!efsi->object_literal) { + efsi->object_literal = + grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj), + GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY); + } + + if (!efsi->object_literal) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "couldn't create hash table for parsing object literal: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_obj *buf; + int added; + if (grn_hash_add(ctx, (grn_hash *)efsi->object_literal, + GRN_TEXT_VALUE(property), GRN_TEXT_LEN(property), + (void **)&buf, &added)) { + if (added) { + GRN_OBJ_INIT(buf, value->header.type, 0, value->header.domain); + GRN_TEXT_PUT(ctx, buf, GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value)); + grn_expr_dfi_pop(e); + e->codes_curr -= 3; + } else { + ERR(GRN_INVALID_ARGUMENT, + "duplicated property name: <%.*s>", + (int)GRN_TEXT_LEN(property), + GRN_TEXT_VALUE(property)); + } + } else { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to add a property to object literal: <%.*s>", + (int)GRN_TEXT_LEN(property), + GRN_TEXT_VALUE(property)); + } + } +} +#line 2070 "grn_ecmascript.c" + break; + case 71: /* member_expression_part ::= BRACKETL expression BRACKETR */ +#line 475 "grn_ecmascript.lemon" +{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GET_MEMBER, 2); +} +#line 2077 "grn_ecmascript.c" + break; + case 72: /* arguments ::= PARENL argument_list PARENR */ +#line 480 "grn_ecmascript.lemon" +{ yymsp[-2].minor.yy0 = yymsp[-1].minor.yy0; } +#line 2082 "grn_ecmascript.c" + break; + case 73: /* argument_list ::= */ +#line 481 "grn_ecmascript.lemon" +{ yymsp[1].minor.yy0 = 0; } +#line 2087 "grn_ecmascript.c" + break; + case 74: /* argument_list ::= assignment_expression */ +#line 482 "grn_ecmascript.lemon" +{ yymsp[0].minor.yy0 = 1; } +#line 2092 "grn_ecmascript.c" + break; + case 75: /* argument_list ::= argument_list COMMA assignment_expression */ +#line 483 "grn_ecmascript.lemon" +{ yylhsminor.yy0 = yymsp[-2].minor.yy0 + 1; } +#line 2097 "grn_ecmascript.c" + yymsp[-2].minor.yy0 = yylhsminor.yy0; + break; + case 76: /* output_columns ::= */ +#line 485 "grn_ecmascript.lemon" +{ + yymsp[1].minor.yy0 = 0; +} +#line 2105 "grn_ecmascript.c" + break; + case 77: /* output_columns ::= output_column */ +#line 488 "grn_ecmascript.lemon" +{ + yylhsminor.yy0 = yymsp[0].minor.yy0; +} +#line 2112 "grn_ecmascript.c" + yymsp[0].minor.yy0 = yylhsminor.yy0; + break; + case 78: /* output_columns ::= output_columns COMMA */ +#line 493 "grn_ecmascript.lemon" +{ + yylhsminor.yy0 = yymsp[-1].minor.yy0; +} +#line 2120 "grn_ecmascript.c" + yymsp[-1].minor.yy0 = yylhsminor.yy0; + break; + case 79: /* output_columns ::= output_columns COMMA output_column */ +#line 498 "grn_ecmascript.lemon" +{ + if (yymsp[-2].minor.yy0 == 0) { + yylhsminor.yy0 = yymsp[0].minor.yy0; + } else if (yymsp[0].minor.yy0 == 0) { + yylhsminor.yy0 = yymsp[-2].minor.yy0; + } else { + if (yymsp[0].minor.yy0 == 1) { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2); + } + yylhsminor.yy0 = 1; + } +} +#line 2137 "grn_ecmascript.c" + yymsp[-2].minor.yy0 = yylhsminor.yy0; + break; + case 80: /* output_column ::= STAR */ +#line 511 "grn_ecmascript.lemon" +{ + grn_ctx *ctx = efsi->ctx; + grn_obj *expr = efsi->e; + grn_obj *variable = grn_expr_get_var_by_offset(ctx, expr, 0); + if (variable) { + grn_id table_id = GRN_OBJ_GET_DOMAIN(variable); + grn_obj *table = grn_ctx_at(ctx, table_id); + grn_obj columns_buffer; + int n_columns; + grn_obj **columns; + + GRN_PTR_INIT(&columns_buffer, GRN_OBJ_VECTOR, GRN_ID_NIL); + grn_obj_columns(ctx, table, "*", strlen("*"), &columns_buffer); + n_columns = GRN_BULK_VSIZE(&columns_buffer) / sizeof(grn_obj *); + columns = (grn_obj **)GRN_BULK_HEAD(&columns_buffer); + + if (n_columns == 0) { + /* do nothing */ + } else if (n_columns == 1) { + grn_obj *column = columns[0]; + grn_expr_append_const(ctx, expr, column, GRN_OP_GET_VALUE, 1); + if (column->header.type == GRN_ACCESSOR) { + grn_expr_take_obj(ctx, expr, column); + } + } else { + grn_expr *e = (grn_expr *)expr; + grn_bool have_column; + int i; + + have_column = (e->codes_curr > 0); + for (i = 0; i < n_columns; i++) { + grn_obj *column = columns[i]; + grn_expr_append_const(ctx, expr, column, GRN_OP_GET_VALUE, 1); + if (have_column || i > 0) { + grn_expr_append_op(ctx, expr, GRN_OP_COMMA, 2); + } + if (column->header.type == GRN_ACCESSOR) { + grn_expr_take_obj(ctx, expr, column); + } + } + } + + GRN_OBJ_FIN(ctx, &columns_buffer); + + yymsp[0].minor.yy0 = n_columns; + } else { + /* TODO: report error */ + yymsp[0].minor.yy0 = 0; + } +} +#line 2192 "grn_ecmascript.c" + break; + case 81: /* output_column ::= NONEXISTENT_COLUMN */ +#line 561 "grn_ecmascript.lemon" +{ + yymsp[0].minor.yy0 = 0; +} +#line 2199 "grn_ecmascript.c" + break; + case 82: /* output_column ::= assignment_expression */ +#line 564 "grn_ecmascript.lemon" +{ + yymsp[0].minor.yy0 = 1; +} +#line 2206 "grn_ecmascript.c" + break; + default: + /* (86) input ::= query */ yytestcase(yyruleno==86); + /* (87) input ::= expression */ yytestcase(yyruleno==87); + /* (88) input ::= START_OUTPUT_COLUMNS output_columns */ yytestcase(yyruleno==88); + /* (89) input ::= START_ADJUSTER adjuster */ yytestcase(yyruleno==89); + /* (90) query ::= query_element (OPTIMIZED OUT) */ assert(yyruleno!=90); + /* (91) query_element ::= QSTRING */ yytestcase(yyruleno==91); + /* (92) query_element ::= PARENL query PARENR */ yytestcase(yyruleno==92); + /* (93) expression ::= assignment_expression (OPTIMIZED OUT) */ assert(yyruleno!=93); + /* (94) assignment_expression ::= conditional_expression (OPTIMIZED OUT) */ assert(yyruleno!=94); + /* (95) conditional_expression ::= logical_or_expression */ yytestcase(yyruleno==95); + /* (96) logical_or_expression ::= logical_and_expression */ yytestcase(yyruleno==96); + /* (97) logical_and_expression ::= bitwise_or_expression */ yytestcase(yyruleno==97); + /* (98) bitwise_or_expression ::= bitwise_xor_expression */ yytestcase(yyruleno==98); + /* (99) bitwise_xor_expression ::= bitwise_and_expression */ yytestcase(yyruleno==99); + /* (100) bitwise_and_expression ::= equality_expression */ yytestcase(yyruleno==100); + /* (101) equality_expression ::= relational_expression */ yytestcase(yyruleno==101); + /* (102) relational_expression ::= shift_expression */ yytestcase(yyruleno==102); + /* (103) shift_expression ::= additive_expression */ yytestcase(yyruleno==103); + /* (104) additive_expression ::= multiplicative_expression */ yytestcase(yyruleno==104); + /* (105) multiplicative_expression ::= unary_expression (OPTIMIZED OUT) */ assert(yyruleno!=105); + /* (106) unary_expression ::= postfix_expression (OPTIMIZED OUT) */ assert(yyruleno!=106); + /* (107) postfix_expression ::= lefthand_side_expression */ yytestcase(yyruleno==107); + /* (108) lefthand_side_expression ::= call_expression (OPTIMIZED OUT) */ assert(yyruleno!=108); + /* (109) lefthand_side_expression ::= member_expression */ yytestcase(yyruleno==109); + /* (110) member_expression ::= primary_expression (OPTIMIZED OUT) */ assert(yyruleno!=110); + /* (111) member_expression ::= member_expression member_expression_part */ yytestcase(yyruleno==111); + /* (112) primary_expression ::= object_literal (OPTIMIZED OUT) */ assert(yyruleno!=112); + /* (113) primary_expression ::= PARENL expression PARENR */ yytestcase(yyruleno==113); + /* (114) primary_expression ::= IDENTIFIER */ yytestcase(yyruleno==114); + /* (115) primary_expression ::= array_literal (OPTIMIZED OUT) */ assert(yyruleno!=115); + /* (116) primary_expression ::= DECIMAL */ yytestcase(yyruleno==116); + /* (117) primary_expression ::= HEX_INTEGER */ yytestcase(yyruleno==117); + /* (118) primary_expression ::= STRING */ yytestcase(yyruleno==118); + /* (119) primary_expression ::= BOOLEAN */ yytestcase(yyruleno==119); + /* (120) primary_expression ::= NULL */ yytestcase(yyruleno==120); + /* (121) array_literal ::= BRACKETL elision BRACKETR */ yytestcase(yyruleno==121); + /* (122) array_literal ::= BRACKETL element_list elision BRACKETR */ yytestcase(yyruleno==122); + /* (123) array_literal ::= BRACKETL element_list BRACKETR */ yytestcase(yyruleno==123); + /* (124) elision ::= COMMA */ yytestcase(yyruleno==124); + /* (125) elision ::= elision COMMA */ yytestcase(yyruleno==125); + /* (126) element_list ::= assignment_expression (OPTIMIZED OUT) */ assert(yyruleno!=126); + /* (127) element_list ::= elision assignment_expression */ yytestcase(yyruleno==127); + /* (128) element_list ::= element_list elision assignment_expression */ yytestcase(yyruleno==128); + /* (129) property_name_and_value_list ::= property_name_and_value (OPTIMIZED OUT) */ assert(yyruleno!=129); + /* (130) property_name_and_value_list ::= property_name_and_value_list COMMA property_name_and_value */ yytestcase(yyruleno==130); + /* (131) property_name ::= STRING */ yytestcase(yyruleno==131); + /* (132) member_expression_part ::= DOT IDENTIFIER */ yytestcase(yyruleno==132); + /* (133) adjuster ::= */ yytestcase(yyruleno==133); + /* (134) adjuster ::= adjust_expression (OPTIMIZED OUT) */ assert(yyruleno!=134); + /* (135) adjust_expression ::= adjust_match_expression */ yytestcase(yyruleno==135); + break; +/********** End reduce actions ************************************************/ + }; + assert( yyrulenoYY_MAX_SHIFT ){ + yyact += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE; + } + yymsp -= yysize-1; + yypParser->yytos = yymsp; + yymsp->stateno = (YYACTIONTYPE)yyact; + yymsp->major = (YYCODETYPE)yygoto; + yyTraceShift(yypParser, yyact); + }else{ + assert( yyact == YY_ACCEPT_ACTION ); + yypParser->yytos -= yysize; + yy_accept(yypParser); + } +} + +/* +** The following code executes when the parse fails +*/ +#ifndef YYNOERRORRECOVERY +static void yy_parse_failed( + yyParser *yypParser /* The parser */ +){ + grn_expr_parserARG_FETCH; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt); + } +#endif + while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser); + /* Here code is inserted which will be executed whenever the + ** parser fails */ +/************ Begin %parse_failure code ***************************************/ +/************ End %parse_failure code *****************************************/ + grn_expr_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} +#endif /* YYNOERRORRECOVERY */ + +/* +** The following code executes when a syntax error first occurs. +*/ +static void yy_syntax_error( + yyParser *yypParser, /* The parser */ + int yymajor, /* The major type of the error token */ + grn_expr_parserTOKENTYPE yyminor /* The minor type of the error token */ +){ + grn_expr_parserARG_FETCH; +#define TOKEN yyminor +/************ Begin %syntax_error code ****************************************/ +#line 20 "grn_ecmascript.lemon" + + { + grn_ctx *ctx = efsi->ctx; + grn_obj message; + GRN_TEXT_INIT(&message, 0); + GRN_TEXT_PUT(ctx, &message, efsi->str, efsi->cur - efsi->str); + GRN_TEXT_PUTC(ctx, &message, '|'); + if (efsi->cur < efsi->str_end) { + GRN_TEXT_PUTC(ctx, &message, efsi->cur[0]); + GRN_TEXT_PUTC(ctx, &message, '|'); + GRN_TEXT_PUT(ctx, &message, + efsi->cur + 1, efsi->str_end - (efsi->cur + 1)); + } else { + GRN_TEXT_PUTC(ctx, &message, '|'); + } + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_SYNTAX_ERROR, "Syntax error: <%.*s>", + (int)GRN_TEXT_LEN(&message), GRN_TEXT_VALUE(&message)); + } else { + ERR(ctx->rc, "Syntax error: <%.*s>: %s", + (int)GRN_TEXT_LEN(&message), GRN_TEXT_VALUE(&message), + ctx->errbuf); + } + GRN_OBJ_FIN(ctx, &message); + } +#line 2341 "grn_ecmascript.c" +/************ End %syntax_error code ******************************************/ + grn_expr_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* +** The following is executed when the parser accepts +*/ +static void yy_accept( + yyParser *yypParser /* The parser */ +){ + grn_expr_parserARG_FETCH; +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt); + } +#endif +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt = -1; +#endif + assert( yypParser->yytos==yypParser->yystack ); + /* Here code is inserted which will be executed whenever the + ** parser accepts */ +/*********** Begin %parse_accept code *****************************************/ +/*********** End %parse_accept code *******************************************/ + grn_expr_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */ +} + +/* The main parser program. +** The first argument is a pointer to a structure obtained from +** "grn_expr_parserAlloc" which describes the current state of the parser. +** The second argument is the major token number. The third is +** the minor token. The fourth optional argument is whatever the +** user wants (and specified in the grammar) and is available for +** use by the action routines. +** +** Inputs: +**
    +**
  • A pointer to the parser (an opaque structure.) +**
  • The major token number. +**
  • The minor token number. +**
  • An option argument of a grammar-specified type. +**
+** +** Outputs: +** None. +*/ +void grn_expr_parser( + void *yyp, /* The parser */ + int yymajor, /* The major token code number */ + grn_expr_parserTOKENTYPE yyminor /* The value for the token */ + grn_expr_parserARG_PDECL /* Optional %extra_argument parameter */ +){ + YYMINORTYPE yyminorunion; + unsigned int yyact; /* The parser action. */ +#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) + int yyendofinput; /* True if we are at the end of input */ +#endif +#ifdef YYERRORSYMBOL + int yyerrorhit = 0; /* True if yymajor has invoked an error */ +#endif + yyParser *yypParser; /* The parser */ + + yypParser = (yyParser*)yyp; + assert( yypParser->yytos!=0 ); +#if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY) + yyendofinput = (yymajor==0); +#endif + grn_expr_parserARG_STORE; + +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sInput '%s'\n",yyTracePrompt,yyTokenName[yymajor]); + } +#endif + + do{ + yyact = yy_find_shift_action(yypParser,(YYCODETYPE)yymajor); + if( yyact <= YY_MAX_SHIFTREDUCE ){ + yy_shift(yypParser,yyact,yymajor,yyminor); +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt--; +#endif + yymajor = YYNOCODE; + }else if( yyact <= YY_MAX_REDUCE ){ + yy_reduce(yypParser,yyact-YY_MIN_REDUCE); + }else{ + assert( yyact == YY_ERROR_ACTION ); + yyminorunion.yy0 = yyminor; +#ifdef YYERRORSYMBOL + int yymx; +#endif +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt); + } +#endif +#ifdef YYERRORSYMBOL + /* A syntax error has occurred. + ** The response to an error depends upon whether or not the + ** grammar defines an error token "ERROR". + ** + ** This is what we do if the grammar does define ERROR: + ** + ** * Call the %syntax_error function. + ** + ** * Begin popping the stack until we enter a state where + ** it is legal to shift the error symbol, then shift + ** the error symbol. + ** + ** * Set the error count to three. + ** + ** * Begin accepting and shifting new tokens. No new error + ** processing will occur until three tokens have been + ** shifted successfully. + ** + */ + if( yypParser->yyerrcnt<0 ){ + yy_syntax_error(yypParser,yymajor,yyminor); + } + yymx = yypParser->yytos->major; + if( yymx==YYERRORSYMBOL || yyerrorhit ){ +#ifndef NDEBUG + if( yyTraceFILE ){ + fprintf(yyTraceFILE,"%sDiscard input token %s\n", + yyTracePrompt,yyTokenName[yymajor]); + } +#endif + yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion); + yymajor = YYNOCODE; + }else{ + while( yypParser->yytos >= yypParser->yystack + && yymx != YYERRORSYMBOL + && (yyact = yy_find_reduce_action( + yypParser->yytos->stateno, + YYERRORSYMBOL)) >= YY_MIN_REDUCE + ){ + yy_pop_parser_stack(yypParser); + } + if( yypParser->yytos < yypParser->yystack || yymajor==0 ){ + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); + yy_parse_failed(yypParser); +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt = -1; +#endif + yymajor = YYNOCODE; + }else if( yymx!=YYERRORSYMBOL ){ + yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor); + } + } + yypParser->yyerrcnt = 3; + yyerrorhit = 1; +#elif defined(YYNOERRORRECOVERY) + /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to + ** do any kind of error recovery. Instead, simply invoke the syntax + ** error routine and continue going as if nothing had happened. + ** + ** Applications can set this macro (for example inside %include) if + ** they intend to abandon the parse upon the first syntax error seen. + */ + yy_syntax_error(yypParser,yymajor, yyminor); + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); + yymajor = YYNOCODE; + +#else /* YYERRORSYMBOL is not defined */ + /* This is what we do if the grammar does not define ERROR: + ** + ** * Report an error message, and throw away the input token. + ** + ** * If the input token is $, then fail the parse. + ** + ** As before, subsequent error messages are suppressed until + ** three input tokens have been successfully shifted. + */ + if( yypParser->yyerrcnt<=0 ){ + yy_syntax_error(yypParser,yymajor, yyminor); + } + yypParser->yyerrcnt = 3; + yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion); + if( yyendofinput ){ + yy_parse_failed(yypParser); +#ifndef YYNOERRORRECOVERY + yypParser->yyerrcnt = -1; +#endif + } + yymajor = YYNOCODE; +#endif + } + }while( yymajor!=YYNOCODE && yypParser->yytos>yypParser->yystack ); +#ifndef NDEBUG + if( yyTraceFILE ){ + yyStackEntry *i; + char cDiv = '['; + fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt); + for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){ + fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]); + cDiv = ' '; + } + fprintf(yyTraceFILE,"]\n"); + } +#endif + return; +} diff --git a/storage/mroonga/vendor/groonga/lib/grn_ecmascript.h b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.h new file mode 100644 index 00000000..15272b0a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.h @@ -0,0 +1,74 @@ +#define GRN_EXPR_TOKEN_START_OUTPUT_COLUMNS 1 +#define GRN_EXPR_TOKEN_START_ADJUSTER 2 +#define GRN_EXPR_TOKEN_LOGICAL_AND 3 +#define GRN_EXPR_TOKEN_LOGICAL_AND_NOT 4 +#define GRN_EXPR_TOKEN_LOGICAL_OR 5 +#define GRN_EXPR_TOKEN_NEGATIVE 6 +#define GRN_EXPR_TOKEN_QSTRING 7 +#define GRN_EXPR_TOKEN_PARENL 8 +#define GRN_EXPR_TOKEN_PARENR 9 +#define GRN_EXPR_TOKEN_ADJUST 10 +#define GRN_EXPR_TOKEN_RELATIVE_OP 11 +#define GRN_EXPR_TOKEN_IDENTIFIER 12 +#define GRN_EXPR_TOKEN_BRACEL 13 +#define GRN_EXPR_TOKEN_BRACER 14 +#define GRN_EXPR_TOKEN_EVAL 15 +#define GRN_EXPR_TOKEN_COMMA 16 +#define GRN_EXPR_TOKEN_ASSIGN 17 +#define GRN_EXPR_TOKEN_STAR_ASSIGN 18 +#define GRN_EXPR_TOKEN_SLASH_ASSIGN 19 +#define GRN_EXPR_TOKEN_MOD_ASSIGN 20 +#define GRN_EXPR_TOKEN_PLUS_ASSIGN 21 +#define GRN_EXPR_TOKEN_MINUS_ASSIGN 22 +#define GRN_EXPR_TOKEN_SHIFTL_ASSIGN 23 +#define GRN_EXPR_TOKEN_SHIFTR_ASSIGN 24 +#define GRN_EXPR_TOKEN_SHIFTRR_ASSIGN 25 +#define GRN_EXPR_TOKEN_AND_ASSIGN 26 +#define GRN_EXPR_TOKEN_XOR_ASSIGN 27 +#define GRN_EXPR_TOKEN_OR_ASSIGN 28 +#define GRN_EXPR_TOKEN_QUESTION 29 +#define GRN_EXPR_TOKEN_COLON 30 +#define GRN_EXPR_TOKEN_BITWISE_OR 31 +#define GRN_EXPR_TOKEN_BITWISE_XOR 32 +#define GRN_EXPR_TOKEN_BITWISE_AND 33 +#define GRN_EXPR_TOKEN_EQUAL 34 +#define GRN_EXPR_TOKEN_NOT_EQUAL 35 +#define GRN_EXPR_TOKEN_LESS 36 +#define GRN_EXPR_TOKEN_GREATER 37 +#define GRN_EXPR_TOKEN_LESS_EQUAL 38 +#define GRN_EXPR_TOKEN_GREATER_EQUAL 39 +#define GRN_EXPR_TOKEN_IN 40 +#define GRN_EXPR_TOKEN_MATCH 41 +#define GRN_EXPR_TOKEN_NEAR 42 +#define GRN_EXPR_TOKEN_NEAR2 43 +#define GRN_EXPR_TOKEN_SIMILAR 44 +#define GRN_EXPR_TOKEN_TERM_EXTRACT 45 +#define GRN_EXPR_TOKEN_LCP 46 +#define GRN_EXPR_TOKEN_PREFIX 47 +#define GRN_EXPR_TOKEN_SUFFIX 48 +#define GRN_EXPR_TOKEN_REGEXP 49 +#define GRN_EXPR_TOKEN_SHIFTL 50 +#define GRN_EXPR_TOKEN_SHIFTR 51 +#define GRN_EXPR_TOKEN_SHIFTRR 52 +#define GRN_EXPR_TOKEN_PLUS 53 +#define GRN_EXPR_TOKEN_MINUS 54 +#define GRN_EXPR_TOKEN_STAR 55 +#define GRN_EXPR_TOKEN_SLASH 56 +#define GRN_EXPR_TOKEN_MOD 57 +#define GRN_EXPR_TOKEN_DELETE 58 +#define GRN_EXPR_TOKEN_INCR 59 +#define GRN_EXPR_TOKEN_DECR 60 +#define GRN_EXPR_TOKEN_NOT 61 +#define GRN_EXPR_TOKEN_BITWISE_NOT 62 +#define GRN_EXPR_TOKEN_EXACT 63 +#define GRN_EXPR_TOKEN_PARTIAL 64 +#define GRN_EXPR_TOKEN_UNSPLIT 65 +#define GRN_EXPR_TOKEN_DECIMAL 66 +#define GRN_EXPR_TOKEN_HEX_INTEGER 67 +#define GRN_EXPR_TOKEN_STRING 68 +#define GRN_EXPR_TOKEN_BOOLEAN 69 +#define GRN_EXPR_TOKEN_NULL 70 +#define GRN_EXPR_TOKEN_BRACKETL 71 +#define GRN_EXPR_TOKEN_BRACKETR 72 +#define GRN_EXPR_TOKEN_DOT 73 +#define GRN_EXPR_TOKEN_NONEXISTENT_COLUMN 74 diff --git a/storage/mroonga/vendor/groonga/lib/grn_ecmascript.lemon b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.lemon new file mode 100644 index 00000000..234ea41c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_ecmascript.lemon @@ -0,0 +1,581 @@ +/* -*- mode: c; c-basic-offset: 2 -*- */ +%name grn_expr_parser +%token_prefix GRN_EXPR_TOKEN_ +%include { +#ifdef assert +# undef assert +#endif +#define assert GRN_ASSERT +} + +%token_type { int } + +%type suppress_unused_variable_warning { void * } +%destructor suppress_unused_variable_warning { + (void)efsi; +} + +%extra_argument { efs_info *efsi } + +%syntax_error { + { + grn_ctx *ctx = efsi->ctx; + grn_obj message; + GRN_TEXT_INIT(&message, 0); + GRN_TEXT_PUT(ctx, &message, efsi->str, efsi->cur - efsi->str); + GRN_TEXT_PUTC(ctx, &message, '|'); + if (efsi->cur < efsi->str_end) { + GRN_TEXT_PUTC(ctx, &message, efsi->cur[0]); + GRN_TEXT_PUTC(ctx, &message, '|'); + GRN_TEXT_PUT(ctx, &message, + efsi->cur + 1, efsi->str_end - (efsi->cur + 1)); + } else { + GRN_TEXT_PUTC(ctx, &message, '|'); + } + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_SYNTAX_ERROR, "Syntax error: <%.*s>", + (int)GRN_TEXT_LEN(&message), GRN_TEXT_VALUE(&message)); + } else { + ERR(ctx->rc, "Syntax error: <%.*s>: %s", + (int)GRN_TEXT_LEN(&message), GRN_TEXT_VALUE(&message), + ctx->errbuf); + } + GRN_OBJ_FIN(ctx, &message); + } +} + +input ::= query. +input ::= expression. +input ::= START_OUTPUT_COLUMNS output_columns. +input ::= START_ADJUSTER adjuster. + +query ::= query_element. +query ::= query query_element. { + grn_expr_append_op(efsi->ctx, efsi->e, grn_int32_value_at(&efsi->op_stack, -1), 2); +} +query ::= query LOGICAL_AND query_element. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND, 2); +} +query ::= query LOGICAL_AND_NOT query_element.{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_NOT, 2); +} +query ::= query LOGICAL_OR query_element.{ + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR, 2); +} +query ::= query NEGATIVE query_element.{ + int weight; + GRN_INT32_POP(&efsi->weight_stack, weight); + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 2); +} + +query_element ::= QSTRING. +query_element ::= PARENL query PARENR. + +query_element ::= ADJUST query_element.{ + int weight; + GRN_INT32_POP(&efsi->weight_stack, weight); +} +query_element ::= RELATIVE_OP query_element.{ + int mode; + GRN_INT32_POP(&efsi->mode_stack, mode); +} +query_element ::= IDENTIFIER RELATIVE_OP query_element. { + int mode; + grn_obj *c; + GRN_PTR_POP(&efsi->column_stack, c); + GRN_INT32_POP(&efsi->mode_stack, mode); + switch (mode) { + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + { + int max_interval; + GRN_INT32_POP(&efsi->max_interval_stack, max_interval); + } + break; + case GRN_OP_SIMILAR : + { + int similarity_threshold; + GRN_INT32_POP(&efsi->similarity_threshold_stack, similarity_threshold); + } + break; + default : + break; + } +} +query_element ::= BRACEL expression BRACER. { + efsi->flags = efsi->default_flags; +} +query_element ::= EVAL primary_expression. { + efsi->flags = efsi->default_flags; +} + +expression ::= assignment_expression. +expression ::= expression COMMA assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2); +} + +assignment_expression ::= conditional_expression. +assignment_expression ::= lefthand_side_expression ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression STAR_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression SLASH_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression MOD_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression PLUS_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression MINUS_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression SHIFTL_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression SHIFTR_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression SHIFTRR_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression AND_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression XOR_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_XOR_ASSIGN, 2); +} +assignment_expression ::= lefthand_side_expression OR_ASSIGN assignment_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR_ASSIGN, 2); +} + +conditional_expression ::= logical_or_expression. +conditional_expression ::= logical_or_expression QUESTION(A) assignment_expression COLON(B) assignment_expression. { + grn_expr *e = (grn_expr *)efsi->e; + e->codes[A].nargs = B - A; + e->codes[B].nargs = e->codes_curr - B - 1; +} + +logical_or_expression ::= logical_and_expression. +logical_or_expression ::= logical_or_expression LOGICAL_OR logical_and_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_OR, 2); +} + +logical_and_expression ::= bitwise_or_expression. +logical_and_expression ::= logical_and_expression LOGICAL_AND bitwise_or_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND, 2); +} +logical_and_expression ::= logical_and_expression LOGICAL_AND_NOT bitwise_or_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_AND_NOT, 2); +} + +bitwise_or_expression ::= bitwise_xor_expression. +bitwise_or_expression ::= bitwise_or_expression BITWISE_OR bitwise_xor_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_OR, 2); +} + +bitwise_xor_expression ::= bitwise_and_expression. +bitwise_xor_expression ::= bitwise_xor_expression BITWISE_XOR bitwise_and_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_XOR, 2); +} + +bitwise_and_expression ::= equality_expression. +bitwise_and_expression ::= bitwise_and_expression BITWISE_AND equality_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_AND, 2); +} + +equality_expression ::= relational_expression. +equality_expression ::= equality_expression EQUAL relational_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EQUAL, 2); +} +equality_expression ::= equality_expression NOT_EQUAL relational_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT_EQUAL, 2); +} + +relational_expression ::= shift_expression. +relational_expression ::= relational_expression LESS shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS, 2); +} +relational_expression ::= relational_expression GREATER shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER, 2); +} +relational_expression ::= relational_expression LESS_EQUAL shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LESS_EQUAL, 2); +} +relational_expression ::= relational_expression GREATER_EQUAL shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GREATER_EQUAL, 2); +} +relational_expression ::= relational_expression IN shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_IN, 2); +} +relational_expression ::= relational_expression MATCH shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MATCH, 2); +} +relational_expression ::= relational_expression NEAR shift_expression. { + { + int max_interval; + GRN_INT32_POP(&efsi->max_interval_stack, max_interval); + grn_expr_append_const_int(efsi->ctx, efsi->e, max_interval, + GRN_OP_PUSH, 1); + } + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR, 3); +} +relational_expression ::= relational_expression NEAR2 shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NEAR2, 2); +} +relational_expression ::= relational_expression SIMILAR shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SIMILAR, 2); +} +relational_expression ::= relational_expression TERM_EXTRACT shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_TERM_EXTRACT, 2); +} +relational_expression ::= relational_expression LCP shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_LCP, 2); +} +relational_expression ::= relational_expression PREFIX shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PREFIX, 2); +} +relational_expression ::= relational_expression SUFFIX shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SUFFIX, 2); +} +relational_expression ::= relational_expression REGEXP shift_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_REGEXP, 2); +} + +shift_expression ::= additive_expression. +shift_expression ::= shift_expression SHIFTL additive_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTL, 2); +} +shift_expression ::= shift_expression SHIFTR additive_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTR, 2); +} +shift_expression ::= shift_expression SHIFTRR additive_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SHIFTRR, 2); +} + +additive_expression ::= multiplicative_expression. +additive_expression ::= additive_expression PLUS multiplicative_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 2); +} +additive_expression ::= additive_expression MINUS multiplicative_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 2); +} + +multiplicative_expression ::= unary_expression. +multiplicative_expression ::= multiplicative_expression STAR unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR, 2); +} +multiplicative_expression ::= multiplicative_expression SLASH unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_SLASH, 2); +} +multiplicative_expression ::= multiplicative_expression MOD unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MOD, 2); +} + +unary_expression ::= postfix_expression. +unary_expression ::= DELETE unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DELETE, 1); +} +unary_expression ::= INCR unary_expression. { + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_expr_dfi *dfi_; + unsigned int const_p; + + dfi_ = grn_expr_dfi_pop(e); + const_p = CONSTP(dfi_->code->value); + grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); + if (const_p) { + ERR(GRN_SYNTAX_ERROR, + "constant can't be incremented: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR, 1); + } +} +unary_expression ::= DECR unary_expression. { + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_expr_dfi *dfi_; + unsigned int const_p; + + dfi_ = grn_expr_dfi_pop(e); + const_p = CONSTP(dfi_->code->value); + grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); + if (const_p) { + ERR(GRN_SYNTAX_ERROR, + "constant can't be decremented: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR, 1); + } +} +unary_expression ::= PLUS unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 1); +} +unary_expression ::= MINUS unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MINUS, 1); +} +unary_expression ::= NOT unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_NOT, 1); +} +unary_expression ::= BITWISE_NOT unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_BITWISE_NOT, 1); +} +unary_expression ::= ADJUST unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_ADJUST, 1); +} +unary_expression ::= EXACT unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_EXACT, 1); +} +unary_expression ::= PARTIAL unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PARTIAL, 1); +} +unary_expression ::= UNSPLIT unary_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_UNSPLIT, 1); +} + +postfix_expression ::= lefthand_side_expression. +postfix_expression ::= lefthand_side_expression INCR. { + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_expr_dfi *dfi_; + unsigned int const_p; + + dfi_ = grn_expr_dfi_pop(e); + const_p = CONSTP(dfi_->code->value); + grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); + if (const_p) { + ERR(GRN_SYNTAX_ERROR, + "constant can't be incremented: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_INCR_POST, 1); + } +} +postfix_expression ::= lefthand_side_expression DECR. { + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_expr_dfi *dfi_; + unsigned int const_p; + + dfi_ = grn_expr_dfi_pop(e); + const_p = CONSTP(dfi_->code->value); + grn_expr_dfi_put(ctx, e, dfi_->type, dfi_->domain, dfi_->code); + if (const_p) { + ERR(GRN_SYNTAX_ERROR, + "constant can't be decremented: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_DECR_POST, 1); + } +} + +lefthand_side_expression ::= call_expression. +lefthand_side_expression ::= member_expression. + +call_expression ::= member_expression arguments(A). { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_CALL, A); +} + +member_expression ::= primary_expression. +member_expression ::= member_expression member_expression_part. + +primary_expression ::= object_literal. +primary_expression ::= PARENL expression PARENR. +primary_expression ::= IDENTIFIER. +primary_expression ::= array_literal. +primary_expression ::= DECIMAL. +primary_expression ::= HEX_INTEGER. +primary_expression ::= STRING. +primary_expression ::= BOOLEAN. +primary_expression ::= NULL. + +array_literal ::= BRACKETL elision BRACKETR. +array_literal ::= BRACKETL element_list elision BRACKETR. +array_literal ::= BRACKETL element_list BRACKETR. + +elision ::= COMMA. +elision ::= elision COMMA. + +element_list ::= assignment_expression. +element_list ::= elision assignment_expression. +element_list ::= element_list elision assignment_expression. + +object_literal ::= BRACEL property_name_and_value_list BRACER. { + grn_ctx *ctx = efsi->ctx; + grn_expr_take_obj(ctx, efsi->e, (grn_obj *)(efsi->object_literal)); + grn_expr_append_obj(ctx, efsi->e, (grn_obj *)(efsi->object_literal), + GRN_OP_PUSH, 1); + efsi->object_literal = NULL; +} + +property_name_and_value_list ::= . { + grn_ctx *ctx = efsi->ctx; + + efsi->object_literal = + grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj), + GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY); + if (!efsi->object_literal) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "couldn't create hash table for parsing object literal: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } +} +property_name_and_value_list ::= property_name_and_value. +property_name_and_value_list ::= property_name_and_value_list COMMA property_name_and_value. + +property_name_and_value ::= property_name COLON assignment_expression. { + grn_ctx *ctx = efsi->ctx; + grn_expr *e = (grn_expr *)(efsi->e); + grn_obj *property = e->codes[e->codes_curr - 3].value; + grn_obj *value = e->codes[e->codes_curr - 1].value; + + if (!efsi->object_literal) { + efsi->object_literal = + grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, sizeof(grn_obj), + GRN_OBJ_KEY_VAR_SIZE|GRN_OBJ_TEMPORARY|GRN_HASH_TINY); + } + + if (!efsi->object_literal) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "couldn't create hash table for parsing object literal: <%.*s>", + (int)(efsi->str_end - efsi->str), efsi->str); + } else { + grn_obj *buf; + int added; + if (grn_hash_add(ctx, (grn_hash *)efsi->object_literal, + GRN_TEXT_VALUE(property), GRN_TEXT_LEN(property), + (void **)&buf, &added)) { + if (added) { + GRN_OBJ_INIT(buf, value->header.type, 0, value->header.domain); + GRN_TEXT_PUT(ctx, buf, GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value)); + grn_expr_dfi_pop(e); + e->codes_curr -= 3; + } else { + ERR(GRN_INVALID_ARGUMENT, + "duplicated property name: <%.*s>", + (int)GRN_TEXT_LEN(property), + GRN_TEXT_VALUE(property)); + } + } else { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to add a property to object literal: <%.*s>", + (int)GRN_TEXT_LEN(property), + GRN_TEXT_VALUE(property)); + } + } +} + +property_name ::= STRING. + +member_expression_part ::= BRACKETL expression BRACKETR. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_GET_MEMBER, 2); +} +member_expression_part ::= DOT IDENTIFIER. + +arguments(A) ::= PARENL argument_list(B) PARENR. { A = B; } +argument_list(A) ::= . { A = 0; } +argument_list(A) ::= assignment_expression. { A = 1; } +argument_list(A) ::= argument_list(B) COMMA assignment_expression. { A = B + 1; } + +output_columns(N_STACKED_COLUMNS) ::= . { + N_STACKED_COLUMNS = 0; +} +output_columns(N_STACKED_COLUMNS) ::= output_column(SUB_N_STACKED_COLUMNS). { + N_STACKED_COLUMNS = SUB_N_STACKED_COLUMNS; +} +/* Accept "column1,,,,,,column2" */ +output_columns(N_STACKED_COLUMNS) ::= + output_columns(SUB_N_STACKED_COLUMNS) COMMA. { + N_STACKED_COLUMNS = SUB_N_STACKED_COLUMNS; +} +output_columns(N_STACKED_COLUMNS) ::= + output_columns(SUB_N_STACKED_COLUMNS) COMMA + output_column(NEW_N_STACKED_COLUMNS). { + if (SUB_N_STACKED_COLUMNS == 0) { + N_STACKED_COLUMNS = NEW_N_STACKED_COLUMNS; + } else if (NEW_N_STACKED_COLUMNS == 0) { + N_STACKED_COLUMNS = SUB_N_STACKED_COLUMNS; + } else { + if (NEW_N_STACKED_COLUMNS == 1) { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_COMMA, 2); + } + N_STACKED_COLUMNS = 1; + } +} + +output_column(N_STACKED_COLUMNS) ::= STAR. { + grn_ctx *ctx = efsi->ctx; + grn_obj *expr = efsi->e; + grn_obj *variable = grn_expr_get_var_by_offset(ctx, expr, 0); + if (variable) { + grn_id table_id = GRN_OBJ_GET_DOMAIN(variable); + grn_obj *table = grn_ctx_at(ctx, table_id); + grn_obj columns_buffer; + int n_columns; + grn_obj **columns; + + GRN_PTR_INIT(&columns_buffer, GRN_OBJ_VECTOR, GRN_ID_NIL); + grn_obj_columns(ctx, table, "*", strlen("*"), &columns_buffer); + n_columns = GRN_BULK_VSIZE(&columns_buffer) / sizeof(grn_obj *); + columns = (grn_obj **)GRN_BULK_HEAD(&columns_buffer); + + if (n_columns == 0) { + /* do nothing */ + } else if (n_columns == 1) { + grn_obj *column = columns[0]; + grn_expr_append_const(ctx, expr, column, GRN_OP_GET_VALUE, 1); + if (column->header.type == GRN_ACCESSOR) { + grn_expr_take_obj(ctx, expr, column); + } + } else { + grn_expr *e = (grn_expr *)expr; + grn_bool have_column; + int i; + + have_column = (e->codes_curr > 0); + for (i = 0; i < n_columns; i++) { + grn_obj *column = columns[i]; + grn_expr_append_const(ctx, expr, column, GRN_OP_GET_VALUE, 1); + if (have_column || i > 0) { + grn_expr_append_op(ctx, expr, GRN_OP_COMMA, 2); + } + if (column->header.type == GRN_ACCESSOR) { + grn_expr_take_obj(ctx, expr, column); + } + } + } + + GRN_OBJ_FIN(ctx, &columns_buffer); + + N_STACKED_COLUMNS = n_columns; + } else { + /* TODO: report error */ + N_STACKED_COLUMNS = 0; + } +} +output_column(N_STACKED_COLUMNS) ::= NONEXISTENT_COLUMN. { + N_STACKED_COLUMNS = 0; +} +output_column(N_STACKED_COLUMNS) ::= assignment_expression. { + N_STACKED_COLUMNS = 1; +} + +adjuster ::= . +adjuster ::= adjust_expression. +adjuster ::= adjuster PLUS adjust_expression. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_PLUS, 2); +} + +adjust_expression ::= adjust_match_expression. +adjust_expression ::= adjust_match_expression STAR DECIMAL. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_STAR, 2); +} + +adjust_match_expression ::= IDENTIFIER MATCH STRING. { + grn_expr_append_op(efsi->ctx, efsi->e, GRN_OP_MATCH, 2); +} diff --git a/storage/mroonga/vendor/groonga/lib/grn_error.h b/storage/mroonga/vendor/groonga/lib/grn_error.h new file mode 100644 index 00000000..6917de83 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_error.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +GRN_API const char *grn_current_error_message(void); +GRN_API const char *grn_strerror(int error_code); + +GRN_API grn_rc grn_windows_error_code_to_rc(int error_code); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_expr.h b/storage/mroonga/vendor/groonga/lib/grn_expr.h new file mode 100644 index 00000000..e270e185 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_expr.h @@ -0,0 +1,86 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define SCAN_ACCESSOR (0x01) +#define SCAN_PUSH (0x02) +#define SCAN_POP (0x04) +#define SCAN_PRE_CONST (0x08) + +typedef enum { + SCAN_START = 0, + SCAN_VAR, + SCAN_COL1, + SCAN_COL2, + SCAN_CONST +} scan_stat; + +typedef struct _grn_scan_info scan_info; +typedef grn_bool (*grn_scan_info_each_arg_callback)(grn_ctx *ctx, grn_obj *obj, void *user_data); + +void grn_expr_init_from_env(void); + +scan_info **grn_scan_info_build(grn_ctx *ctx, grn_obj *expr, int *n, + grn_operator op, grn_bool record_exist); + +scan_info *grn_scan_info_open(grn_ctx *ctx, int start); +void grn_scan_info_close(grn_ctx *ctx, scan_info *si); +void grn_scan_info_put_index(grn_ctx *ctx, scan_info *si, grn_obj *index, + uint32_t sid, int32_t weight, + grn_obj *scorer, + grn_obj *scorer_args_expr, + uint32_t scorer_args_expr_offset); +scan_info **grn_scan_info_put_logical_op(grn_ctx *ctx, scan_info **sis, int *ip, + grn_operator op, int start); +int grn_scan_info_get_flags(scan_info *si); +void grn_scan_info_set_flags(scan_info *si, int flags); +grn_operator grn_scan_info_get_logical_op(scan_info *si); +void grn_scan_info_set_logical_op(scan_info *si, grn_operator logical_op); +grn_operator grn_scan_info_get_op(scan_info *si); +void grn_scan_info_set_op(scan_info *si, grn_operator op); +void grn_scan_info_set_end(scan_info *si, uint32_t end); +void grn_scan_info_set_query(scan_info *si, grn_obj *query); +int grn_scan_info_get_max_interval(scan_info *si); +void grn_scan_info_set_max_interval(scan_info *si, int max_interval); +int grn_scan_info_get_similarity_threshold(scan_info *si); +void grn_scan_info_set_similarity_threshold(scan_info *si, int similarity_threshold); +grn_bool grn_scan_info_push_arg(scan_info *si, grn_obj *arg); +grn_obj *grn_scan_info_get_arg(grn_ctx *ctx, scan_info *si, int i); +int grn_scan_info_get_start_position(scan_info *si); +void grn_scan_info_set_start_position(scan_info *si, int start); +void grn_scan_info_reset_position(scan_info *si); + +int32_t grn_expr_code_get_weight(grn_ctx *ctx, grn_expr_code *ec, uint32_t *offset); +grn_rc grn_expr_code_inspect_indented(grn_ctx *ctx, + grn_obj *buffer, + grn_expr_code *code, + const char *indent); +void grn_p_expr_code(grn_ctx *ctx, grn_expr_code *code); + +grn_obj *grn_expr_alloc_const(grn_ctx *ctx, grn_obj *expr); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_expr_code.h b/storage/mroonga/vendor/groonga/lib/grn_expr_code.h new file mode 100644 index 00000000..48c907d5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_expr_code.h @@ -0,0 +1,33 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +unsigned int grn_expr_code_n_used_codes(grn_ctx *ctx, + grn_expr_code *start, + grn_expr_code *target); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_expr_executor.h b/storage/mroonga/vendor/groonga/lib/grn_expr_executor.h new file mode 100644 index 00000000..1f2a1f4e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_expr_executor.h @@ -0,0 +1,39 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _grn_expr_executor grn_expr_executor; + +grn_expr_executor *grn_expr_executor_open(grn_ctx *ctx, + grn_obj *expr); +grn_obj *grn_expr_executor_exec(grn_ctx *ctx, + grn_expr_executor *executor, + grn_id id); +grn_rc grn_expr_executor_close(grn_ctx *ctx, + grn_expr_executor *executor); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_file_lock.h b/storage/mroonga/vendor/groonga/lib/grn_file_lock.h new file mode 100644 index 00000000..538e88af --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_file_lock.h @@ -0,0 +1,48 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + const char *path; +#ifdef WIN32 + HANDLE handle; +#else /* WIN32 */ + int fd; +#endif /* WIN32 */ +} grn_file_lock; + +void grn_file_lock_init(grn_ctx *ctx, + grn_file_lock *file_lock, + const char *path); +grn_bool grn_file_lock_acquire(grn_ctx *ctx, + grn_file_lock *file_lock, + int timeout, + const char *error_message_tag); +void grn_file_lock_release(grn_ctx *ctx, grn_file_lock *file_lock); +void grn_file_lock_fin(grn_ctx *ctx, grn_file_lock *file_lock); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_geo.h b/storage/mroonga/vendor/groonga/lib/grn_geo.h new file mode 100644 index 00000000..9597336a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_geo.h @@ -0,0 +1,200 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ii.h" +#include "grn_db.h" + +#if defined(WIN32) || defined(__sun) +# define _USE_MATH_DEFINES +# ifndef MAX +# define MAX(a, b) ((a) > (b) ? (a) : (b)) +# endif + +# ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +# endif +#endif /* WIN32 or __sun */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_GEO_RESOLUTION 3600000 +#define GRN_GEO_RADIUS 6357303 +#define GRN_GEO_BES_C1 6334834 +#define GRN_GEO_BES_C2 6377397 +#define GRN_GEO_BES_C3 0.006674 +#define GRN_GEO_GRS_C1 6335439 +#define GRN_GEO_GRS_C2 6378137 +#define GRN_GEO_GRS_C3 0.006694 +#define GRN_GEO_INT2RAD(x) ((M_PI / (GRN_GEO_RESOLUTION * 180)) * (x)) +#define GRN_GEO_RAD2INT(x) ((int)(((GRN_GEO_RESOLUTION * 180) / M_PI) * (x))) + +#define GRN_GEO_MAX_LATITUDE 324000000 /* 90 * 60 * 60 * 1000 */ +#define GRN_GEO_MAX_LONGITUDE (648000000 - 1) /* 180 * 60 * 60 * 1000 - 1 */ +#define GRN_GEO_MIN_LATITUDE -GRN_GEO_MAX_LATITUDE +#define GRN_GEO_MIN_LONGITUDE -GRN_GEO_MAX_LONGITUDE + +#define GRN_GEO_POINT_VALUE_RAW(obj) (grn_geo_point *)GRN_BULK_HEAD(obj) +#define GRN_GEO_POINT_VALUE_RADIUS(obj,_latitude,_longitude) do {\ + grn_geo_point *_val = (grn_geo_point *)GRN_BULK_HEAD(obj);\ + _latitude = GRN_GEO_INT2RAD(_val->latitude);\ + _longitude = GRN_GEO_INT2RAD(_val->longitude);\ +} while (0) + +#define GRN_GEO_KEY_MAX_BITS 64 + +typedef enum { + GRN_GEO_APPROXIMATE_RECTANGLE, + GRN_GEO_APPROXIMATE_SPHERE, + GRN_GEO_APPROXIMATE_ELLIPSOID +} grn_geo_approximate_type; + +typedef enum { + GRN_GEO_CURSOR_ENTRY_STATUS_NONE = 0, + GRN_GEO_CURSOR_ENTRY_STATUS_TOP_INCLUDED = 1 << 0, + GRN_GEO_CURSOR_ENTRY_STATUS_BOTTOM_INCLUDED = 1 << 1, + GRN_GEO_CURSOR_ENTRY_STATUS_LEFT_INCLUDED = 1 << 2, + GRN_GEO_CURSOR_ENTRY_STATUS_RIGHT_INCLUDED = 1 << 3, + GRN_GEO_CURSOR_ENTRY_STATUS_LATITUDE_INNER = 1 << 4, + GRN_GEO_CURSOR_ENTRY_STATUS_LONGITUDE_INNER = 1 << 5 +} grn_geo_cursor_entry_status_flag; + +typedef enum { + GRN_GEO_AREA_NORTH_EAST, + GRN_GEO_AREA_NORTH_WEST, + GRN_GEO_AREA_SOUTH_WEST, + GRN_GEO_AREA_SOUTH_EAST, + GRN_GEO_AREA_LAST +} grn_geo_area_type; + +#define GRN_GEO_N_AREAS GRN_GEO_AREA_LAST + +typedef struct { + uint8_t key[sizeof(grn_geo_point)]; + int target_bit; + int status_flags; +} grn_geo_cursor_entry; + +typedef struct { + grn_geo_point top_left; + grn_geo_point bottom_right; + uint8_t top_left_key[sizeof(grn_geo_point)]; + uint8_t bottom_right_key[sizeof(grn_geo_point)]; + int current_entry; + grn_geo_cursor_entry entries[GRN_GEO_KEY_MAX_BITS]; +} grn_geo_cursor_area; + +typedef struct { + grn_db_obj obj; + grn_obj *pat; + grn_obj *index; + grn_geo_point top_left; + grn_geo_point bottom_right; + grn_geo_point current; + grn_table_cursor *pat_cursor; + grn_ii_cursor *ii_cursor; + int offset; + int rest; + int minimum_reduce_bit; + grn_geo_area_type current_area; + grn_geo_cursor_area areas[GRN_GEO_N_AREAS]; +} grn_geo_cursor_in_rectangle; + +grn_rc grn_geo_cursor_close(grn_ctx *ctx, grn_obj *geo_cursor); + + +grn_rc grn_geo_resolve_approximate_type(grn_ctx *ctx, grn_obj *type_name, + grn_geo_approximate_type *type); + +/** + * grn_geo_select_in_circle: + * @index: the index column for TokyoGeoPoint or WGS84GeoPpoint type. + * @center_point: the center point of the target circle. (ShortText, Text, + * LongText, TokyoGeoPoint or WGS84GeoPoint) + * @distance: the radius of the target circle (Int32, + * UInt32, Int64, UInt64 or Float) or the point + * on the circumference of the target circle. (ShortText, Text, LongText, + * TokyoGeoPoint or WGS84GeoPoint) + * @approximate_type: the approximate type to compute + * distance. + * @res: the table to store found record IDs. It must be + * GRN_TABLE_HASH_KEY type table. + * @op: the operator for matched records. + * + * It selects records that are in the circle specified by + * @center_point and @distance from @center_point. Records + * are searched by @index. Found records are added to @res + * table with @op operation. + **/ +grn_rc grn_geo_select_in_circle(grn_ctx *ctx, + grn_obj *index, + grn_obj *center_point, + grn_obj *distance, + grn_geo_approximate_type approximate_type, + grn_obj *res, + grn_operator op); + +grn_rc grn_selector_geo_in_circle(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op); +grn_rc grn_selector_geo_in_rectangle(grn_ctx *ctx, + grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op); + +GRN_API grn_bool grn_geo_in_circle(grn_ctx *ctx, grn_obj *point, grn_obj *center, + grn_obj *radius_or_point, + grn_geo_approximate_type approximate_type); +GRN_API grn_bool grn_geo_in_rectangle(grn_ctx *ctx, grn_obj *point, + grn_obj *top_left, grn_obj *bottom_right); +grn_bool grn_geo_in_rectangle_raw(grn_ctx *ctx, grn_geo_point *point, + grn_geo_point *top_left, + grn_geo_point *bottom_right); +double grn_geo_distance(grn_ctx *ctx, grn_obj *point1, grn_obj *point2, + grn_geo_approximate_type type); +GRN_API double grn_geo_distance_rectangle(grn_ctx *ctx, grn_obj *point1, + grn_obj *point2); +GRN_API double grn_geo_distance_sphere(grn_ctx *ctx, grn_obj *point1, + grn_obj *point2); +GRN_API double grn_geo_distance_ellipsoid(grn_ctx *ctx, grn_obj *point1, + grn_obj *point2); +double grn_geo_distance_rectangle_raw(grn_ctx *ctx, + grn_geo_point *point1, + grn_geo_point *point2); +double grn_geo_distance_sphere_raw(grn_ctx *ctx, + grn_geo_point *point1, + grn_geo_point *point2); +double grn_geo_distance_ellipsoid_raw(grn_ctx *ctx, + grn_geo_point *point1, + grn_geo_point *point2, + int c1, int c2, double c3); +double grn_geo_distance_ellipsoid_raw_tokyo(grn_ctx *ctx, + grn_geo_point *point1, + grn_geo_point *point2); +double grn_geo_distance_ellipsoid_raw_wgs84(grn_ctx *ctx, + grn_geo_point *point1, + grn_geo_point *point2); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_hash.h b/storage/mroonga/vendor/groonga/lib/grn_hash.h new file mode 100644 index 00000000..4038909b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_hash.h @@ -0,0 +1,378 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**** grn_tiny_array ****/ + +/* + * grn_tiny_array_init() accepts a logical OR of the following flags. + * Note that other flags, such as (1 << 30), will be ignored. + * + * - GRN_TINY_ARRAY_CLEAR specifies to initialize a new block with zeros. + * It is valid only iff specified with GRN_TINY_ARRAY_USE_MALLOC. + * - GRN_TINY_ARRAY_THREADSAFE specifies to create a critical section when + * allocating memory. + * - GRN_TINY_ARRAY_USE_MALLOC specifies to use GRN_MALLOC/CALLOC/FREE instead + * of GRN_CTX_ALLOC/FREE. + */ +#define GRN_TINY_ARRAY_CLEAR (1 << 0) +#define GRN_TINY_ARRAY_THREADSAFE (1 << 1) +#define GRN_TINY_ARRAY_USE_MALLOC (1 << 2) + +/* + * - GRN_TINY_ARRAY_FACTOR is the global parameter of grn_tiny_array. + * - GRN_TINY_ARRAY_GET_OFFSET() returns the offset of a specified block. + * - GRN_TINY_ARRAY_BASE_BLOCK_SIZE is the number of elements in the first + * block. + * - GRN_TINY_ARRAY_GET_BLOCK_SIZE() returns the number of elements in a + * specified block. + * - GRN_TINY_ARRAY_NUM_BLOCKS is the maximum number of blocks. + */ +#define GRN_TINY_ARRAY_FACTOR 0 +#define GRN_TINY_ARRAY_GET_OFFSET(block_id) \ + (1 << ((block_id) << GRN_TINY_ARRAY_FACTOR)) +#define GRN_TINY_ARRAY_BASE_BLOCK_SIZE \ + (GRN_TINY_ARRAY_GET_OFFSET(1) - GRN_TINY_ARRAY_GET_OFFSET(0)) +#define GRN_TINY_ARRAY_GET_BLOCK_SIZE(block_id) \ + (GRN_TINY_ARRAY_BASE_BLOCK_SIZE * GRN_TINY_ARRAY_GET_OFFSET(block_id)) +#define GRN_TINY_ARRAY_NUM_BLOCKS (32 >> GRN_TINY_ARRAY_FACTOR) + +/* + * grn_tiny_array uses several blocks to emulate an array. + * The k-th block, blocks[k - 1], consists of 2^(k-1) elements. + */ +typedef struct _grn_tiny_array grn_tiny_array; + +struct _grn_tiny_array { + grn_ctx *ctx; + grn_id max; + uint16_t element_size; + uint16_t flags; + void *blocks[GRN_TINY_ARRAY_NUM_BLOCKS]; + grn_critical_section lock; +}; + +#define GRN_TINY_ARRAY_EACH(array, head, tail, key, value, block) do { \ + int _block_id; \ + const grn_id _head = (head); \ + const grn_id _tail = (tail); \ + for (_block_id = 0, (key) = (_head); \ + _block_id < GRN_TINY_ARRAY_NUM_BLOCKS && (key) <= (_tail); \ + _block_id++) { \ + int _id = GRN_TINY_ARRAY_GET_BLOCK_SIZE(_block_id); \ + (value) = (array)->blocks[_block_id]; \ + if (value) { \ + while (_id-- && (key) <= (_tail)) { \ + { \ + block \ + } \ + (key)++; \ + (value) = (void *)((byte *)(value) + (array)->element_size); \ + } \ + } else { \ + (key) += _id; \ + } \ + } \ +} while (0) + +GRN_API void grn_tiny_array_init(grn_ctx *ctx, grn_tiny_array *array, + uint16_t element_size, uint16_t flags); +GRN_API void grn_tiny_array_fin(grn_tiny_array *array); +GRN_API void *grn_tiny_array_at(grn_tiny_array *array, grn_id id); +GRN_API grn_id grn_tiny_array_id(grn_tiny_array *array, + const void *element_address); + +/**** grn_tiny_bitmap ****/ + +typedef struct _grn_tiny_bitmap grn_tiny_bitmap; + +struct _grn_tiny_bitmap { + grn_ctx *ctx; + void *blocks[GRN_TINY_ARRAY_NUM_BLOCKS]; +}; + +/**** grn_array ****/ + +#define GRN_ARRAY_TINY (0x01<<6) + +/* + * grn_array uses grn_io or grn_tiny_array to represent an array. + * + * To create a grn_tiny_array-based grn_array, specify the GRN_ARRAY_TINY flag + * to grn_array_create(). Note that a grn_tiny_array-based grn_array is not + * backed by a file. + */ +struct _grn_array { + grn_db_obj obj; + grn_ctx *ctx; + uint32_t value_size; + int32_t n_keys; + grn_table_sort_key *keys; + uint32_t *n_garbages; + uint32_t *n_entries; + + /* For grn_io_array. */ + grn_io *io; + struct grn_array_header *header; + uint32_t *lock; + + /* For grn_tiny_array. */ + uint32_t n_garbages_buf; + uint32_t n_entries_buf; + grn_id garbages; + grn_tiny_array array; + grn_tiny_bitmap bitmap; +}; + +struct _grn_array_cursor { + grn_db_obj obj; + grn_array *array; + grn_ctx *ctx; + grn_id curr_rec; + grn_id tail; + unsigned int rest; + int dir; +}; + +/* + * grn_array_size() returns the number of entries in an array. + * If the array was truncated by another process but `array` still refers to + * the old one, this function returns 0. + */ +uint32_t grn_array_size(grn_ctx *ctx, grn_array *array); + +uint32_t grn_array_get_flags(grn_ctx *ctx, grn_array *array); + +grn_rc grn_array_truncate(grn_ctx *ctx, grn_array *array); +grn_rc grn_array_copy_sort_key(grn_ctx *ctx, grn_array *array, + grn_table_sort_key *keys, int n_keys); + +/* grn_table_queue */ + +typedef struct _grn_table_queue grn_table_queue; + +struct _grn_table_queue { + grn_mutex mutex; + grn_cond cond; + grn_id head; + grn_id tail; + grn_id cap; + grn_bool unblock_requested; +}; + +GRN_API void grn_array_queue_lock_clear(grn_ctx *ctx, grn_array *array); +GRN_API void grn_array_clear_curr_rec(grn_ctx *ctx, grn_array *array); +GRN_API grn_table_queue *grn_array_queue(grn_ctx *ctx, grn_array *array); +GRN_API uint32_t grn_table_queue_size(grn_table_queue *queue); +GRN_API void grn_table_queue_head_increment(grn_table_queue *queue); +GRN_API void grn_table_queue_tail_increment(grn_table_queue *queue); +GRN_API grn_id grn_table_queue_head(grn_table_queue *queue); +GRN_API grn_id grn_table_queue_tail(grn_table_queue *queue); + +/**** grn_hash ****/ + +#define GRN_HASH_MAX_KEY_SIZE_NORMAL GRN_TABLE_MAX_KEY_SIZE +#define GRN_HASH_MAX_KEY_SIZE_LARGE (0xffff) + +#define GRN_HASH_IS_LARGE_KEY(hash)\ + ((hash)->key_size > GRN_HASH_MAX_KEY_SIZE_NORMAL) + +typedef struct _grn_hash_header_common grn_hash_header_common; +typedef struct _grn_hash_header_normal grn_hash_header_normal; +typedef struct _grn_hash_header_large grn_hash_header_large; + +struct _grn_hash { + grn_db_obj obj; + grn_ctx *ctx; + uint32_t key_size; + grn_encoding encoding; + uint32_t value_size; + uint32_t entry_size; + uint32_t *n_garbages; + uint32_t *n_entries; + uint32_t *max_offset; + grn_obj *tokenizer; + grn_obj *normalizer; + grn_obj token_filters; + + /* For grn_io_hash. */ + grn_io *io; + union { + grn_hash_header_common *common; + grn_hash_header_normal *normal; + grn_hash_header_large *large; + } header; + uint32_t *lock; + // uint32_t nref; + // unsigned int max_n_subrecs; + // unsigned int record_size; + // unsigned int subrec_size; + // grn_rec_unit record_unit; + // grn_rec_unit subrec_unit; + // uint8_t arrayp; + // grn_recordh *curr_rec; + // grn_set_cursor *cursor; + // int limit; + // void *userdata; + // grn_id subrec_id; + + /* For grn_tiny_hash. */ + uint32_t max_offset_; + uint32_t n_garbages_; + uint32_t n_entries_; + grn_id *index; + grn_id garbages; + grn_tiny_array a; + grn_tiny_bitmap bitmap; +}; + +#define GRN_HASH_HEADER_COMMON_FIELDS\ + uint32_t flags;\ + grn_encoding encoding;\ + uint32_t key_size;\ + uint32_t value_size;\ + grn_id tokenizer;\ + uint32_t curr_rec;\ + uint32_t curr_key_normal;\ + uint32_t idx_offset;\ + uint32_t entry_size;\ + uint32_t max_offset;\ + uint32_t n_entries;\ + uint32_t n_garbages;\ + uint32_t lock;\ + grn_id normalizer;\ + uint32_t truncated;\ + uint64_t curr_key_large;\ + uint32_t reserved[12] + +struct _grn_hash_header_common { + GRN_HASH_HEADER_COMMON_FIELDS; +}; + +struct _grn_hash_header_normal { + GRN_HASH_HEADER_COMMON_FIELDS; + grn_id garbages[GRN_HASH_MAX_KEY_SIZE_NORMAL]; + grn_table_queue queue; +}; + +struct _grn_hash_header_large { + GRN_HASH_HEADER_COMMON_FIELDS; + grn_id garbages[GRN_HASH_MAX_KEY_SIZE_LARGE]; + grn_table_queue queue; +}; + +struct _grn_hash_cursor { + grn_db_obj obj; + grn_hash *hash; + grn_ctx *ctx; + grn_id curr_rec; + grn_id tail; + unsigned int rest; + int dir; +}; + +/* deprecated */ + +#define GRN_TABLE_SORT_BY_KEY 0 +#define GRN_TABLE_SORT_BY_ID (1L<<1) +#define GRN_TABLE_SORT_BY_VALUE (1L<<2) +#define GRN_TABLE_SORT_RES_ID 0 +#define GRN_TABLE_SORT_RES_KEY (1L<<3) +#define GRN_TABLE_SORT_AS_BIN 0 +#define GRN_TABLE_SORT_AS_NUMBER (1L<<4) +#define GRN_TABLE_SORT_AS_SIGNED 0 +#define GRN_TABLE_SORT_AS_UNSIGNED (1L<<5) +#define GRN_TABLE_SORT_AS_INT32 0 +#define GRN_TABLE_SORT_AS_INT64 (1L<<6) +#define GRN_TABLE_SORT_NO_PROC 0 +#define GRN_TABLE_SORT_WITH_PROC (1L<<7) + +typedef struct _grn_table_sort_optarg grn_table_sort_optarg; + +struct _grn_table_sort_optarg { + grn_table_sort_flags flags; + int (*compar)(grn_ctx *ctx, + grn_obj *table1, void *target1, unsigned int target1_size, + grn_obj *table2, void *target2, unsigned int target2_size, + void *compare_arg); + void *compar_arg; + grn_obj *proc; + int offset; +}; + +GRN_API int grn_hash_sort(grn_ctx *ctx, grn_hash *hash, int limit, + grn_array *result, grn_table_sort_optarg *optarg); + +grn_rc grn_hash_lock(grn_ctx *ctx, grn_hash *hash, int timeout); +grn_rc grn_hash_unlock(grn_ctx *ctx, grn_hash *hash); +grn_rc grn_hash_clear_lock(grn_ctx *ctx, grn_hash *hash); + +#define GRN_HASH_SIZE(hash) (*((hash)->n_entries)) + +/* private */ +typedef enum { + grn_rec_document = 0, + grn_rec_section, + grn_rec_position, + grn_rec_userdef, + grn_rec_none +} grn_rec_unit; + +GRN_API grn_rc grn_hash_truncate(grn_ctx *ctx, grn_hash *hash); + +int grn_rec_unit_size(grn_rec_unit unit, int rec_size); + +const char * _grn_hash_key(grn_ctx *ctx, grn_hash *hash, grn_id id, uint32_t *key_size); + +int grn_hash_get_key_value(grn_ctx *ctx, grn_hash *hash, grn_id id, + void *keybuf, int bufsize, void *valuebuf); + +int _grn_hash_get_key_value(grn_ctx *ctx, grn_hash *hash, grn_id id, + void **key, void **value); + +grn_id grn_hash_next(grn_ctx *ctx, grn_hash *hash, grn_id id); + +/* only valid for hash tables, GRN_OBJ_KEY_VAR_SIZE && GRN_HASH_TINY */ +const char *_grn_hash_strkey_by_val(void *v, uint16_t *size); + +const char *grn_hash_get_value_(grn_ctx *ctx, grn_hash *hash, grn_id id, uint32_t *size); + +grn_rc grn_hash_remove(grn_ctx *ctx, const char *path); +grn_rc grn_array_remove(grn_ctx *ctx, const char *path); + +grn_id grn_hash_at(grn_ctx *ctx, grn_hash *hash, grn_id id); +grn_id grn_array_at(grn_ctx *ctx, grn_array *array, grn_id id); + +void grn_hash_check(grn_ctx *ctx, grn_hash *hash); + +grn_bool grn_hash_is_large_total_key_size(grn_ctx *ctx, grn_hash *hash); + +uint64_t grn_hash_total_key_size(grn_ctx *ctx, grn_hash *hash); +uint64_t grn_hash_max_total_key_size(grn_ctx *ctx, grn_hash *hash); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_ii.h b/storage/mroonga/vendor/groonga/lib/grn_ii.h new file mode 100644 index 00000000..0598c9e7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_ii.h @@ -0,0 +1,192 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +/* "ii" is for inverted index */ + +#include "grn.h" +#include "grn_hash.h" +#include "grn_io.h" +#include "grn_store.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct _grn_ii { + grn_db_obj obj; + grn_io *seg; /* I/O for a variety of segments */ + grn_io *chunk; /* I/O for posting chunks */ + grn_obj *lexicon; /* Lexicon table */ + grn_table_flags lflags; + grn_encoding encoding; /* Character encoding */ + /* This member is used for matching */ + uint32_t n_elements; /* Number of elements in postings */ + /* rid, [sid], tf, [weight] and [pos] */ + struct grn_ii_header *header; +}; + +/* BGQ is buffer garbage queue? */ +#define GRN_II_BGQSIZE 16 +#define GRN_II_MAX_LSEG 0x10000 +#define GRN_II_W_TOTAL_CHUNK 40 +#define GRN_II_W_CHUNK 22 +#define GRN_II_W_LEAST_CHUNK (GRN_II_W_TOTAL_CHUNK - 32) +#define GRN_II_MAX_CHUNK (1 << (GRN_II_W_TOTAL_CHUNK - GRN_II_W_CHUNK)) +#define GRN_II_N_CHUNK_VARIATION (GRN_II_W_CHUNK - GRN_II_W_LEAST_CHUNK) + +#define GRN_II_MAX_CHUNK_SMALL (1 << (GRN_II_W_TOTAL_CHUNK - GRN_II_W_CHUNK - 8)) +/* GRN_II_MAX_CHUNK_MEDIUM has enough space for the following source: + * * Single source. + * * Source is a fixed size column or _key of a table. + * * Source column is a scalar column. + * * Lexicon doesn't have tokenizer. + */ +#define GRN_II_MAX_CHUNK_MEDIUM (1 << (GRN_II_W_TOTAL_CHUNK - GRN_II_W_CHUNK - 4)) + +#define GRN_II_PSEG_NOT_ASSIGNED 0xffffffff + +struct grn_ii_header { + uint64_t total_chunk_size; + uint64_t bmax; + uint32_t flags; + uint32_t amax; + uint32_t smax; + uint32_t param1; + uint32_t param2; + uint32_t pnext; + uint32_t bgqhead; + uint32_t bgqtail; + uint32_t bgqbody[GRN_II_BGQSIZE]; + uint32_t reserved[288]; + uint32_t ainfo[GRN_II_MAX_LSEG]; /* array info */ + uint32_t binfo[GRN_II_MAX_LSEG]; /* buffer info */ + uint32_t free_chunks[GRN_II_N_CHUNK_VARIATION + 1]; + uint32_t garbages[GRN_II_N_CHUNK_VARIATION + 1]; + uint32_t ngarbages[GRN_II_N_CHUNK_VARIATION + 1]; + uint8_t chunks[GRN_II_MAX_CHUNK >> 3]; +}; + +struct _grn_ii_pos { + struct _grn_ii_pos *next; + uint32_t pos; +}; + +struct _grn_ii_updspec { + uint32_t rid; + uint32_t sid; + int32_t weight; + int32_t tf; /* number of postings successfully stored to index */ + int32_t atf; /* actual number of postings */ + int32_t offset; + struct _grn_ii_pos *pos; + struct _grn_ii_pos *tail; + /* grn_vgram_vnode *vnodes; */ +}; + +typedef struct _grn_ii_updspec grn_ii_updspec; + +void grn_ii_init_from_env(void); + +GRN_API grn_ii *grn_ii_create(grn_ctx *ctx, const char *path, grn_obj *lexicon, + uint32_t flags); +GRN_API grn_ii *grn_ii_open(grn_ctx *ctx, const char *path, grn_obj *lexicon); +GRN_API grn_rc grn_ii_close(grn_ctx *ctx, grn_ii *ii); +GRN_API grn_rc grn_ii_remove(grn_ctx *ctx, const char *path); +grn_rc grn_ii_info(grn_ctx *ctx, grn_ii *ii, uint64_t *seg_size, uint64_t *chunk_size); +grn_column_flags grn_ii_get_flags(grn_ctx *ctx, grn_ii *ii); +grn_rc grn_ii_update_one(grn_ctx *ctx, grn_ii *ii, uint32_t key, grn_ii_updspec *u, + grn_hash *h); +grn_rc grn_ii_delete_one(grn_ctx *ctx, grn_ii *ii, uint32_t key, grn_ii_updspec *u, + grn_hash *h); +grn_ii_updspec *grn_ii_updspec_open(grn_ctx *ctx, uint32_t rid, uint32_t sid); +grn_rc grn_ii_updspec_close(grn_ctx *ctx, grn_ii_updspec *u); +grn_rc grn_ii_updspec_add(grn_ctx *ctx, grn_ii_updspec *u, int pos, int32_t weight); +int grn_ii_updspec_cmp(grn_ii_updspec *a, grn_ii_updspec *b); + +void grn_ii_expire(grn_ctx *ctx, grn_ii *ii); +grn_rc grn_ii_flush(grn_ctx *ctx, grn_ii *ii); +size_t grn_ii_get_disk_usage(grn_ctx *ctx, grn_ii *ii); + +grn_ii_cursor *grn_ii_cursor_openv1(grn_ii *ii, uint32_t key); +grn_rc grn_ii_cursor_openv2(grn_ii_cursor **cursors, int ncursors); + +uint32_t grn_ii_max_section(grn_ii *ii); + +const char *grn_ii_path(grn_ii *ii); +grn_obj *grn_ii_lexicon(grn_ii *ii); + +/* +grn_rc grn_ii_upd(grn_ctx *ctx, grn_ii *ii, grn_id rid, grn_vgram *vgram, + const char *oldvalue, unsigned int oldvalue_len, + const char *newvalue, unsigned int newvalue_len); +grn_rc grn_ii_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, grn_vgram *vgram, + unsigned int section, + grn_values *oldvalues, grn_values *newvalues); +*/ + +typedef struct _grn_select_optarg grn_select_optarg; + +struct _grn_select_optarg { + grn_operator mode; + int similarity_threshold; + int max_interval; + int *weight_vector; + int vector_size; + int (*func)(grn_ctx *, grn_hash *, const void *, int, void *); + void *func_arg; + int max_size; + grn_obj *scorer; + grn_obj *scorer_args_expr; + unsigned int scorer_args_expr_offset; + grn_fuzzy_search_optarg fuzzy; + grn_match_info *match_info; +}; + +GRN_API grn_rc grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id id, + unsigned int section, grn_obj *oldvalue, + grn_obj *newvalue, grn_obj *posting); +grn_rc grn_ii_term_extract(grn_ctx *ctx, grn_ii *ii, const char *string, + unsigned int string_len, grn_hash *s, + grn_operator op, grn_select_optarg *optarg); +grn_rc grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len, + grn_hash *s, grn_operator op, grn_select_optarg *optarg); +GRN_API grn_rc grn_ii_select(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len, + grn_hash *s, grn_operator op, grn_select_optarg *optarg); +grn_rc grn_ii_sel(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len, + grn_hash *s, grn_operator op, grn_search_optarg *optarg); + +void grn_ii_resolve_sel_and(grn_ctx *ctx, grn_hash *s, grn_operator op); + +grn_rc grn_ii_at(grn_ctx *ctx, grn_ii *ii, grn_id id, grn_hash *s, grn_operator op); + +void grn_ii_inspect_values(grn_ctx *ctx, grn_ii *ii, grn_obj *buf); +void grn_ii_cursor_inspect(grn_ctx *ctx, grn_ii_cursor *c, grn_obj *buf); + +grn_rc grn_ii_truncate(grn_ctx *ctx, grn_ii *ii); +grn_rc grn_ii_build(grn_ctx *ctx, grn_ii *ii, uint64_t sparsity); + +typedef struct grn_ii_builder_options grn_ii_builder_options; + +grn_rc grn_ii_build2(grn_ctx *ctx, grn_ii *ii, + const grn_ii_builder_options *options); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_index_column.h b/storage/mroonga/vendor/groonga/lib/grn_index_column.h new file mode 100644 index 00000000..b9142d5c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_index_column.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_index_column_init_from_env(void); +grn_rc grn_index_column_build(grn_ctx *ctx, grn_obj *index_column); +grn_rc grn_index_column_rebuild(grn_ctx *ctx, grn_obj *index_column); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_io.h b/storage/mroonga/vendor/groonga/lib/grn_io.h new file mode 100644 index 00000000..bc5ecf7f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_io.h @@ -0,0 +1,487 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_error.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +# define GRN_IO_FILE_CREATE_MODE (GENERIC_READ | GENERIC_WRITE) +#else /* WIN32 */ +# define GRN_IO_FILE_CREATE_MODE 0644 +#endif /* WIN32 */ + +typedef enum { + grn_io_rdonly, + grn_io_wronly, + grn_io_rdwr +} grn_io_rw_mode; + +typedef enum { + grn_io_auto, + grn_io_manual +} grn_io_mode; + +/**** grn_io ****/ + +typedef struct _grn_io grn_io; + +typedef struct { + grn_io *io; + grn_ctx *ctx; + uint8_t mode; + uint8_t tiny_p; + uint32_t pseg; + uint32_t segment; + uint32_t offset; + uint32_t size; + uint32_t nseg; + off_t pos; + void *addr; + uint32_t diff; + int32_t cached; +#ifdef WIN32 + HANDLE fmo; +#endif /* WIN32 */ + void *uncompressed_value; +} grn_io_win; + +typedef struct { + void *map; + uint32_t nref; + uint32_t count; +#ifdef WIN32 + HANDLE fmo; +#endif /* WIN32 */ +} grn_io_mapinfo; + +typedef struct _grn_io_array_info grn_io_array_info; + +struct _grn_io_header { + char idstr[16]; + uint32_t type; + uint32_t version; + uint32_t flags; + uint32_t header_size; + uint32_t segment_size; + uint32_t max_segment; + uint32_t n_arrays; + uint32_t lock; + uint64_t curr_size; + uint32_t segment_tail; + uint32_t last_modified; +}; + +struct _grn_io { + char path[PATH_MAX]; + struct _grn_io_header *header; + byte *user_header; + grn_io_mapinfo *maps; + uint32_t base; + uint32_t base_seg; + grn_io_mode mode; + struct _grn_io_fileinfo *fis; + grn_io_array_info *ainfo; + uint32_t max_map_seg; + uint32_t nmaps; + uint32_t nref; + uint32_t count; + uint8_t flags; + uint32_t *lock; +}; + +GRN_API grn_io *grn_io_create(grn_ctx *ctx, const char *path, + uint32_t header_size, uint32_t segment_size, + uint32_t max_segment, grn_io_mode mode, + unsigned int flags); +grn_io *grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode); +GRN_API grn_rc grn_io_close(grn_ctx *ctx, grn_io *io); +grn_rc grn_io_remove(grn_ctx *ctx, const char *path); +grn_rc grn_io_remove_if_exist(grn_ctx *ctx, const char *path); +grn_rc grn_io_size(grn_ctx *ctx, grn_io *io, uint64_t *size); +grn_rc grn_io_rename(grn_ctx *ctx, const char *old_name, const char *new_name); +GRN_API void *grn_io_header(grn_io *io); + +void *grn_io_win_map(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment, + uint32_t offset, uint32_t size, grn_io_rw_mode mode); +grn_rc grn_io_win_unmap(grn_io_win *iw); + +typedef struct _grn_io_ja_einfo grn_io_ja_einfo; +typedef struct _grn_io_ja_ehead grn_io_ja_ehead; + +struct _grn_io_ja_einfo { + uint32_t pos; + uint32_t size; +}; + +struct _grn_io_ja_ehead { + uint32_t size; + uint32_t key; +}; + +grn_rc grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, + uint32_t key, uint32_t segment, uint32_t offset, + void **value, uint32_t *value_len); +grn_rc grn_io_write_ja(grn_io *io, grn_ctx *ctx, + uint32_t key, uint32_t segment, uint32_t offset, + void *value, uint32_t value_len); + +grn_rc grn_io_write_ja_ehead(grn_io *io, grn_ctx *ctx, uint32_t key, + uint32_t segment, uint32_t offset, uint32_t value_len); + +#define GRN_TABLE_ADD (0x01<<6) +#define GRN_TABLE_ADDED (0x01<<7) + +#define GRN_IO_MAX_RETRY (0x10000) +#define GRN_IO_MAX_REF (0x80000000) + +#define GRN_IO_EXPIRE_GTICK (0x01) +#define GRN_IO_EXPIRE_SEGMENT (0x02) +#define GRN_IO_TEMPORARY (0x04) + +void grn_io_seg_map_(grn_ctx *ctx, grn_io *io, uint32_t segno, grn_io_mapinfo *info); + +/* arguments must be validated by caller; + * io mustn't be NULL; + * segno must be in valid range; + * addr must be set NULL; + */ +#define GRN_IO_SEG_REF(io,segno,addr) do {\ + grn_io_mapinfo *info = &(io)->maps[segno];\ + uint32_t nref, retry, *pnref = &info->nref;\ + if (io->flags & GRN_IO_EXPIRE_SEGMENT) {\ + if (io->flags & GRN_IO_EXPIRE_GTICK) {\ + for (retry = 0; !info->map || info->count != grn_gtick; retry++) {\ + GRN_ATOMIC_ADD_EX(pnref, 1, nref);\ + if (nref) {\ + GRN_ATOMIC_ADD_EX(pnref, -1, nref);\ + if (retry >= GRN_IO_MAX_RETRY) {\ + GRN_LOG(ctx, GRN_LOG_CRIT,\ + "deadlock detected! in GRN_IO_SEG_REF(%p, %u)", io, segno);\ + break;\ + }\ + GRN_FUTEX_WAIT(pnref);\ + } else {\ + info->count = grn_gtick;\ + if (!info->map) {\ + grn_io_seg_map_(ctx, io, segno, info);\ + if (!info->map) {\ + GRN_LOG(ctx, GRN_LOG_CRIT,\ + "mmap failed! in GRN_IO_SEG_REF(%p, %u): %s",\ + io, segno, grn_current_error_message());\ + }\ + }\ + GRN_ATOMIC_ADD_EX(pnref, -1, nref);\ + GRN_FUTEX_WAKE(pnref);\ + break;\ + }\ + }\ + } else {\ + for (retry = 0;; retry++) {\ + GRN_ATOMIC_ADD_EX(pnref, 1, nref);\ + if (nref >= GRN_IO_MAX_REF) {\ + GRN_ATOMIC_ADD_EX(pnref, -1, nref);\ + if (retry >= GRN_IO_MAX_RETRY) {\ + GRN_LOG(ctx, GRN_LOG_CRIT,\ + "deadlock detected!! in GRN_IO_SEG_REF(%p, %u, %u)",\ + io, segno, nref);\ + *pnref = 0; /* force reset */ \ + break;\ + }\ + GRN_FUTEX_WAIT(pnref);\ + continue;\ + }\ + if (nref >= 0x40000000) {\ + ALERT("strange nref value!! in GRN_IO_SEG_REF(%p, %u, %u)",\ + io, segno, nref); \ + }\ + if (!info->map) {\ + if (nref) {\ + GRN_ATOMIC_ADD_EX(pnref, -1, nref);\ + if (retry >= GRN_IO_MAX_RETRY) {\ + GRN_LOG(ctx, GRN_LOG_CRIT,\ + "deadlock detected!!! in GRN_IO_SEG_REF(%p, %u, %u)",\ + io, segno, nref);\ + break;\ + }\ + GRN_FUTEX_WAIT(pnref);\ + continue;\ + } else {\ + grn_io_seg_map_(ctx, io, segno, info);\ + if (!info->map) {\ + GRN_ATOMIC_ADD_EX(pnref, -1, nref);\ + GRN_LOG(ctx, GRN_LOG_CRIT,\ + "mmap failed!!! in GRN_IO_SEG_REF(%p, %u, %u): %s",\ + io, segno, nref, grn_current_error_message());\ + }\ + \ + GRN_FUTEX_WAKE(pnref);\ + }\ + }\ + break;\ + }\ + info->count = grn_gtick;\ + }\ + } else {\ + for (retry = 0; !info->map; retry++) {\ + GRN_ATOMIC_ADD_EX(pnref, 1, nref);\ + if (nref) {\ + GRN_ATOMIC_ADD_EX(pnref, -1, nref);\ + if (retry >= GRN_IO_MAX_RETRY) {\ + GRN_LOG(ctx, GRN_LOG_CRIT,\ + "deadlock detected!!!! in GRN_IO_SEG_REF(%p, %u)",\ + io, segno);\ + break;\ + }\ + GRN_FUTEX_WAIT(pnref);\ + } else {\ + if (!info->map) {\ + grn_io_seg_map_(ctx, io, segno, info);\ + if (!info->map) {\ + GRN_LOG(ctx, GRN_LOG_CRIT,\ + "mmap failed!!!! in GRN_IO_SEG_REF(%p, %u): %s",\ + io, segno, grn_current_error_message());\ + }\ + }\ + GRN_ATOMIC_ADD_EX(pnref, -1, nref);\ + GRN_FUTEX_WAKE(pnref);\ + break;\ + }\ + }\ + info->count = grn_gtick;\ + }\ + addr = info->map;\ +} while (0) + +#define GRN_IO_SEG_UNREF(io,segno) do {\ + if (GRN_IO_EXPIRE_SEGMENT ==\ + (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) {\ + uint32_t nref, *pnref = &(io)->maps[segno].nref;\ + GRN_ATOMIC_ADD_EX(pnref, -1, nref);\ + }\ +} while (0) + +uint32_t grn_io_base_seg(grn_io *io); +const char *grn_io_path(grn_io *io); + +typedef struct _grn_io_array_spec grn_io_array_spec; + +struct _grn_io_array_spec { + uint32_t w_of_element; + uint32_t max_n_segments; +}; + +struct _grn_io_array_info { + uint32_t w_of_elm_in_a_segment; + uint32_t elm_mask_in_a_segment; + uint32_t max_n_segments; + uint32_t element_size; + uint32_t *segments; + void **addrs; +}; + +grn_io *grn_io_create_with_array(grn_ctx *ctx, const char *path, uint32_t header_size, + uint32_t segment_size, grn_io_mode mode, + int n_arrays, grn_io_array_spec *array_specs); + +void *grn_io_array_at(grn_ctx *ctx, grn_io *io, uint32_t array, off_t offset, int *flags); + +void grn_io_segment_alloc(grn_ctx *ctx, grn_io *io, grn_io_array_info *ai, + uint32_t lseg, int *flags, void **p); + +GRN_API grn_rc grn_io_lock(grn_ctx *ctx, grn_io *io, int timeout); +GRN_API void grn_io_unlock(grn_io *io); +void grn_io_clear_lock(grn_io *io); +uint32_t grn_io_is_locked(grn_io *io); +grn_bool grn_io_is_corrupt(grn_ctx *ctx, grn_io *io); +size_t grn_io_get_disk_usage(grn_ctx *ctx, grn_io *io); + +#define GRN_IO_ARRAY_AT(io,array,offset,flags,res) do {\ + grn_io_array_info *ainfo = &(io)->ainfo[array];\ + uint32_t lseg = (offset) >> ainfo->w_of_elm_in_a_segment;\ + void **p_ = &ainfo->addrs[lseg];\ + if (!*p_) {\ + grn_io_segment_alloc(ctx, (io), ainfo, lseg, (flags), p_);\ + if (!*p_) { (res) = NULL; break; }\ + }\ + *((byte **)(&(res))) = (((byte *)*p_) + \ + (((offset) & ainfo->elm_mask_in_a_segment) * ainfo->element_size));\ +} while (0) + +#define GRN_IO_ARRAY_BIT_AT(io,array,offset,res) do {\ + uint8_t *ptr_;\ + int flags_ = 0;\ + GRN_IO_ARRAY_AT((io), (array), ((offset) >> 3) + 1, &flags_, ptr_);\ + res = ptr_ ? ((*ptr_ >> ((offset) & 7)) & 1) : 0;\ +} while (0) + +#define GRN_IO_ARRAY_BIT_ON(io,array,offset) do {\ + uint8_t *ptr_;\ + int flags_ = GRN_TABLE_ADD;\ + GRN_IO_ARRAY_AT((io), (array), ((offset) >> 3) + 1, &flags_, ptr_);\ + if (ptr_) { *ptr_ |= (1 << ((offset) & 7)); }\ +} while (0) + +#define GRN_IO_ARRAY_BIT_OFF(io,array,offset) do {\ + uint8_t *ptr_;\ + int flags_ = GRN_TABLE_ADD;\ + GRN_IO_ARRAY_AT((io), (array), ((offset) >> 3) + 1, &flags_, ptr_);\ + if (ptr_) { *ptr_ &= ~(1 << ((offset) & 7)); }\ +} while (0) + +#define GRN_IO_ARRAY_BIT_FLIP(io,array,offset) do {\ + uint8_t *ptr_;\ + int flags_ = GRN_TABLE_ADD;\ + GRN_IO_ARRAY_AT((io), (array), ((offset) >> 3) + 1, &flags_, ptr_);\ + if (ptr_) { *ptr_ ^= (1 << ((offset) & 7)); }\ +} while (0) + +void *grn_io_anon_map(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length); +void grn_io_anon_unmap(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length); +uint32_t grn_io_detect_type(grn_ctx *ctx, const char *path); +grn_rc grn_io_set_type(grn_io *io, uint32_t type); +uint32_t grn_io_get_type(grn_io *io); + +void grn_io_init_from_env(void); + +uint32_t grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit); + +grn_rc grn_io_flush(grn_ctx *ctx, grn_io *io); + +/* encode/decode */ + +#define GRN_B_ENC(v,p) do {\ + uint8_t *_p = (uint8_t *)p; \ + uint32_t _v = v; \ + if (_v < 0x8f) { \ + *_p++ = _v; \ + } else if (_v < 0x408f) { \ + _v -= 0x8f; \ + *_p++ = 0xc0 + (_v >> 8); \ + *_p++ = _v & 0xff; \ + } else if (_v < 0x20408f) { \ + _v -= 0x408f; \ + *_p++ = 0xa0 + (_v >> 16); \ + *_p++ = (_v >> 8) & 0xff; \ + *_p++ = _v & 0xff; \ + } else if (_v < 0x1020408f) { \ + _v -= 0x20408f; \ + *_p++ = 0x90 + (_v >> 24); \ + *_p++ = (_v >> 16) & 0xff; \ + *_p++ = (_v >> 8) & 0xff; \ + *_p++ = _v & 0xff; \ + } else { \ + *_p++ = 0x8f; \ + grn_memcpy(_p, &_v, sizeof(uint32_t));\ + _p += sizeof(uint32_t); \ + } \ + p = _p; \ +} while (0) + +#define GRN_B_ENC_SIZE(v) \ + ((v) < 0x8f ? 1 : ((v) < 0x408f ? 2 : ((v) < 0x20408f ? 3 : ((v) < 0x1020408f ? 4 : 5)))) + +#define GRN_B_DEC(v,p) do { \ + uint8_t *_p = (uint8_t *)p; \ + uint32_t _v = *_p++; \ + switch (_v >> 4) { \ + case 0x08 : \ + if (_v == 0x8f) { \ + grn_memcpy(&_v, _p, sizeof(uint32_t));\ + _p += sizeof(uint32_t); \ + } \ + break; \ + case 0x09 : \ + _v = (_v - 0x90) * 0x100 + *_p++; \ + _v = _v * 0x100 + *_p++; \ + _v = _v * 0x100 + *_p++ + 0x20408f; \ + break; \ + case 0x0a : \ + case 0x0b : \ + _v = (_v - 0xa0) * 0x100 + *_p++; \ + _v = _v * 0x100 + *_p++ + 0x408f; \ + break; \ + case 0x0c : \ + case 0x0d : \ + case 0x0e : \ + case 0x0f : \ + _v = (_v - 0xc0) * 0x100 + *_p++ + 0x8f; \ + break; \ + } \ + v = _v; \ + p = _p; \ +} while (0) + +#define GRN_B_SKIP(p) do { \ + uint8_t *_p = (uint8_t *)p; \ + uint32_t _v = *_p++; \ + switch (_v >> 4) { \ + case 0x08 : \ + if (_v == 0x8f) { \ + _p += sizeof(uint32_t); \ + } \ + break; \ + case 0x09 : \ + _p += 3; \ + break; \ + case 0x0a : \ + case 0x0b : \ + _p += 2; \ + break; \ + case 0x0c : \ + case 0x0d : \ + case 0x0e : \ + case 0x0f : \ + _p += 1; \ + break; \ + } \ + p = _p; \ +} while (0) + +#define GRN_B_COPY(p2,p1) do { \ + uint32_t size = 0, _v = *p1++; \ + *p2++ = _v; \ + switch (_v >> 4) { \ + case 0x08 : \ + size = (_v == 0x8f) ? 4 : 0; \ + break; \ + case 0x09 : \ + size = 3; \ + break; \ + case 0x0a : \ + case 0x0b : \ + size = 2; \ + break; \ + case 0x0c : \ + case 0x0d : \ + case 0x0e : \ + case 0x0f : \ + size = 1; \ + break; \ + } \ + while (size--) { *p2++ = *p1++; } \ +} while (0) + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_load.h b/storage/mroonga/vendor/groonga/lib/grn_load.h new file mode 100644 index 00000000..a3b909b2 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_load.h @@ -0,0 +1,47 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_raw_string.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_JSON_LOAD_OPEN_BRACKET 0x40000000 +#define GRN_JSON_LOAD_OPEN_BRACE 0x40000001 + +typedef struct grn_load_input_ { + grn_content_type type; + grn_raw_string table; + grn_raw_string columns; + grn_raw_string values; + grn_raw_string if_exists; + grn_raw_string each; + grn_bool output_ids; + grn_bool output_errors; + uint32_t emit_level; +} grn_load_input; + +void grn_load_internal(grn_ctx *ctx, grn_load_input *input); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_logger.h b/storage/mroonga/vendor/groonga/lib/grn_logger.h new file mode 100644 index 00000000..58d745cf --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_logger.h @@ -0,0 +1,35 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_logger_init(void); +void grn_logger_fin(grn_ctx *ctx); + +void grn_query_logger_init(void); +void grn_query_logger_fin(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_mrb.h b/storage/mroonga/vendor/groonga/lib/grn_mrb.h new file mode 100644 index 00000000..d1e20a66 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_mrb.h @@ -0,0 +1,42 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" + +#ifdef GRN_WITH_MRUBY +# include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_init_from_env(void); + +#ifdef GRN_WITH_MRUBY +GRN_API mrb_value grn_mrb_load(grn_ctx *ctx, const char *path); +GRN_API const char *grn_mrb_get_system_ruby_scripts_dir(grn_ctx *ctx); +grn_bool grn_mrb_is_order_by_estimated_size_enabled(void); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_msgpack.h b/storage/mroonga/vendor/groonga/lib/grn_msgpack.h new file mode 100644 index 00000000..3452d588 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_msgpack.h @@ -0,0 +1,46 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#ifdef GRN_WITH_MESSAGE_PACK +# include + +# if MSGPACK_VERSION_MAJOR < 1 +typedef unsigned int msgpack_size_t; + +# define msgpack_pack_str(packer, size) msgpack_pack_raw(packer, size) +# define msgpack_pack_str_body(packer, value, size) \ + msgpack_pack_raw_body(packer, value, size) + +# define MSGPACK_OBJECT_STR MSGPACK_OBJECT_RAW +# define MSGPACK_OBJECT_FLOAT MSGPACK_OBJECT_DOUBLE + +# define MSGPACK_OBJECT_STR_PTR(object) (object)->via.raw.ptr +# define MSGPACK_OBJECT_STR_SIZE(object) (object)->via.raw.size + +# define MSGPACK_OBJECT_FLOAT_VALUE(object) (object)->via.dec +# else /* MSGPACK_VERSION_MAJOR < 1 */ +typedef size_t msgpack_size_t; + +# define MSGPACK_OBJECT_STR_PTR(object) (object)->via.str.ptr +# define MSGPACK_OBJECT_STR_SIZE(object) (object)->via.str.size + +# define MSGPACK_OBJECT_FLOAT_VALUE(object) (object)->via.f64 +# endif /* MSGPACK_VERSION_MAJOR < 1 */ +#endif /* GRN_WITH_MESSAGE_PACK */ diff --git a/storage/mroonga/vendor/groonga/lib/grn_nfkc.h b/storage/mroonga/vendor/groonga/lib/grn_nfkc.h new file mode 100644 index 00000000..33119d55 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_nfkc.h @@ -0,0 +1,39 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +grn_char_type grn_nfkc50_char_type(const unsigned char *utf8); + +const char *grn_nfkc_decompose(const unsigned char *utf8); +const char *grn_nfkc50_decompose(const unsigned char *utf8); + +const char *grn_nfkc_compose(const unsigned char *prefix_utf8, + const unsigned char *suffix_utf8); +const char *grn_nfkc50_compose(const unsigned char *prefix_utf8, + const unsigned char *suffix_utf8); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_normalizer.h b/storage/mroonga/vendor/groonga/lib/grn_normalizer.h new file mode 100644 index 00000000..2ff50047 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_normalizer.h @@ -0,0 +1,42 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" +#include "grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_NORMALIZER_AUTO_NAME "NormalizerAuto" + +grn_rc grn_normalizer_init(void); +grn_rc grn_normalizer_fin(void); + +grn_rc grn_normalizer_normalize(grn_ctx *ctx, + grn_obj *normalizer, + grn_obj *string); + +grn_rc grn_db_init_builtin_normalizers(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_obj.h b/storage/mroonga/vendor/groonga/lib/grn_obj.h new file mode 100644 index 00000000..48eb503b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_obj.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_io.h" +#include "grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +grn_io *grn_obj_get_io(grn_ctx *ctx, grn_obj *obj); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_output.h b/storage/mroonga/vendor/groonga/lib/grn_output.h new file mode 100644 index 00000000..14364107 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_output.h @@ -0,0 +1,127 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" +#include "grn_store.h" +#include "grn_ctx_impl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +GRN_API void grn_output_array_open(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + const char *name, int nelements); +GRN_API void grn_output_array_close(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type); +GRN_API void grn_output_map_open(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + const char *name, int nelements); +GRN_API void grn_output_map_close(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type); +GRN_API void grn_output_null(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type); +void grn_output_int32(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + int32_t value); +GRN_API void grn_output_int64(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + int64_t value); +GRN_API void grn_output_uint64(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + uint64_t value); +void grn_output_float(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + double value); +GRN_API void grn_output_cstr(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + const char *value); +GRN_API void grn_output_str(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + const char *value, size_t value_len); +GRN_API void grn_output_bool(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_bool value); + +GRN_API void grn_output_result_set_open(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *result_set, + grn_obj_format *format, + uint32_t n_additional_elements); +GRN_API void grn_output_result_set_close(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *result_set, + grn_obj_format *format); +GRN_API void grn_output_result_set(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *result_set, + grn_obj_format *format); +GRN_API void grn_output_table_columns(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, + grn_obj_format *format); +GRN_API void grn_output_table_records(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, + grn_obj_format *format); + +grn_rc grn_output_format_set_columns(grn_ctx *ctx, grn_obj_format *format, + grn_obj *table, + const char *columns, int columns_len); + +#define GRN_OUTPUT_ARRAY_OPEN(name,nelements) \ + (grn_ctx_output_array_open(ctx, name, nelements)) +#define GRN_OUTPUT_ARRAY_CLOSE() \ + (grn_ctx_output_array_close(ctx)) +#define GRN_OUTPUT_MAP_OPEN(name,nelements) \ + (grn_ctx_output_map_open(ctx, name, nelements)) +#define GRN_OUTPUT_MAP_CLOSE() \ + (grn_ctx_output_map_close(ctx)) +#define GRN_OUTPUT_NULL() \ + (grn_ctx_output_null(ctx)) +#define GRN_OUTPUT_INT32(value) \ + (grn_ctx_output_int32(ctx, value)) +#define GRN_OUTPUT_INT64(value) \ + (grn_ctx_output_int64(ctx, value)) +#define GRN_OUTPUT_UINT64(value) \ + (grn_ctx_output_uint64(ctx, value)) +#define GRN_OUTPUT_FLOAT(value) \ + (grn_ctx_output_float(ctx, value)) +#define GRN_OUTPUT_CSTR(value)\ + (grn_ctx_output_cstr(ctx, value)) +#define GRN_OUTPUT_STR(value,value_len)\ + (grn_ctx_output_str(ctx, value, value_len)) +#define GRN_OUTPUT_BOOL(value)\ + (grn_ctx_output_bool(ctx, value)) +#define GRN_OUTPUT_OBJ(obj,format)\ + (grn_ctx_output_obj(ctx, obj, format)) +#define GRN_OUTPUT_RESULT_SET_OPEN(result_set,format,n_additional_elements)\ + (grn_ctx_output_result_set_open(ctx, result_set, format, n_additional_elements)) +#define GRN_OUTPUT_RESULT_SET_CLOSE(result_set,format)\ + (grn_ctx_output_result_set_close(ctx, result_set, format)) +#define GRN_OUTPUT_RESULT_SET(result_set,format,n_additional_elements)\ + (grn_ctx_output_result_set(ctx, result_set, format, n_additional_elements)) +#define GRN_OUTPUT_TABLE_COLUMNS(table,format)\ + (grn_ctx_output_table_columns(ctx, table, format)) +#define GRN_OUTPUT_TABLE_RECORDS(table,format)\ + (grn_ctx_output_table_records(ctx, table, format)) + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_pat.h b/storage/mroonga/vendor/groonga/lib/grn_pat.h new file mode 100644 index 00000000..1a7e3cfb --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_pat.h @@ -0,0 +1,129 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_db.h" +#include "grn_hash.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_PAT_MAX_KEY_SIZE GRN_TABLE_MAX_KEY_SIZE +#define GRN_PAT_MAX_TOTAL_KEY_SIZE (UINT32_MAX - 1) + +struct _grn_pat { + grn_db_obj obj; + grn_io *io; + struct grn_pat_header *header; + grn_encoding encoding; + uint32_t key_size; + uint32_t value_size; + grn_obj *tokenizer; + grn_obj *normalizer; + grn_obj token_filters; + grn_id *cache; + uint32_t cache_size; + grn_bool is_dirty; + grn_critical_section lock; +}; + +#define GRN_PAT_NDELINFOS 0x100 + +typedef struct { + grn_id d; /* The ID of a deleting node. */ + grn_id ld; /* The ID of the parent node of a deleting node. */ + /* delinfo->ld is set if required. */ + uint32_t stat; /* DL_EMPTY, DL_PHASE1, or DL_PHASE2. */ + uint32_t shared; /* This flag is used if GRN_OBJ_KEY_WITH_SIS is set. */ +} grn_pat_delinfo; + +struct grn_pat_header { + uint32_t flags; + grn_encoding encoding; + uint32_t key_size; + uint32_t value_size; + grn_id tokenizer; + uint32_t n_entries; + uint32_t curr_rec; + int32_t curr_key; + int32_t curr_del; + int32_t curr_del2; + int32_t curr_del3; + uint32_t n_garbages; + grn_id normalizer; + uint32_t truncated; + uint32_t n_dirty_opens; + uint32_t reserved[1002]; + grn_pat_delinfo delinfos[GRN_PAT_NDELINFOS]; + grn_id garbages[GRN_PAT_MAX_KEY_SIZE + 1]; +}; + +struct _grn_pat_cursor_entry { + grn_id id; + uint16_t check; +}; + +typedef struct _grn_pat_cursor_entry grn_pat_cursor_entry; + +struct _grn_pat_cursor { + grn_db_obj obj; + grn_id curr_rec; /* ID of the latest record */ + grn_pat *pat; + grn_ctx *ctx; + unsigned int size; /* stack size (the maximum number of entries) */ + unsigned int sp; /* stack pointer (the number of entries) */ + grn_id tail; /* sentinel (the end of the traversal) */ + unsigned int rest; /* limit rest (the number of remaining records) */ + grn_pat_cursor_entry *ss; /* stack buffer (pointer to entries) */ + uint8_t curr_key[GRN_TABLE_MAX_KEY_SIZE]; +}; + +GRN_API grn_id grn_pat_curr_id(grn_ctx *ctx, grn_pat *pat); + +/* private */ +GRN_API grn_rc grn_pat_truncate(grn_ctx *ctx, grn_pat *pat); +const char *_grn_pat_key(grn_ctx *ctx, grn_pat *pat, grn_id id, uint32_t *key_size); +grn_id grn_pat_next(grn_ctx *ctx, grn_pat *pat, grn_id id); +const char *grn_pat_get_value_(grn_ctx *ctx, grn_pat *pat, grn_id id, uint32_t *size); +GRN_API grn_id grn_pat_at(grn_ctx *ctx, grn_pat *pat, grn_id id); +void grn_pat_check(grn_ctx *ctx, grn_pat *pat); +void grn_pat_inspect_nodes(grn_ctx *ctx, grn_pat *pat, grn_obj *buf); +void grn_pat_cursor_inspect(grn_ctx *ctx, grn_pat_cursor *c, grn_obj *buf); + +grn_rc grn_pat_cache_enable(grn_ctx *ctx, grn_pat *pat, uint32_t cache_size); +void grn_pat_cache_disable(grn_ctx *ctx, grn_pat *pat); + +GRN_API grn_rc grn_pat_fuzzy_search(grn_ctx *ctx, grn_pat *pat, + const void *key, unsigned int key_size, + grn_fuzzy_search_optarg *args, grn_hash *h); + +uint32_t grn_pat_total_key_size(grn_ctx *ctx, grn_pat *pat); + +grn_bool grn_pat_is_key_encoded(grn_ctx *ctx, grn_pat *pat); + +grn_rc grn_pat_dirty(grn_ctx *ctx, grn_pat *pat); +grn_bool grn_pat_is_dirty(grn_ctx *ctx, grn_pat *pat); +grn_rc grn_pat_clean(grn_ctx *ctx, grn_pat *pat); +grn_rc grn_pat_clear_dirty(grn_ctx *ctx, grn_pat *pat); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_plugin.h b/storage/mroonga/vendor/groonga/lib/grn_plugin.h new file mode 100644 index 00000000..0bed139c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_plugin.h @@ -0,0 +1,62 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" +#include "grn_store.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +typedef HINSTANCE grn_dl; +typedef FARPROC grn_dl_symbol; + +#else +typedef void * grn_dl; +typedef void * grn_dl_symbol; +#endif + +typedef struct _grn_plugin grn_plugin; + +struct _grn_plugin { + char path[PATH_MAX]; + grn_dl dl; + grn_plugin_func init_func; + grn_plugin_func register_func; + grn_plugin_func unregister_func; + grn_plugin_func fin_func; + int refcount; +}; + +void grn_plugin_init_from_env(void); +grn_rc grn_plugins_init(void); +grn_rc grn_plugins_fin(void); +grn_id grn_plugin_open(grn_ctx *ctx, const char *filename); +grn_rc grn_plugin_close(grn_ctx *ctx, grn_id id); +grn_id grn_plugin_reference(grn_ctx *ctx, const char *filename); +const char *grn_plugin_path(grn_ctx *ctx, grn_id id); +char *grn_plugin_find_path(grn_ctx *ctx, const char *name); +void grn_plugin_ensure_registered(grn_ctx *ctx, grn_obj *proc); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_proc.h b/storage/mroonga/vendor/groonga/lib/grn_proc.h new file mode 100644 index 00000000..267ef01b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_proc.h @@ -0,0 +1,152 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_SELECT_DEFAULT_LIMIT 10 +#define GRN_SELECT_DEFAULT_OUTPUT_COLUMNS "_id, _key, *" + +#define GRN_SELECT_INTERNAL_VAR_CONDITION "$condition" +#define GRN_SELECT_INTERNAL_VAR_CONDITION_LEN \ + (sizeof(GRN_SELECT_INTERNAL_VAR_CONDITION) - 1) + +void grn_proc_init_from_env(void); + +GRN_VAR const char *grn_document_root; +void grn_db_init_builtin_commands(grn_ctx *ctx); + +void grn_proc_init_clearlock(grn_ctx *ctx); +void grn_proc_init_column_copy(grn_ctx *ctx); +void grn_proc_init_column_create(grn_ctx *ctx); +void grn_proc_init_column_list(grn_ctx *ctx); +void grn_proc_init_column_remove(grn_ctx *ctx); +void grn_proc_init_column_rename(grn_ctx *ctx); +void grn_proc_init_config_get(grn_ctx *ctx); +void grn_proc_init_config_set(grn_ctx *ctx); +void grn_proc_init_config_delete(grn_ctx *ctx); +void grn_proc_init_define_selector(grn_ctx *ctx); +void grn_proc_init_dump(grn_ctx *ctx); +void grn_proc_init_edit_distance(grn_ctx *ctx); +void grn_proc_init_fuzzy_search(grn_ctx *ctx); +void grn_proc_init_highlight(grn_ctx *ctx); +void grn_proc_init_highlight_full(grn_ctx *ctx); +void grn_proc_init_highlight_html(grn_ctx *ctx); +void grn_proc_init_in_records(grn_ctx *ctx); +void grn_proc_init_lock_acquire(grn_ctx *ctx); +void grn_proc_init_lock_clear(grn_ctx *ctx); +void grn_proc_init_lock_release(grn_ctx *ctx); +void grn_proc_init_object_exist(grn_ctx *ctx); +void grn_proc_init_object_inspect(grn_ctx *ctx); +void grn_proc_init_object_list(grn_ctx *ctx); +void grn_proc_init_object_remove(grn_ctx *ctx); +void grn_proc_init_query_expand(grn_ctx *ctx); +void grn_proc_init_query_log_flags_get(grn_ctx *ctx); +void grn_proc_init_query_log_flags_set(grn_ctx *ctx); +void grn_proc_init_query_log_flags_add(grn_ctx *ctx); +void grn_proc_init_query_log_flags_remove(grn_ctx *ctx); +void grn_proc_init_schema(grn_ctx *ctx); +void grn_proc_init_select(grn_ctx *ctx); +void grn_proc_init_snippet(grn_ctx *ctx); +void grn_proc_init_snippet_html(grn_ctx *ctx); +void grn_proc_init_table_copy(grn_ctx *ctx); +void grn_proc_init_table_create(grn_ctx *ctx); +void grn_proc_init_table_list(grn_ctx *ctx); +void grn_proc_init_table_remove(grn_ctx *ctx); +void grn_proc_init_table_rename(grn_ctx *ctx); +void grn_proc_init_table_tokenize(grn_ctx *ctx); +void grn_proc_init_tokenize(grn_ctx *ctx); + +grn_bool grn_proc_option_value_bool(grn_ctx *ctx, + grn_obj *option, + grn_bool default_value); +int32_t grn_proc_option_value_int32(grn_ctx *ctx, + grn_obj *option, + int32_t default_value); +const char *grn_proc_option_value_string(grn_ctx *ctx, + grn_obj *option, + size_t *size); +grn_content_type grn_proc_option_value_content_type(grn_ctx *ctx, + grn_obj *option, + grn_content_type default_value); +grn_operator grn_proc_option_value_mode(grn_ctx *ctx, + grn_obj *option, + grn_operator default_mode, + const char *context); + + +void grn_proc_output_object_name(grn_ctx *ctx, grn_obj *obj); +void grn_proc_output_object_id_name(grn_ctx *ctx, grn_id id); + +grn_bool grn_proc_table_set_token_filters(grn_ctx *ctx, + grn_obj *table, + grn_obj *token_filter_names); + +grn_column_flags grn_proc_column_parse_flags(grn_ctx *ctx, + const char *error_message_tag, + const char *text, + const char *end); + +grn_bool grn_proc_select_output_columns_open(grn_ctx *ctx, + grn_obj_format *format, + grn_obj *result_set, + int n_hits, + int offset, + int limit, + const char *columns, + int columns_len, + grn_obj *condition, + uint32_t n_additional_elements); +grn_bool grn_proc_select_output_columns_close(grn_ctx *ctx, + grn_obj_format *format, + grn_obj *result_set); +grn_bool grn_proc_select_output_columns(grn_ctx *ctx, + grn_obj *res, + int n_hits, + int offset, + int limit, + const char *columns, + int columns_len, + grn_obj *condition); + +grn_rc grn_proc_syntax_expand_query(grn_ctx *ctx, + const char *query, + unsigned int query_len, + grn_expr_flags flags, + const char *query_expander_name, + unsigned int query_expander_name_len, + const char *term_column_name, + unsigned int term_column_name_len, + const char *expanded_term_column_name, + unsigned int expanded_term_column_name_len, + grn_obj *expanded_query, + const char *error_message_tag); + +grn_expr_flags grn_proc_expr_query_flags_parse(grn_ctx *ctx, + const char *query_flags, + size_t query_flags_size, + const char *error_message_tag); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_raw_string.h b/storage/mroonga/vendor/groonga/lib/grn_raw_string.h new file mode 100644 index 00000000..2b5fdc9c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_raw_string.h @@ -0,0 +1,62 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_RAW_STRING_INIT(string) do { \ + string.value = NULL; \ + string.length = 0; \ + } while (GRN_FALSE) + +#define GRN_RAW_STRING_SET(string, bulk) \ + if (bulk && GRN_TEXT_LEN(bulk) > 0) { \ + string.value = GRN_TEXT_VALUE(bulk); \ + string.length = GRN_TEXT_LEN(bulk); \ + } else { \ + string.value = NULL; \ + string.length = 0; \ + } + +#define GRN_RAW_STRING_FILL(string, bulk) \ + if (bulk && GRN_TEXT_LEN(bulk) > 0) { \ + string.value = GRN_TEXT_VALUE(bulk); \ + string.length = GRN_TEXT_LEN(bulk); \ + } + +#define GRN_RAW_STRING_EQUAL_CSTRING(string, cstring) \ + (cstring ? \ + (string.length == strlen(cstring) && \ + memcmp(string.value, cstring, string.length) == 0) : \ + (string.length == 0)) + +typedef struct { + const char *value; + size_t length; +} grn_raw_string; + +void grn_raw_string_lstrip(grn_ctx *ctx, grn_raw_string *string); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_report.h b/storage/mroonga/vendor/groonga/lib/grn_report.h new file mode 100644 index 00000000..bb76caf7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_report.h @@ -0,0 +1,47 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern const grn_log_level GRN_REPORT_INDEX_LOG_LEVEL; + +void grn_report_index(grn_ctx *ctx, + const char *action, + const char *tag, + grn_obj *index); + +void grn_report_index_not_used(grn_ctx *ctx, + const char *action, + const char *tag, + grn_obj *index, + const char *reason); + +void grn_report_table(grn_ctx *ctx, + const char *action, + const char *tag, + grn_obj *table); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_request_canceler.h b/storage/mroonga/vendor/groonga/lib/grn_request_canceler.h new file mode 100644 index 00000000..ddb4031a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_request_canceler.h @@ -0,0 +1,28 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +grn_bool grn_request_canceler_init(void); +void grn_request_canceler_fin(void); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_request_timer.h b/storage/mroonga/vendor/groonga/lib/grn_request_timer.h new file mode 100644 index 00000000..4a45751c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_request_timer.h @@ -0,0 +1,28 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +grn_bool grn_request_timer_init(void); +void grn_request_timer_fin(void); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_rset.h b/storage/mroonga/vendor/groonga/lib/grn_rset.h new file mode 100644 index 00000000..5ca6e8d5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_rset.h @@ -0,0 +1,114 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + double score; + int n_subrecs; + int subrecs[1]; +} grn_rset_recinfo; + +typedef struct { + grn_id rid; + uint32_t sid; + uint32_t pos; +} grn_rset_posinfo; + +#define GRN_RSET_UTIL_BIT (0x80000000) + +#define GRN_RSET_N_SUBRECS_SIZE (sizeof(int)) +#define GRN_RSET_MAX_SIZE (sizeof(int64_t)) +#define GRN_RSET_MIN_SIZE (sizeof(int64_t)) +#define GRN_RSET_SUM_SIZE (sizeof(int64_t)) +#define GRN_RSET_AVG_SIZE (sizeof(double)) + +#define GRN_RSET_SCORE_SIZE (sizeof(double)) + +#define GRN_RSET_N_SUBRECS(ri) ((ri)->n_subrecs & ~GRN_RSET_UTIL_BIT) + +#define GRN_RSET_SUBREC_SIZE(subrec_size) \ + (GRN_RSET_SCORE_SIZE + subrec_size) +#define GRN_RSET_SUBRECS_CMP(a,b,dir) (((a) - (b))*(dir)) +#define GRN_RSET_SUBRECS_NTH(subrecs,size,n) \ + ((double *)((byte *)subrecs + n * GRN_RSET_SUBREC_SIZE(size))) +#define GRN_RSET_SUBRECS_COPY(subrecs,size,n,src) \ + (grn_memcpy(GRN_RSET_SUBRECS_NTH(subrecs, size, n), src, GRN_RSET_SUBREC_SIZE(size))) +#define GRN_RSET_SUBRECS_SIZE(subrec_size,n) \ + (GRN_RSET_SUBREC_SIZE(subrec_size) * n) + +uint32_t grn_rset_recinfo_calc_values_size(grn_ctx *ctx, + grn_table_group_flags flags); +void grn_rset_recinfo_update_calc_values(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + grn_obj *value); + +int64_t *grn_rset_recinfo_get_max_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +int64_t grn_rset_recinfo_get_max(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +void grn_rset_recinfo_set_max(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t max); + +int64_t *grn_rset_recinfo_get_min_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +int64_t grn_rset_recinfo_get_min(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +void grn_rset_recinfo_set_min(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t min); + +int64_t *grn_rset_recinfo_get_sum_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +int64_t grn_rset_recinfo_get_sum(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +void grn_rset_recinfo_set_sum(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t sum); + +double *grn_rset_recinfo_get_avg_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +double grn_rset_recinfo_get_avg(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table); +void grn_rset_recinfo_set_avg(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + double avg); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_scanner.h b/storage/mroonga/vendor/groonga/lib/grn_scanner.h new file mode 100644 index 00000000..8ea8597b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_scanner.h @@ -0,0 +1,40 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_expr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _grn_scaner { + grn_obj *expr; + grn_obj *source_expr; + scan_info **sis; + unsigned int n_sis; +} grn_scanner; + +grn_scanner *grn_scanner_open(grn_ctx *ctx, grn_obj *expr, + grn_operator op, grn_bool record_exist); +void grn_scanner_close(grn_ctx *ctx, grn_scanner *scanner); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_scorer.h b/storage/mroonga/vendor/groonga/lib/grn_scorer.h new file mode 100644 index 00000000..04e8bfd5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_scorer.h @@ -0,0 +1,49 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_ctx.h" +#include "grn_db.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct _grn_scorer_matched_record { + grn_obj *table; + grn_obj *lexicon; + grn_id id; + grn_obj terms; + grn_obj term_weights; + uint32_t total_term_weights; + uint64_t n_documents; + uint32_t n_occurrences; + uint64_t n_candidates; + uint32_t n_tokens; + int weight; + grn_obj *args_expr; + unsigned int args_expr_offset; +}; + + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_scorers.h b/storage/mroonga/vendor/groonga/lib/grn_scorers.h new file mode 100644 index 00000000..1f136a9c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_scorers.h @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +grn_rc grn_db_init_builtin_scorers(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_snip.h b/storage/mroonga/vendor/groonga/lib/grn_snip.h new file mode 100644 index 00000000..3989a17d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_snip.h @@ -0,0 +1,125 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_str.h" +#include "grn_db.h" + +#define ASIZE 256U +#define MAX_SNIP_TAG_COUNT 512U +#define MAX_SNIP_COND_COUNT 32U +#define MAX_SNIP_RESULT_COUNT 16U + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define SNIPCOND_NONSTOP 0 +#define SNIPCOND_STOP 1 +#define SNIPCOND_ACROSS 2 + +#define GRN_QUERY_SCAN_ALLOCCONDS 0x0002 + +typedef struct _snip_cond +{ + /* initial parameters */ + const char *opentag; + const char *closetag; + size_t opentag_len; + size_t closetag_len; + grn_obj *keyword; + + /* Tuned BM pre */ + size_t bmBc[ASIZE]; + size_t shift; + + /* Tuned BM temporal result */ + size_t found; + size_t last_found; + size_t last_offset; + size_t start_offset; + size_t end_offset; + size_t found_alpha_head; + + /* search result */ + int count; + + /* stop flag */ + int_least8_t stopflag; +} snip_cond; + +typedef struct +{ + size_t start_offset; + size_t end_offset; + snip_cond *cond; +} _snip_tag_result; + +typedef struct +{ + size_t start_offset; + size_t end_offset; + unsigned int first_tag_result_idx; + unsigned int last_tag_result_idx; + unsigned int tag_count; +} _snip_result; + +typedef struct _grn_snip +{ + grn_db_obj obj; + grn_encoding encoding; + int flags; + size_t width; + unsigned int max_results; + const char *defaultopentag; + const char *defaultclosetag; + size_t defaultopentag_len; + size_t defaultclosetag_len; + + grn_snip_mapping *mapping; + + snip_cond cond[MAX_SNIP_COND_COUNT]; + unsigned int cond_len; + + unsigned int tag_count; + unsigned int snip_count; + + const char *string; + grn_obj *nstr; + + _snip_result snip_result[MAX_SNIP_RESULT_COUNT]; + _snip_tag_result tag_result[MAX_SNIP_TAG_COUNT]; + + size_t max_tagged_len; + + grn_obj *normalizer; +} grn_snip; + +grn_rc grn_snip_close(grn_ctx *ctx, grn_snip *snip); +grn_rc grn_snip_cond_init(grn_ctx *ctx, snip_cond *sc, const char *keyword, unsigned int keyword_len, + grn_encoding enc, grn_obj *normalizer, int flags); +void grn_snip_cond_reinit(snip_cond *cond); +grn_rc grn_snip_cond_close(grn_ctx *ctx, snip_cond *cond); +void grn_bm_tunedbm(grn_ctx *ctx, snip_cond *cond, grn_obj *string, int flags); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_store.h b/storage/mroonga/vendor/groonga/lib/grn_store.h new file mode 100644 index 00000000..8de6fd66 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_store.h @@ -0,0 +1,216 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" +#include "grn_hash.h" +#include "grn_io.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/**** fixed sized elements ****/ + +typedef struct _grn_ra grn_ra; + +struct _grn_ra { + grn_db_obj obj; + grn_io *io; + int element_width; + int element_mask; + struct grn_ra_header *header; +}; + +struct grn_ra_header { + uint32_t element_size; + uint32_t nrecords; /* nrecords is not maintained by default */ + uint32_t reserved[10]; +}; + +grn_ra *grn_ra_create(grn_ctx *ctx, const char *path, unsigned int element_size); +grn_ra *grn_ra_open(grn_ctx *ctx, const char *path); +grn_rc grn_ra_info(grn_ctx *ctx, grn_ra *ra, unsigned int *element_size); +grn_rc grn_ra_close(grn_ctx *ctx, grn_ra *ra); +grn_rc grn_ra_remove(grn_ctx *ctx, const char *path); +void *grn_ra_ref(grn_ctx *ctx, grn_ra *ra, grn_id id); +grn_rc grn_ra_unref(grn_ctx *ctx, grn_ra *ra, grn_id id); + +typedef struct _grn_ra_cache grn_ra_cache; + +struct _grn_ra_cache { + void *p; + int32_t seg; +}; + +#define GRN_RA_CACHE_INIT(ra,c) do {\ + (c)->p = NULL; (c)->seg = -1;\ +} while (0) + +#define GRN_RA_CACHE_FIN(ra,c) do {\ + if ((c)->seg != -1) { GRN_IO_SEG_UNREF((ra)->io, (c)->seg); }\ +} while (0); + +void *grn_ra_ref_cache(grn_ctx *ctx, grn_ra *ra, grn_id id, grn_ra_cache *cache); + +/**** variable sized elements ****/ + +typedef struct _grn_ja grn_ja; + +struct _grn_ja { + grn_db_obj obj; + grn_io *io; + struct grn_ja_header *header; +}; + +GRN_API grn_ja *grn_ja_create(grn_ctx *ctx, const char *path, + uint32_t max_element_size, uint32_t flags); +grn_ja *grn_ja_open(grn_ctx *ctx, const char *path); +grn_rc grn_ja_info(grn_ctx *ctx, grn_ja *ja, unsigned int *max_element_size); +grn_column_flags grn_ja_get_flags(grn_ctx *ctx, grn_ja *ja); +GRN_API grn_rc grn_ja_close(grn_ctx *ctx, grn_ja *ja); +grn_rc grn_ja_remove(grn_ctx *ctx, const char *path); +grn_rc grn_ja_put(grn_ctx *ctx, grn_ja *ja, grn_id id, + void *value, uint32_t value_len, int flags, uint64_t *cas); +int grn_ja_at(grn_ctx *ctx, grn_ja *ja, grn_id id, void *valbuf, int buf_size); + +GRN_API void *grn_ja_ref(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, + uint32_t *value_len); +grn_obj *grn_ja_get_value(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *value); + +GRN_API grn_rc grn_ja_unref(grn_ctx *ctx, grn_io_win *iw); +int grn_ja_defrag(grn_ctx *ctx, grn_ja *ja, int threshold); + +GRN_API grn_rc grn_ja_putv(grn_ctx *ctx, grn_ja *ja, grn_id id, + grn_obj *vector, int flags); +GRN_API uint32_t grn_ja_size(grn_ctx *ctx, grn_ja *ja, grn_id id); + +void grn_ja_check(grn_ctx *ctx, grn_ja *ja); + +#define GRN_JA_READER_INITIAL_REF_SEG_IDS_SIZE 16 + +/* + * grn_ja_reader is designed to improve the performance of sequential access. + */ +typedef struct { + grn_ja *ja; /* Target jagged array (without ref. count). */ + uint32_t einfo_seg_id; /* ID of the current header segment. */ + void *einfo_seg_addr; /* Address of the current header segment. */ + void *einfo; /* Header of the current value. */ + grn_bool ref_avail; /* grn_ja_reader_ref() is available or not. */ + uint32_t ref_seg_id; /* ID of the current referenced segment. */ + void *ref_seg_addr; /* Address of the current referenced segment. */ + uint32_t *ref_seg_ids; /* IDs of referenced segments. */ + uint32_t nref_seg_ids; /* Number of referenced segments. */ + uint32_t ref_seg_ids_size; /* Maximum number of referenced segments. */ + uint32_t body_seg_id; /* ID of the current body segment. */ + uint32_t body_seg_offset; /* Offset in the current body segment. */ + void *body_seg_addr; /* Address of the current body segment. */ + uint32_t value_size; /* Size of the current value. */ + uint32_t packed_size; /* Compressed size of the current value. */ + void *packed_buf; /* Buffer for decompression. */ + uint32_t packed_buf_size; /* Size of the buffer for decompression. */ + void *stream; /* Stream of a compression library. */ +} grn_ja_reader; + +/* + * grn_ja_reader_init() initializes a reader. + * An initialized reader must be finalized by grn_ja_reader_fin(). + */ +grn_rc grn_ja_reader_init(grn_ctx *ctx, grn_ja_reader *reader, grn_ja *ja); + +/* grn_ja_reader_fin() finalizes a reader. */ +grn_rc grn_ja_reader_fin(grn_ctx *ctx, grn_ja_reader *reader); + +/* + * grn_ja_reader_open() creates a reader. + * A created reader must be destroyed by grn_ja_reader_close(). + */ +grn_rc grn_ja_reader_open(grn_ctx *ctx, grn_ja *ja, grn_ja_reader **reader); + +/* grn_ja_reader_close() destroys a reader. */ +grn_rc grn_ja_reader_close(grn_ctx *ctx, grn_ja_reader *reader); + +/* + * grn_ja_reader_seek() prepares to access a value specified by `id`. + * On success, `reader->value_size` is set. + */ +grn_rc grn_ja_reader_seek(grn_ctx *ctx, grn_ja_reader *reader, grn_id id); + +/* + * grn_ja_reader_ref() gets the address to the current value. + * This function is available if `reader->ref_avail` is true. + */ +grn_rc grn_ja_reader_ref(grn_ctx *ctx, grn_ja_reader *reader, void **addr); + +/* grn_ja_reader_unref() frees refereces returned by grn_ja_reader_ref(). */ +grn_rc grn_ja_reader_unref(grn_ctx *ctx, grn_ja_reader *reader); + +/* grn_ja_reader_read() reads the current value to `buf`. */ +grn_rc grn_ja_reader_read(grn_ctx *ctx, grn_ja_reader *reader, void *buf); + +/* + * grn_ja_reader_pread() reads a part of the current value to `buf`. + * If `offset` and `size` are invalid, the behavior is undefined. + * FIXME: Compressed values are not supported yet. + */ +grn_rc grn_ja_reader_pread(grn_ctx *ctx, grn_ja_reader *reader, + size_t offset, size_t size, void *buf); + +/* +typedef struct _grn_vgram_vnode +{ + struct _grn_vgram_vnode *car; + struct _grn_vgram_vnode *cdr; + grn_id tid; + grn_id vid; + int freq; + int len; +} grn_vgram_vnode; + +typedef struct _grn_vgram grn_vgram; +struct _grn_vgram { + void *vgram; +}; + +struct _grn_vgram_buf { + size_t len; + grn_id *tvs; + grn_id *tvp; + grn_id *tve; + grn_vgram_vnode *vps; + grn_vgram_vnode *vpp; + grn_vgram_vnode *vpe; +}; + +grn_vgram *grn_vgram_create(const char *path); +grn_vgram *grn_vgram_open(const char *path); +grn_rc grn_vgram_close(grn_vgram *vgram); +grn_rc grn_vgram_update(grn_vgram *vgram, grn_id rid, grn_vgram_buf *b, grn_hash *terms); + +grn_vgram_buf *grn_vgram_buf_open(size_t len); +grn_rc grn_vgram_buf_add(grn_vgram_buf *b, grn_id tid); +grn_rc grn_vgram_buf_close(grn_vgram_buf *b); + +*/ + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_str.h b/storage/mroonga/vendor/groonga/lib/grn_str.h new file mode 100644 index 00000000..9efd28e3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_str.h @@ -0,0 +1,116 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + GETOPT_OP_NONE = 0, + GETOPT_OP_ON, + GETOPT_OP_OFF, + GETOPT_OP_UPDATE +} grn_str_getopt_op; + +typedef struct { + const char opt; /* ends opt == 0 && longopt == NULL */ + const char *longopt; + const char **arg; /* if NULL, no arg are required */ + int flag; + grn_str_getopt_op op; +} grn_str_getopt_opt; + +GRN_API size_t grn_str_len(grn_ctx *ctx, const char *str, grn_encoding encoding, const char **last); + +#define GRN_STR_BLANK 0x80 +#define GRN_STR_ISBLANK(c) (c & 0x80) +#define GRN_STR_CTYPE(c) (c & 0x7f) + +GRN_API int grn_isspace(const char *s, grn_encoding encoding); +int8_t grn_atoi8(const char *nptr, const char *end, const char **rest); +uint8_t grn_atoui8(const char *nptr, const char *end, const char **rest); +int16_t grn_atoi16(const char *nptr, const char *end, const char **rest); +uint16_t grn_atoui16(const char *nptr, const char *end, const char **rest); +GRN_API int grn_atoi(const char *nptr, const char *end, const char **rest); +GRN_API unsigned int grn_atoui(const char *nptr, const char *end, const char **rest); +unsigned int grn_htoui(const char *nptr, const char *end, const char **rest); +GRN_API int64_t grn_atoll(const char *nptr, const char *end, const char **rest); +GRN_API uint64_t grn_atoull(const char *nptr, const char *end, const char **rest); +grn_rc grn_itoa(int i, char *p, char *end, char **rest); +grn_rc grn_lltoa(int64_t i, char *p, char *end, char **rest); +grn_rc grn_ulltoa(uint64_t i, char *p, char *end, char **rest); +GRN_API grn_rc grn_aton(grn_ctx *ctx, const char *p, const char *end, const char **rest, grn_obj *res); + +GRN_API void grn_itoh(unsigned int i, char *p, unsigned int len); +int grn_str_tok(const char *str, size_t str_len, char delim, const char **tokbuf, int buf_size, const char **rest); +GRN_API int grn_str_getopt(int argc, char * const argv[], const grn_str_getopt_opt *opts, int *flags); + +extern int grn_str_margin_size; + +char *grn_itob(grn_id id, char *p); +grn_id grn_btoi(char *b); + +grn_rc grn_substring(grn_ctx *ctx, char **str, char **str_end, int start, int end, grn_encoding encoding); + +GRN_API int grn_charlen_(grn_ctx *ctx, const char *str, const char *end, grn_encoding encoding); +GRN_API grn_str *grn_str_open_(grn_ctx *ctx, const char *str, unsigned int str_len, int flags, grn_encoding encoding); + +#define GRN_BULK_SET_CURR(buf,p) do {\ + if (GRN_BULK_OUTP(buf)) {\ + (buf)->u.b.curr = (char *)(p);\ + } else {\ + (buf)->header.flags = (char *)(p) - GRN_BULK_HEAD(buf);\ + }\ +} while (0) + +grn_rc grn_text_ulltoa(grn_ctx *ctx, grn_obj *buf, unsigned long long int i); + +GRN_API const char *grn_text_cgidec(grn_ctx *ctx, grn_obj *buf, + const char *p, const char *e, + const char *delimiters); + +#define GRN_TOK_VOID (0x00) +#define GRN_TOK_SYMBOL (0x01) +#define GRN_TOK_STRING (0x02) +#define GRN_TOK_QUOTE (0x03) + +GRN_API const char *grn_text_unesc_tok(grn_ctx *ctx, grn_obj *buf, + const char *p, const char *e, + char *tok_type); + +GRN_API void grn_str_url_path_normalize(grn_ctx *ctx, + const char *path, size_t path_len, + char *buf, size_t buf_len); + +#define GRN_OBJ_FORMAT_XML_ELEMENT_MASK (0x01<<1) +#define GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET (0x00<<1) +#define GRN_OBJ_FORMAT_XML_ELEMENT_NAVIGATIONENTRY (0x01<<1) + +#include +GRN_API grn_rc grn_text_fgets(grn_ctx *ctx, grn_obj *buf, FILE *fp); + +grn_bool grn_bulk_is_zero(grn_ctx *ctx, grn_obj *obj); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_string.h b/storage/mroonga/vendor/groonga/lib/grn_string.h new file mode 100644 index 00000000..39e76c96 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_string.h @@ -0,0 +1,51 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" +#include "grn_db.h" +#include "grn_str.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + grn_obj_header header; + const char *original; + unsigned int original_length_in_bytes; + char *normalized; + unsigned int normalized_length_in_bytes; + unsigned int n_characters; + short *checks; + unsigned char *ctypes; + grn_encoding encoding; + int flags; +} grn_string; + +grn_obj *grn_string_open_(grn_ctx *ctx, const char *str, unsigned int str_len, + grn_obj *normalizer, int flags, grn_encoding encoding); +grn_rc grn_string_close(grn_ctx *ctx, grn_obj *string); +grn_rc grn_string_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *string); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_time.h b/storage/mroonga/vendor/groonga/lib/grn_time.h new file mode 100644 index 00000000..b34f6687 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_time.h @@ -0,0 +1,40 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GRN_TIMEVAL_STR_SIZE +#define GRN_TIMEVAL_STR_SIZE 0x100 +#endif /* GRN_TIMEVAL_STR_SIZE */ +#ifndef GRN_TIMEVAL_STR_FORMAT +#define GRN_TIMEVAL_STR_FORMAT "%04d-%02d-%02d %02d:%02d:%02d.%06d" +#endif /* GRN_TIMEVAL_STR_FORMAT */ + +GRN_API grn_rc grn_timeval2str(grn_ctx *ctx, grn_timeval *tv, char *buf, size_t buf_size); +struct tm *grn_timeval2tm(grn_ctx *ctx, grn_timeval *tv, struct tm *tm_buffer); +grn_rc grn_str2timeval(const char *str, uint32_t str_len, grn_timeval *tv); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_token_cursor.h b/storage/mroonga/vendor/groonga/lib/grn_token_cursor.h new file mode 100644 index 00000000..a89f4c68 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_token_cursor.h @@ -0,0 +1,81 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_ctx.h" +#include "grn_db.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_TOKENIZER_BEGIN_MARK_UTF8 "\xEF\xBF\xAF" +#define GRN_TOKENIZER_BEGIN_MARK_UTF8_LEN 3 +#define GRN_TOKENIZER_END_MARK_UTF8 "\xEF\xBF\xB0" +#define GRN_TOKENIZER_END_MARK_UTF8_LEN 3 + +typedef enum { + GRN_TOKEN_CURSOR_DOING = 0, + GRN_TOKEN_CURSOR_DONE, + GRN_TOKEN_CURSOR_DONE_SKIP, + GRN_TOKEN_CURSOR_NOT_FOUND +} grn_token_cursor_status; + +struct _grn_token { + grn_obj data; + grn_token_status status; +}; + +typedef struct { + grn_obj *table; + const unsigned char *orig; + const unsigned char *curr; + uint32_t orig_blen; + uint32_t curr_size; + int32_t pos; + grn_tokenize_mode mode; + grn_token_cursor_status status; + grn_bool force_prefix; + grn_obj_flags table_flags; + grn_encoding encoding; + grn_obj *tokenizer; + grn_proc_ctx pctx; + struct { + grn_obj *objects; + void **data; + } token_filter; + uint32_t variant; + grn_obj *nstr; +} grn_token_cursor; + +#define GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER (0x01L<<0) + +GRN_API grn_token_cursor *grn_token_cursor_open(grn_ctx *ctx, grn_obj *table, + const char *str, size_t str_len, + grn_tokenize_mode mode, + unsigned int flags); + +GRN_API grn_id grn_token_cursor_next(grn_ctx *ctx, grn_token_cursor *token_cursor); +GRN_API grn_rc grn_token_cursor_close(grn_ctx *ctx, grn_token_cursor *token_cursor); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h new file mode 100644 index 00000000..81ac2ab6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_tokenizers.h @@ -0,0 +1,38 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern grn_obj *grn_tokenizer_uvector; + +grn_rc grn_tokenizers_init(void); +grn_rc grn_tokenizers_fin(void); + +grn_rc grn_db_init_mecab_tokenizer(grn_ctx *ctx); +void grn_db_fin_mecab_tokenizer(grn_ctx *ctx); +grn_rc grn_db_init_builtin_tokenizers(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_ts.h b/storage/mroonga/vendor/groonga/lib/grn_ts.h new file mode 100644 index 00000000..83f4dca8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_ts.h @@ -0,0 +1,48 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * grn_ts_select() finds records passing through a filter and writes the values + * of output columns (the evaluation results of output expressions) into the + * output buffer (`ctx->impl->outbuf`). + * + * Note that the first `offset` records will be discarded and at most `limit` + * records will be output. + * + * On success, grn_ts_select() returns GRN_SUCCESS. + * On failure, grn_ts_select() returns an error code and set the details into + * `ctx`. + */ +grn_rc grn_ts_select(grn_ctx *ctx, grn_obj *table, + const char *filter_ptr, size_t filter_len, + const char *scorer_ptr, size_t scorer_len, + const char *sortby_ptr, size_t sortby_len, + const char *output_columns_ptr, size_t output_columns_len, + size_t offset, size_t limit); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_util.h b/storage/mroonga/vendor/groonga/lib/grn_util.h new file mode 100644 index 00000000..5b888fd5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_util.h @@ -0,0 +1,49 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" +#include "grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +GRN_API grn_rc grn_normalize_offset_and_limit(grn_ctx *ctx, int size, int *offset, int *limit); + +GRN_API char *grn_path_separator_to_system(char *dest, char *groonga_path); + +void grn_p_record(grn_ctx *ctx, grn_obj *table, grn_id id); + +/* + * grn_mkstemp generates a unique filename from path_template, creates a + * file with permissions 0600 and returns a open file desciptor for the file. + * The last 6 bytes of path_template must be "XXXXXX" and these are replaced + * with a string that makes the filename unique. + */ +int grn_mkstemp(char *path_template); +grn_bool grn_path_exist(const char *path); + +int grn_tokenize(const char *str, size_t str_len, + const char **tokbuf, int buf_size, + const char **rest); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_window_function.h b/storage/mroonga/vendor/groonga/lib/grn_window_function.h new file mode 100644 index 00000000..c5894241 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_window_function.h @@ -0,0 +1,40 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +struct _grn_window { + grn_obj *table; + grn_obj *grouped_table; + grn_obj ids; + size_t n_ids; + ssize_t current_index; + grn_window_direction direction; + grn_bool is_sorted; +}; + +grn_rc grn_window_init(grn_ctx *ctx, + grn_window *window, + grn_obj *table, + grn_bool is_sorted); +grn_rc grn_window_fin(grn_ctx *ctx, grn_window *window); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_window_functions.h b/storage/mroonga/vendor/groonga/lib/grn_window_functions.h new file mode 100644 index 00000000..c44e65a1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_window_functions.h @@ -0,0 +1,26 @@ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +grn_rc grn_db_init_builtin_window_functions(grn_ctx *ctx); + + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/grn_windows.h b/storage/mroonga/vendor/groonga/lib/grn_windows.h new file mode 100644 index 00000000..aee18aec --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/grn_windows.h @@ -0,0 +1,33 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +GRN_API UINT grn_windows_encoding_to_code_page(grn_encoding encoding); +#endif /* WIN32 */ + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/hash.c b/storage/mroonga/vendor/groonga/lib/hash.c new file mode 100644 index 00000000..3fb372ee --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/hash.c @@ -0,0 +1,3720 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn_hash.h" +#include "grn_output.h" +#include +#include + +#include "grn_store.h" +#include "grn_normalizer.h" + +/* grn_tiny_array */ + +/* Requirements: id != GRN_ID_NIL. */ +inline static int +grn_tiny_array_get_block_id(grn_id id) +{ + int most_significant_one_bit_offset; + GRN_BIT_SCAN_REV(id, most_significant_one_bit_offset); + return most_significant_one_bit_offset >> GRN_TINY_ARRAY_FACTOR; +} + +/* Requirements: id != GRN_ID_NIL. */ +inline static void * +grn_tiny_array_get(grn_tiny_array *array, grn_id id) { + const int block_id = grn_tiny_array_get_block_id(id); + uint8_t * const block = (uint8_t *)array->blocks[block_id]; + if (block) { + const size_t offset = GRN_TINY_ARRAY_GET_OFFSET(block_id); + return block + (id - offset) * array->element_size; + } + return NULL; +} + +/* Requirements: id != GRN_ID_NIL. */ +inline static void * +grn_tiny_array_put(grn_tiny_array *array, grn_id id) { + const int block_id = grn_tiny_array_get_block_id(id); + void ** const block = &array->blocks[block_id]; + const size_t offset = GRN_TINY_ARRAY_GET_OFFSET(block_id); + if (!*block) { + grn_ctx * const ctx = array->ctx; + if (array->flags & GRN_TINY_ARRAY_THREADSAFE) { + CRITICAL_SECTION_ENTER(array->lock); + } + if (!*block) { + const size_t block_size = + GRN_TINY_ARRAY_GET_BLOCK_SIZE(block_id) * array->element_size; + if (array->flags & GRN_TINY_ARRAY_USE_MALLOC) { + if (array->flags & GRN_TINY_ARRAY_CLEAR) { + *block = GRN_CALLOC(block_size); + } else { + *block = GRN_MALLOC(block_size); + } + } else { + *block = GRN_CTX_ALLOC(ctx, block_size); + } + } + if (array->flags & GRN_TINY_ARRAY_THREADSAFE) { + CRITICAL_SECTION_LEAVE(array->lock); + } + if (!*block) { + return NULL; + } + } + if (id > array->max) { + array->max = id; + } + return (uint8_t *)*block + (id - offset) * array->element_size; +} + +inline static void * +grn_tiny_array_at_inline(grn_tiny_array *array, grn_id id) +{ + return id ? grn_tiny_array_put(array, id) : NULL; +} + +void +grn_tiny_array_init(grn_ctx *ctx, grn_tiny_array *array, + uint16_t element_size, uint16_t flags) +{ + array->ctx = ctx; + array->max = 0; + array->element_size = element_size; + array->flags = flags; + memset(array->blocks, 0, sizeof(array->blocks)); + if (flags & GRN_TINY_ARRAY_THREADSAFE) { + CRITICAL_SECTION_INIT(array->lock); + } +} + +void +grn_tiny_array_fin(grn_tiny_array *array) +{ + int block_id; + grn_ctx * const ctx = array->ctx; + for (block_id = 0; block_id < GRN_TINY_ARRAY_NUM_BLOCKS; block_id++) { + if (array->blocks[block_id]) { + if (array->flags & GRN_TINY_ARRAY_USE_MALLOC) { + GRN_FREE(array->blocks[block_id]); + } else { + GRN_CTX_FREE(ctx, array->blocks[block_id]); + } + array->blocks[block_id] = NULL; + } + } +} + +void * +grn_tiny_array_at(grn_tiny_array *array, grn_id id) +{ + return grn_tiny_array_at_inline(array, id); +} + +grn_id +grn_tiny_array_id(grn_tiny_array *array, const void *element_address) +{ + const uint8_t * const ptr = (const uint8_t *)element_address; + uint32_t block_id, offset = 1; + for (block_id = 0; block_id < GRN_TINY_ARRAY_NUM_BLOCKS; block_id++) { + const uint32_t block_size = GRN_TINY_ARRAY_GET_BLOCK_SIZE(block_id); + const uint8_t * const block = (const uint8_t *)array->blocks[block_id]; + if (block) { + if (block <= ptr && ptr < (block + block_size * array->element_size)) { + return offset + ((ptr - block) / array->element_size); + } + } + offset += block_size; + } + return GRN_ID_NIL; +} + +/* grn_tiny_bitmap */ + +static void +grn_tiny_bitmap_init(grn_ctx *ctx, grn_tiny_bitmap *bitmap) +{ + bitmap->ctx = ctx; + memset(bitmap->blocks, 0, sizeof(bitmap->blocks)); +} + +static void +grn_tiny_bitmap_fin(grn_tiny_bitmap *bitmap) +{ + int block_id; + grn_ctx * const ctx = bitmap->ctx; + for (block_id = 0; block_id < GRN_TINY_ARRAY_NUM_BLOCKS; block_id++) { + if (bitmap->blocks[block_id]) { + GRN_CTX_FREE(ctx, bitmap->blocks[block_id]); + bitmap->blocks[block_id] = NULL; + } + } +} + +/* Requirements: bit_id != GRN_ID_NIL. */ +inline static uint8_t * +grn_tiny_bitmap_get_byte(grn_tiny_bitmap *bitmap, grn_id bit_id) { + const uint32_t byte_id = (bit_id >> 3) + 1; + const int block_id = grn_tiny_array_get_block_id(byte_id); + uint8_t * const block = (uint8_t *)bitmap->blocks[block_id]; + if (block) { + const size_t offset = GRN_TINY_ARRAY_GET_OFFSET(block_id); + return block + byte_id - offset; + } + return NULL; +} + +/* Requirements: bit_id != GRN_ID_NIL. */ +inline static uint8_t * +grn_tiny_bitmap_put_byte(grn_tiny_bitmap *bitmap, grn_id bit_id) { + const uint32_t byte_id = (bit_id >> 3) + 1; + const int block_id = grn_tiny_array_get_block_id(byte_id); + void ** const block = &bitmap->blocks[block_id]; + const size_t offset = GRN_TINY_ARRAY_GET_OFFSET(block_id); + if (!*block) { + grn_ctx * const ctx = bitmap->ctx; + *block = GRN_CTX_ALLOC(ctx, GRN_TINY_ARRAY_GET_BLOCK_SIZE(block_id)); + if (!*block) { + return NULL; + } + } + return (uint8_t *)*block + byte_id - offset; +} + +/* Requirements: bit_id != GRN_ID_NIL. */ +/* Return value: 1/0 on success, -1 on failure. */ +/* Note: A bitmap is extended if needed. */ +inline static int +grn_tiny_bitmap_put(grn_tiny_bitmap *bitmap, grn_id bit_id) +{ + uint8_t * const ptr = grn_tiny_bitmap_put_byte(bitmap, bit_id); + return ptr ? ((*ptr >> (bit_id & 7)) & 1) : -1; +} + +/* Requirements: bit_id != GRN_ID_NIL. */ +inline static uint8_t * +grn_tiny_bitmap_get_and_set(grn_tiny_bitmap *bitmap, grn_id bit_id, + grn_bool bit) +{ + uint8_t * const ptr = grn_tiny_bitmap_get_byte(bitmap, bit_id); + if (ptr) { + /* This branch will be removed because the given `bit' is constant. */ + if (bit) { + *ptr |= 1 << (bit_id & 7); + } else { + *ptr &= ~(1 << (bit_id & 7)); + } + } + return ptr; +} + +/* Requirements: bit_id != GRN_ID_NIL. */ +/* Note: A bitmap is extended if needed. */ +inline static uint8_t * +grn_tiny_bitmap_put_and_set(grn_tiny_bitmap *bitmap, grn_id bit_id, + grn_bool bit) +{ + uint8_t * const ptr = grn_tiny_bitmap_put_byte(bitmap, bit_id); + if (ptr) { + /* This branch will be removed because the given `bit' is constant. */ + if (bit) { + *ptr |= 1 << (bit_id & 7); + } else { + *ptr &= ~(1 << (bit_id & 7)); + } + } + return ptr; +} + +/* grn_io_array */ + +#define GRN_ARRAY_MAX (GRN_ID_MAX - 8) + +inline static void * +grn_io_array_at_inline(grn_ctx *ctx, grn_io *io, uint32_t segment_id, + uint64_t offset, int flags) +{ + void *ptr; + GRN_IO_ARRAY_AT(io, segment_id, offset, &flags, ptr); + return ptr; +} + +/* + * grn_io_array_bit_at() returns 1/0 on success, -1 on failure. + */ +inline static int +grn_io_array_bit_at(grn_ctx *ctx, grn_io *io, + uint32_t segment_id, uint32_t offset) +{ + uint8_t * const ptr = (uint8_t *)grn_io_array_at_inline( + ctx, io, segment_id, (offset >> 3) + 1, 0); + return ptr ? ((*ptr >> (offset & 7)) & 1) : -1; +} + +/* + * The following functions, grn_io_array_bit_*(), return a non-NULL pointer on + * success, a NULL pointer on failure. + */ +inline static void * +grn_io_array_bit_on(grn_ctx *ctx, grn_io *io, + uint32_t segment_id, uint32_t offset) +{ + uint8_t * const ptr = (uint8_t *)grn_io_array_at_inline( + ctx, io, segment_id, (offset >> 3) + 1, GRN_TABLE_ADD); + if (ptr) { + *ptr |= 1 << (offset & 7); + } + return ptr; +} + +inline static void * +grn_io_array_bit_off(grn_ctx *ctx, grn_io *io, + uint32_t segment_id, uint32_t offset) +{ + uint8_t * const ptr = (uint8_t *)grn_io_array_at_inline( + ctx, io, segment_id, (offset >> 3) + 1, GRN_TABLE_ADD); + if (ptr) { + *ptr &= ~(1 << (offset & 7)); + } + return ptr; +} + +/* grn_table_queue */ + +static void +grn_table_queue_lock_init(grn_ctx *ctx, grn_table_queue *queue) +{ + MUTEX_INIT_SHARED(queue->mutex); + COND_INIT_SHARED(queue->cond); +} + +static void +grn_table_queue_init(grn_ctx *ctx, grn_table_queue *queue) +{ + queue->head = 0; + queue->tail = 0; + queue->cap = GRN_ARRAY_MAX; + queue->unblock_requested = GRN_FALSE; + grn_table_queue_lock_init(ctx, queue); +} + +uint32_t +grn_table_queue_size(grn_table_queue *queue) +{ + return (queue->head < queue->tail) + ? 2 * queue->cap + queue->head - queue->tail + : queue->head - queue->tail; +} + +void +grn_table_queue_head_increment(grn_table_queue *queue) +{ + if (queue->head == 2 * queue->cap) { + queue->head = 1; + } else { + queue->head++; + } +} + +void +grn_table_queue_tail_increment(grn_table_queue *queue) +{ + if (queue->tail == 2 * queue->cap) { + queue->tail = 1; + } else { + queue->tail++; + } +} + +grn_id +grn_table_queue_head(grn_table_queue *queue) +{ + return queue->head > queue->cap + ? queue->head - queue->cap + : queue->head; +} + +grn_id +grn_table_queue_tail(grn_table_queue *queue) +{ + return queue->tail > queue->cap + ? queue->tail - queue->cap + : queue->tail; +} + +/* grn_array */ + +#define GRN_ARRAY_SEGMENT_SIZE 0x400000 + +/* Header of grn_io-based grn_array. */ +struct grn_array_header { + uint32_t flags; + uint32_t curr_rec; + uint32_t value_size; + uint32_t n_entries; + uint32_t n_garbages; + grn_id garbages; + uint32_t lock; + uint32_t truncated; + uint32_t reserved[8]; + grn_table_queue queue; +}; + +/* + * A grn_io-based grn_array consists of the following 2 segments. + * GRN_ARRAY_VALUE_SEGMENT: stores values. + * GRN_ARRAY_BITMAP_SEGMENT: stores whether entries are valid or not. + */ +enum { + GRN_ARRAY_VALUE_SEGMENT = 0, + GRN_ARRAY_BITMAP_SEGMENT = 1 +}; + +inline static grn_bool +grn_array_is_io_array(grn_array *array) +{ + return array->io != NULL; +} + +inline static void * +grn_array_io_entry_at(grn_ctx *ctx, grn_array *array, grn_id id, int flags) +{ + return grn_io_array_at_inline(ctx, array->io, GRN_ARRAY_VALUE_SEGMENT, id, flags); +} + +inline static void * +grn_array_entry_at(grn_ctx *ctx, grn_array *array, grn_id id, int flags) +{ + if (grn_array_is_io_array(array)) { + return grn_array_io_entry_at(ctx, array, id, flags); + } else { + return grn_tiny_array_at_inline(&array->array, id); + } +} + +/* grn_array_bitmap_at() returns 1/0 on success, -1 on failure. */ +inline static int +grn_array_bitmap_at(grn_ctx *ctx, grn_array *array, grn_id id) +{ + if (grn_array_is_io_array(array)) { + return grn_io_array_bit_at(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id); + } else { + return grn_tiny_bitmap_put(&array->bitmap, id); + } +} + +static grn_rc +grn_array_init_tiny_array(grn_ctx *ctx, grn_array *array, const char *path, + uint32_t value_size, uint32_t flags) +{ + if (path) { + ERR(GRN_INVALID_ARGUMENT, "failed to create tiny array"); + return ctx->rc; + } + array->obj.header.flags = flags; + array->ctx = ctx; + array->value_size = value_size; + array->n_keys = 0; + array->keys = NULL; + array->n_garbages = &array->n_garbages_buf; + array->n_entries = &array->n_entries_buf; + array->n_garbages_buf = 0; + array->n_entries_buf = 0; + array->io = NULL; + array->header = NULL; + array->garbages = GRN_ID_NIL; + grn_tiny_array_init(ctx, &array->array, value_size, GRN_TINY_ARRAY_CLEAR); + grn_tiny_bitmap_init(ctx, &array->bitmap); + return GRN_SUCCESS; +} + +static grn_io * +grn_array_create_io_array(grn_ctx *ctx, const char *path, uint32_t value_size) +{ + uint32_t w_of_element = 0; + grn_io_array_spec array_spec[2]; + + while ((1U << w_of_element) < value_size) { + w_of_element++; + } + + array_spec[GRN_ARRAY_VALUE_SEGMENT].w_of_element = w_of_element; + array_spec[GRN_ARRAY_VALUE_SEGMENT].max_n_segments = + 1U << (30 - (22 - w_of_element)); + array_spec[GRN_ARRAY_BITMAP_SEGMENT].w_of_element = 0; + array_spec[GRN_ARRAY_BITMAP_SEGMENT].max_n_segments = 1U << (30 - (22 + 3)); + return grn_io_create_with_array(ctx, path, sizeof(struct grn_array_header), + GRN_ARRAY_SEGMENT_SIZE, grn_io_auto, + 2, array_spec); +} + +static grn_rc +grn_array_init_io_array(grn_ctx *ctx, grn_array *array, const char *path, + uint32_t value_size, uint32_t flags) +{ + grn_io *io; + struct grn_array_header *header; + + io = grn_array_create_io_array(ctx, path, value_size); + if (!io) { + return ctx->rc; + } + grn_io_set_type(io, GRN_TABLE_NO_KEY); + + header = grn_io_header(io); + header->flags = flags; + header->curr_rec = 0; + header->lock = 0; + header->value_size = value_size; + header->n_entries = 0; + header->n_garbages = 0; + header->garbages = GRN_ID_NIL; + header->truncated = GRN_FALSE; + grn_table_queue_init(ctx, &header->queue); + array->obj.header.flags = flags; + array->ctx = ctx; + array->value_size = value_size; + array->n_keys = 0; + array->keys = NULL; + array->n_garbages = &header->n_garbages; + array->n_entries = &header->n_entries; + array->io = io; + array->header = header; + array->lock = &header->lock; + return GRN_SUCCESS; +} + +void +grn_array_queue_lock_clear(grn_ctx *ctx, grn_array *array) +{ + struct grn_array_header *header; + header = grn_io_header(array->io); + grn_table_queue_lock_init(ctx, &header->queue); +} + +grn_table_queue * +grn_array_queue(grn_ctx *ctx, grn_array *array) +{ + if (grn_array_is_io_array(array)) { + struct grn_array_header *header; + header = grn_io_header(array->io); + return &header->queue; + } else { + return NULL; + } +} + +static grn_rc +grn_array_init(grn_ctx *ctx, grn_array *array, + const char *path, uint32_t value_size, uint32_t flags) +{ + if (flags & GRN_ARRAY_TINY) { + return grn_array_init_tiny_array(ctx, array, path, value_size, flags); + } else { + return grn_array_init_io_array(ctx, array, path, value_size, flags); + } +} + +grn_array * +grn_array_create(grn_ctx *ctx, const char *path, uint32_t value_size, uint32_t flags) +{ + if (ctx) { + grn_array * const array = (grn_array *)GRN_CALLOC(sizeof(grn_array)); + if (array) { + GRN_DB_OBJ_SET_TYPE(array, GRN_TABLE_NO_KEY); + if (!grn_array_init(ctx, array, path, value_size, flags)) { + return array; + } + GRN_FREE(array); + } + } + return NULL; +} + +grn_array * +grn_array_open(grn_ctx *ctx, const char *path) +{ + if (ctx) { + grn_io * const io = grn_io_open(ctx, path, grn_io_auto); + if (io) { + struct grn_array_header * const header = grn_io_header(io); + uint32_t io_type = grn_io_get_type(io); + if (io_type == GRN_TABLE_NO_KEY) { + grn_array * const array = (grn_array *)GRN_MALLOC(sizeof(grn_array)); + if (array) { + if (!(header->flags & GRN_ARRAY_TINY)) { + GRN_DB_OBJ_SET_TYPE(array, GRN_TABLE_NO_KEY); + array->obj.header.flags = header->flags; + array->ctx = ctx; + array->value_size = header->value_size; + array->n_keys = 0; + array->keys = NULL; + array->n_garbages = &header->n_garbages; + array->n_entries = &header->n_entries; + array->io = io; + array->header = header; + array->lock = &header->lock; + return array; + } else { + GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid array flags. (%x)", header->flags); + } + GRN_FREE(array); + } + } else { + ERR(GRN_INVALID_FORMAT, + "[table][array] file type must be %#04x: <%#04x>", + GRN_TABLE_NO_KEY, io_type); + } + grn_io_close(ctx, io); + } + } + return NULL; +} + +/* + * grn_array_error_if_truncated() logs an error and returns its error code if + * an array is truncated by another process. + * Otherwise, this function returns GRN_SUCCESS. + * Note that `ctx` and `array` must be valid. + * + * FIXME: An array should be reopened if possible. + */ +static grn_rc +grn_array_error_if_truncated(grn_ctx *ctx, grn_array *array) +{ + if (array->header && array->header->truncated) { + ERR(GRN_FILE_CORRUPT, + "array is truncated, please unmap or reopen the database"); + return GRN_FILE_CORRUPT; + } + return GRN_SUCCESS; +} + +grn_rc +grn_array_close(grn_ctx *ctx, grn_array *array) +{ + grn_rc rc = GRN_SUCCESS; + if (!ctx || !array) { return GRN_INVALID_ARGUMENT; } + if (array->keys) { GRN_FREE(array->keys); } + if (grn_array_is_io_array(array)) { + rc = grn_io_close(ctx, array->io); + } else { + GRN_ASSERT(ctx == array->ctx); + grn_tiny_array_fin(&array->array); + grn_tiny_bitmap_fin(&array->bitmap); + } + GRN_FREE(array); + return rc; +} + +grn_rc +grn_array_remove(grn_ctx *ctx, const char *path) +{ + if (!ctx || !path) { return GRN_INVALID_ARGUMENT; } + return grn_io_remove(ctx, path); +} + +uint32_t +grn_array_size(grn_ctx *ctx, grn_array *array) +{ + if (grn_array_error_if_truncated(ctx, array) != GRN_SUCCESS) { + return 0; + } + return *array->n_entries; +} + +uint32_t +grn_array_get_flags(grn_ctx *ctx, grn_array *array) +{ + return array->header->flags; +} + +grn_rc +grn_array_truncate(grn_ctx *ctx, grn_array *array) +{ + grn_rc rc; + char *path = NULL; + uint32_t value_size, flags; + + if (!ctx || !array) { return GRN_INVALID_ARGUMENT; } + rc = grn_array_error_if_truncated(ctx, array); + if (rc != GRN_SUCCESS) { + return rc; + } + if (grn_array_is_io_array(array)) { + const char * const io_path = grn_io_path(array->io); + if (io_path && *io_path) { + path = GRN_STRDUP(io_path); + if (!path) { + ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path); + return GRN_NO_MEMORY_AVAILABLE; + } + } + } + value_size = array->value_size; + flags = array->obj.header.flags; + + if (grn_array_is_io_array(array)) { + if (path) { + /* Only an I/O array with a valid path uses the `truncated` flag. */ + array->header->truncated = GRN_TRUE; + } + rc = grn_io_close(ctx, array->io); + if (!rc) { + array->io = NULL; + if (path) { + rc = grn_io_remove(ctx, path); + } + } + } + if (!rc) { + rc = grn_array_init(ctx, array, path, value_size, flags); + } + if (path) { GRN_FREE(path); } + return rc; +} + +inline static grn_id +grn_array_get_max_id(grn_array *array) +{ + return grn_array_is_io_array(array) ? array->header->curr_rec : array->array.max; +} + +inline static void * +grn_array_get_value_inline(grn_ctx *ctx, grn_array *array, grn_id id) +{ + if (!ctx || !array) { + return NULL; + } + if (grn_array_error_if_truncated(ctx, array) != GRN_SUCCESS) { + return NULL; + } + if (*array->n_garbages) { + /* + * grn_array_bitmap_at() is a time-consuming function, so it is called only + * when there are garbages in the array. + */ + if (grn_array_bitmap_at(ctx, array, id) != 1) { + return NULL; + } + } else if (id == 0 || id > grn_array_get_max_id(array)) { + return NULL; + } + return grn_array_entry_at(ctx, array, id, 0); +} + +int +grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id, void *valuebuf) +{ + void * const value = grn_array_get_value_inline(ctx, array, id); + if (value) { + if (valuebuf) { + grn_memcpy(valuebuf, value, array->value_size); + } + return array->value_size; + } + return 0; +} + +void * +_grn_array_get_value(grn_ctx *ctx, grn_array *array, grn_id id) +{ + return grn_array_get_value_inline(ctx, array, id); +} + +inline static grn_rc +grn_array_set_value_inline(grn_ctx *ctx, grn_array *array, grn_id id, + const void *value, int flags) +{ + void *entry; + entry = grn_array_entry_at(ctx, array, id, 0); + if (!entry) { + return GRN_NO_MEMORY_AVAILABLE; + } + + switch ((flags & GRN_OBJ_SET_MASK)) { + case GRN_OBJ_SET : + grn_memcpy(entry, value, array->value_size); + return GRN_SUCCESS; + case GRN_OBJ_INCR : + switch (array->value_size) { + case sizeof(int32_t) : + *((int32_t *)entry) += *((int32_t *)value); + return GRN_SUCCESS; + case sizeof(int64_t) : + *((int64_t *)entry) += *((int64_t *)value); + return GRN_SUCCESS; + default : + return GRN_INVALID_ARGUMENT; + } + break; + case GRN_OBJ_DECR : + switch (array->value_size) { + case sizeof(int32_t) : + *((int32_t *)entry) -= *((int32_t *)value); + return GRN_SUCCESS; + case sizeof(int64_t) : + *((int64_t *)entry) -= *((int64_t *)value); + return GRN_SUCCESS; + default : + return GRN_INVALID_ARGUMENT; + } + break; + default : + /* todo : support other types. */ + return GRN_INVALID_ARGUMENT; + } +} + +grn_rc +grn_array_set_value(grn_ctx *ctx, grn_array *array, grn_id id, + const void *value, int flags) +{ + grn_rc rc; + + if (!ctx || !array || !value) { + return GRN_INVALID_ARGUMENT; + } + + rc = grn_array_error_if_truncated(ctx, array); + if (rc != GRN_SUCCESS) { + return rc; + } + if (*array->n_garbages) { + /* + * grn_array_bitmap_at() is a time-consuming function, so it is called only + * when there are garbages in the array. + */ + if (grn_array_bitmap_at(ctx, array, id) != 1) { + return GRN_INVALID_ARGUMENT; + } + } else if (id == 0 || id > grn_array_get_max_id(array)) { + return GRN_INVALID_ARGUMENT; + } + return grn_array_set_value_inline(ctx, array, id, value, flags); +} + +grn_rc +grn_array_delete_by_id(grn_ctx *ctx, grn_array *array, grn_id id, + grn_table_delete_optarg *optarg) +{ + grn_rc rc; + if (!ctx || !array) { + return GRN_INVALID_ARGUMENT; + } + rc = grn_array_error_if_truncated(ctx, array); + if (rc != GRN_SUCCESS) { + return rc; + } + if (grn_array_bitmap_at(ctx, array, id) != 1) { + return GRN_INVALID_ARGUMENT; + } + + { + rc = GRN_SUCCESS; + /* lock */ + if (grn_array_is_io_array(array)) { + if (array->value_size >= sizeof(grn_id)) { + struct grn_array_header * const header = array->header; + void * const entry = grn_array_io_entry_at(ctx, array, id, 0); + if (!entry) { + rc = GRN_INVALID_ARGUMENT; + } else { + *((grn_id *)entry) = header->garbages; + header->garbages = id; + } + } + if (!rc) { + (*array->n_entries)--; + (*array->n_garbages)++; + /* + * The following grn_io_array_bit_off() fails iff a problem has + * occurred after the above grn_array_bitmap_at(). That is to say, + * an unexpected case. + */ + grn_io_array_bit_off(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id); + } + } else { + if (array->value_size >= sizeof(grn_id)) { + void * const entry = grn_tiny_array_get(&array->array, id); + if (!entry) { + rc = GRN_INVALID_ARGUMENT; + } else { + *((grn_id *)entry) = array->garbages; + array->garbages = id; + } + } + if (!rc) { + (*array->n_entries)--; + (*array->n_garbages)++; + /* + * The following grn_io_array_bit_off() fails iff a problem has + * occurred after the above grn_array_bitmap_at(). That is to say, + * an unexpected case. + */ + grn_tiny_bitmap_get_and_set(&array->bitmap, id, 0); + } + } + /* unlock */ + return rc; + } +} + +grn_id +grn_array_at(grn_ctx *ctx, grn_array *array, grn_id id) +{ + if (grn_array_error_if_truncated(ctx, array) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + if (*array->n_garbages) { + /* + * grn_array_bitmap_at() is a time-consuming function, so it is called only + * when there are garbages in the array. + */ + if (grn_array_bitmap_at(ctx, array, id) != 1) { + return GRN_ID_NIL; + } + } else if (id > grn_array_get_max_id(array)) { + return GRN_ID_NIL; + } + return id; +} + +grn_rc +grn_array_copy_sort_key(grn_ctx *ctx, grn_array *array, + grn_table_sort_key *keys, int n_keys) +{ + array->keys = (grn_table_sort_key *)GRN_MALLOCN(grn_table_sort_key, n_keys); + if (!array->keys) { + return ctx->rc; + } + grn_memcpy(array->keys, keys, sizeof(grn_table_sort_key) * n_keys); + array->n_keys = n_keys; + return GRN_SUCCESS; +} + +void +grn_array_cursor_close(grn_ctx *ctx, grn_array_cursor *cursor) +{ + GRN_ASSERT(cursor->ctx == ctx); + GRN_FREE(cursor); +} + +grn_array_cursor * +grn_array_cursor_open(grn_ctx *ctx, grn_array *array, grn_id min, grn_id max, + int offset, int limit, int flags) +{ + grn_array_cursor *cursor; + if (!array || !ctx) { return NULL; } + if (grn_array_error_if_truncated(ctx, array) != GRN_SUCCESS) { + return NULL; + } + + cursor = (grn_array_cursor *)GRN_MALLOCN(grn_array_cursor, 1); + if (!cursor) { return NULL; } + + GRN_DB_OBJ_SET_TYPE(cursor, GRN_CURSOR_TABLE_NO_KEY); + cursor->array = array; + cursor->ctx = ctx; + cursor->obj.header.flags = flags; + cursor->obj.header.domain = GRN_ID_NIL; + + if (flags & GRN_CURSOR_DESCENDING) { + cursor->dir = -1; + if (max) { + cursor->curr_rec = max; + if (!(flags & GRN_CURSOR_LT)) { cursor->curr_rec++; } + } else { + cursor->curr_rec = grn_array_get_max_id(array) + 1; + } + if (min) { + cursor->tail = min; + if ((flags & GRN_CURSOR_GT)) { cursor->tail++; } + } else { + cursor->tail = GRN_ID_NIL + 1; + } + if (cursor->curr_rec < cursor->tail) { cursor->tail = cursor->curr_rec; } + } else { + cursor->dir = 1; + if (min) { + cursor->curr_rec = min; + if (!(flags & GRN_CURSOR_GT)) { cursor->curr_rec--; } + } else { + cursor->curr_rec = GRN_ID_NIL; + } + if (max) { + cursor->tail = max; + if ((flags & GRN_CURSOR_LT)) { cursor->tail--; } + } else { + cursor->tail = grn_array_get_max_id(array); + } + if (cursor->tail < cursor->curr_rec) { cursor->tail = cursor->curr_rec; } + } + + if (*array->n_garbages) { + while (offset && cursor->curr_rec != cursor->tail) { + cursor->curr_rec += cursor->dir; + if (grn_array_bitmap_at(ctx, cursor->array, cursor->curr_rec) == 1) { + offset--; + } + } + } else { + cursor->curr_rec += cursor->dir * offset; + } + cursor->rest = (limit < 0) ? GRN_ARRAY_MAX : limit; + return cursor; +} + +grn_id +grn_array_cursor_next(grn_ctx *ctx, grn_array_cursor *cursor) +{ + if (cursor && cursor->rest) { + while (cursor->curr_rec != cursor->tail) { + cursor->curr_rec += cursor->dir; + if (*cursor->array->n_garbages) { + if (grn_array_bitmap_at(ctx, cursor->array, cursor->curr_rec) != 1) { + continue; + } + } + cursor->rest--; + return cursor->curr_rec; + } + } + return GRN_ID_NIL; +} + +grn_id +grn_array_next(grn_ctx *ctx, grn_array *array, grn_id id) +{ + grn_id max_id; + if (grn_array_error_if_truncated(ctx, array) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + max_id = grn_array_get_max_id(array); + while (++id <= max_id) { + if (!*array->n_garbages || + grn_array_bitmap_at(ctx, array, id) == 1) { + return id; + } + } + return GRN_ID_NIL; +} + +int +grn_array_cursor_get_value(grn_ctx *ctx, grn_array_cursor *cursor, void **value) +{ + if (cursor && value) { + void * const entry = grn_array_entry_at(ctx, cursor->array, cursor->curr_rec, 0); + if (entry) { + *value = entry; + return cursor->array->value_size; + } + } + return 0; +} + +grn_rc +grn_array_cursor_set_value(grn_ctx *ctx, grn_array_cursor *cursor, + const void *value, int flags) +{ + return grn_array_set_value_inline(ctx, cursor->array, cursor->curr_rec, + value, flags); +} + +grn_rc +grn_array_cursor_delete(grn_ctx *ctx, grn_array_cursor *cursor, + grn_table_delete_optarg *optarg) +{ + return grn_array_delete_by_id(ctx, cursor->array, cursor->curr_rec, optarg); +} + +inline static grn_id +grn_array_add_to_tiny_array(grn_ctx *ctx, grn_array *array, void **value) +{ + grn_id id = array->garbages; + void *entry; + if (id) { + /* These operations fail iff the array is broken. */ + entry = grn_tiny_array_get(&array->array, id); + if (!entry) { + return GRN_ID_NIL; + } + array->garbages = *(grn_id *)entry; + memset(entry, 0, array->value_size); + (*array->n_garbages)--; + if (!grn_tiny_bitmap_get_and_set(&array->bitmap, id, 1)) { + /* Actually, it is difficult to recover from this error. */ + *(grn_id *)entry = array->garbages; + array->garbages = id; + (*array->n_garbages)++; + return GRN_ID_NIL; + } + } else { + id = array->array.max + 1; + if (!grn_tiny_bitmap_put_and_set(&array->bitmap, id, 1)) { + return GRN_ID_NIL; + } + entry = grn_tiny_array_put(&array->array, id); + if (!entry) { + grn_tiny_bitmap_get_and_set(&array->bitmap, id, 0); + return GRN_ID_NIL; + } + array->array.max = id; + } + (*array->n_entries)++; + if (value) { *value = entry; } + return id; +} + +inline static grn_id +grn_array_add_to_io_array(grn_ctx *ctx, grn_array *array, void **value) +{ + grn_id id; + void *entry; + struct grn_array_header *header; + if (grn_array_error_if_truncated(ctx, array) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + header = array->header; + id = header->garbages; + if (id) { + /* These operations fail iff the array is broken. */ + entry = grn_array_io_entry_at(ctx, array, id, GRN_TABLE_ADD); + if (!entry) { + return GRN_ID_NIL; + } + header->garbages = *(grn_id *)entry; + memset(entry, 0, header->value_size); + (*array->n_garbages)--; + if (!grn_io_array_bit_on(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id)) { + /* Actually, it is difficult to recover from this error. */ + *(grn_id *)entry = array->garbages; + array->garbages = id; + (*array->n_garbages)++; + return GRN_ID_NIL; + } + } else { + if (header->curr_rec >= GRN_ARRAY_MAX) { return GRN_ID_NIL; } + id = header->curr_rec + 1; + if (!grn_io_array_bit_on(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id)) { + return GRN_ID_NIL; + } + entry = grn_array_io_entry_at(ctx, array, id, GRN_TABLE_ADD); + if (!entry) { + grn_io_array_bit_off(ctx, array->io, GRN_ARRAY_BITMAP_SEGMENT, id); + return GRN_ID_NIL; + } + header->curr_rec = id; + } + (*array->n_entries)++; + if (value) { *value = entry; } + return id; +} + +void +grn_array_clear_curr_rec(grn_ctx *ctx, grn_array *array) +{ + struct grn_array_header * const header = array->header; + header->curr_rec = GRN_ID_NIL; +} + +grn_id +grn_array_add(grn_ctx *ctx, grn_array *array, void **value) +{ + if (ctx && array) { + if (grn_array_is_io_array(array)) { + return grn_array_add_to_io_array(ctx, array, value); + } else { + return grn_array_add_to_tiny_array(ctx, array, value); + } + } + return GRN_ID_NIL; +} + +grn_id +grn_array_push(grn_ctx *ctx, grn_array *array, + void (*func)(grn_ctx *, grn_array *, grn_id, void *), + void *func_arg) +{ + grn_id id = GRN_ID_NIL; + grn_table_queue *queue = grn_array_queue(ctx, array); + if (queue) { + MUTEX_LOCK(queue->mutex); + if (grn_table_queue_head(queue) == queue->cap) { + grn_array_clear_curr_rec(ctx, array); + } + id = grn_array_add(ctx, array, NULL); + if (func) { + func(ctx, array, id, func_arg); + } + if (grn_table_queue_size(queue) == queue->cap) { + grn_table_queue_tail_increment(queue); + } + grn_table_queue_head_increment(queue); + COND_SIGNAL(queue->cond); + MUTEX_UNLOCK(queue->mutex); + } else { + ERR(GRN_OPERATION_NOT_SUPPORTED, "only persistent arrays support push"); + } + return id; +} + +grn_id +grn_array_pull(grn_ctx *ctx, grn_array *array, grn_bool blockp, + void (*func)(grn_ctx *, grn_array *, grn_id, void *), + void *func_arg) +{ + grn_id id = GRN_ID_NIL; + grn_table_queue *queue = grn_array_queue(ctx, array); + if (queue) { + MUTEX_LOCK(queue->mutex); + queue->unblock_requested = GRN_FALSE; + while (grn_table_queue_size(queue) == 0) { + if (!blockp || queue->unblock_requested) { + MUTEX_UNLOCK(queue->mutex); + GRN_OUTPUT_BOOL(0); + return id; + } + COND_WAIT(queue->cond, queue->mutex); + } + grn_table_queue_tail_increment(queue); + id = grn_table_queue_tail(queue); + if (func) { + func(ctx, array, id, func_arg); + } + MUTEX_UNLOCK(queue->mutex); + } else { + ERR(GRN_OPERATION_NOT_SUPPORTED, "only persistent arrays support pull"); + } + return id; +} + +void +grn_array_unblock(grn_ctx *ctx, grn_array *array) +{ + grn_table_queue *queue = grn_array_queue(ctx, array); + if (!queue) { + return; + } + + queue->unblock_requested = GRN_TRUE; + COND_BROADCAST(queue->cond); +} + +/* grn_hash : hash table */ + +#define GRN_HASH_MAX_SEGMENT 0x400 +#define GRN_HASH_HEADER_SIZE_NORMAL 0x9000 +#define GRN_HASH_HEADER_SIZE_LARGE\ + (GRN_HASH_HEADER_SIZE_NORMAL +\ + (sizeof(grn_id) *\ + (GRN_HASH_MAX_KEY_SIZE_LARGE - GRN_HASH_MAX_KEY_SIZE_NORMAL))) +#define GRN_HASH_SEGMENT_SIZE 0x400000 +#define GRN_HASH_KEY_MAX_N_SEGMENTS_NORMAL 0x400 +#define GRN_HASH_KEY_MAX_N_SEGMENTS_LARGE 0x40000 +#define W_OF_KEY_IN_A_SEGMENT 22 +#define GRN_HASH_KEY_MAX_TOTAL_SIZE_NORMAL\ + (((uint64_t)(1) << W_OF_KEY_IN_A_SEGMENT) *\ + GRN_HASH_KEY_MAX_N_SEGMENTS_NORMAL - 1) +#define GRN_HASH_KEY_MAX_TOTAL_SIZE_LARGE\ + (((uint64_t)(1) << W_OF_KEY_IN_A_SEGMENT) *\ + GRN_HASH_KEY_MAX_N_SEGMENTS_LARGE - 1) +#define IDX_MASK_IN_A_SEGMENT 0xfffff + +typedef struct { + uint8_t key[4]; + uint8_t value[1]; +} grn_plain_hash_entry; + +typedef struct { + uint32_t hash_value; + uint8_t key_and_value[1]; +} grn_rich_hash_entry; + +typedef struct { + uint32_t hash_value; + uint16_t flag; + uint16_t key_size; + union { + uint8_t buf[sizeof(uint32_t)]; + uint32_t offset; + } key; + uint8_t value[1]; +} grn_io_hash_entry_normal; + +typedef struct { + uint32_t hash_value; + uint16_t flag; + uint16_t key_size; + union { + uint8_t buf[sizeof(uint64_t)]; + uint64_t offset; + } key; + uint8_t value[1]; +} grn_io_hash_entry_large; + +typedef struct { + uint32_t hash_value; + uint16_t flag; + uint16_t key_size; + union { + uint8_t buf[sizeof(void *)]; + void *ptr; + } key; + uint8_t value[1]; +} grn_tiny_hash_entry; + +/* + * hash_value is valid even if the entry is grn_plain_hash_entry. In this case, + * its hash_value equals its key. + * flag, key_size and key.buf are valid if the entry has a variable length key. + */ +typedef struct { + uint32_t hash_value; + uint16_t flag; + uint16_t key_size; +} grn_hash_entry_header; + +typedef union { + uint32_t hash_value; + grn_hash_entry_header header; + grn_plain_hash_entry plain_entry; + grn_rich_hash_entry rich_entry; + grn_io_hash_entry_normal io_entry_normal; + grn_io_hash_entry_large io_entry_large; + grn_tiny_hash_entry tiny_entry; +} grn_hash_entry; + +typedef struct { + uint32_t key; + uint8_t dummy[1]; +} entry; + +typedef struct { + uint32_t key; + uint16_t flag; + uint16_t size; + uint32_t str; + uint8_t dummy[1]; +} entry_str; + +typedef struct { + uint32_t key; + uint16_t flag; + uint16_t size; + char *str; + uint8_t dummy[1]; +} entry_astr; + +enum { + GRN_HASH_KEY_SEGMENT = 0, + GRN_HASH_ENTRY_SEGMENT = 1, + GRN_HASH_INDEX_SEGMENT = 2, + GRN_HASH_BITMAP_SEGMENT = 3 +}; + +inline static int +grn_hash_name(grn_ctx *ctx, grn_hash *hash, char *buffer, int buffer_size) +{ + int name_size; + + if (DB_OBJ(hash)->id == GRN_ID_NIL) { + grn_strcpy(buffer, buffer_size, "(anonymous)"); + name_size = strlen(buffer); + } else { + name_size = grn_obj_name(ctx, (grn_obj *)hash, buffer, buffer_size); + } + + return name_size; +} + +inline static grn_bool +grn_hash_is_io_hash(grn_hash *hash) +{ + return hash->io != NULL; +} + +inline static void * +grn_io_hash_entry_at(grn_ctx *ctx, grn_hash *hash, grn_id id, int flags) +{ + return grn_io_array_at_inline(ctx, hash->io, GRN_HASH_ENTRY_SEGMENT, id, flags); +} + +/* todo : error handling */ +inline static void * +grn_hash_entry_at(grn_ctx *ctx, grn_hash *hash, grn_id id, int flags) +{ + if (grn_hash_is_io_hash(hash)) { + return grn_io_hash_entry_at(ctx, hash, id, flags); + } else { + return grn_tiny_array_at_inline(&hash->a, id); + } +} + +inline static grn_bool +grn_hash_bitmap_at(grn_ctx *ctx, grn_hash *hash, grn_id id) +{ + if (grn_hash_is_io_hash(hash)) { + return grn_io_array_bit_at(ctx, hash->io, GRN_HASH_BITMAP_SEGMENT, id) == 1; + } else { + return grn_tiny_bitmap_put(&hash->bitmap, id) == 1; + } +} + +inline static grn_id * +grn_io_hash_idx_at(grn_ctx *ctx, grn_hash *hash, grn_id id) +{ + return grn_io_array_at_inline(ctx, hash->io, GRN_HASH_INDEX_SEGMENT, + id, GRN_TABLE_ADD); +} + +inline static grn_id * +grn_hash_idx_at(grn_ctx *ctx, grn_hash *hash, grn_id id) +{ + if (grn_hash_is_io_hash(hash)) { + id = (id & *hash->max_offset) + hash->header.common->idx_offset; + return grn_io_hash_idx_at(ctx, hash, id); + } else { + return hash->index + (id & *hash->max_offset); + } +} + +inline static void * +grn_io_hash_key_at(grn_ctx *ctx, grn_hash *hash, uint64_t pos) +{ + return grn_io_array_at_inline(ctx, hash->io, GRN_HASH_KEY_SEGMENT, + pos, GRN_TABLE_ADD); +} + +#define HASH_IMMEDIATE 1 + +#define MAX_INDEX_SIZE ((GRN_HASH_MAX_SEGMENT * (IDX_MASK_IN_A_SEGMENT + 1)) >> 1) + +inline static uint16_t +grn_hash_entry_get_key_size(grn_hash *hash, grn_hash_entry *entry) +{ + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + return entry->header.key_size; + } else { + return hash->key_size; + } +} + +inline static char * +grn_hash_entry_get_key(grn_ctx *ctx, grn_hash *hash, grn_hash_entry *entry) +{ + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + if (grn_hash_is_io_hash(hash)) { + if (grn_hash_is_large_total_key_size(ctx, hash)) { + if (entry->io_entry_large.flag & HASH_IMMEDIATE) { + return (char *)entry->io_entry_large.key.buf; + } else { + return (char *)grn_io_hash_key_at(ctx, hash, + entry->io_entry_large.key.offset); + } + } else { + if (entry->io_entry_normal.flag & HASH_IMMEDIATE) { + return (char *)entry->io_entry_normal.key.buf; + } else { + return (char *)grn_io_hash_key_at(ctx, hash, + entry->io_entry_normal.key.offset); + } + } + } else { + if (entry->tiny_entry.flag & HASH_IMMEDIATE) { + return (char *)entry->tiny_entry.key.buf; + } else { + return entry->tiny_entry.key.ptr; + } + } + } else { + if (hash->key_size == sizeof(uint32_t)) { + return (char *)entry->plain_entry.key; + } else { + return (char *)entry->rich_entry.key_and_value; + } + } +} + +inline static void * +grn_hash_entry_get_value(grn_ctx *ctx, grn_hash *hash, grn_hash_entry *entry) +{ + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + if (grn_hash_is_io_hash(hash)) { + if (grn_hash_is_large_total_key_size(ctx, hash)) { + return entry->io_entry_large.value; + } else { + return entry->io_entry_normal.value; + } + } else { + return entry->tiny_entry.value; + } + } else { + if (hash->key_size == sizeof(uint32_t)) { + return entry->plain_entry.value; + } else { + return entry->rich_entry.key_and_value + hash->key_size; + } + } +} + +inline static grn_rc +grn_io_hash_entry_put_key(grn_ctx *ctx, grn_hash *hash, + grn_hash_entry *entry, + const void *key, unsigned int key_size) +{ + grn_bool is_large_mode; + grn_bool key_exist; + uint64_t key_offset; + grn_io_hash_entry_normal *io_entry_normal = &(entry->io_entry_normal); + grn_io_hash_entry_large *io_entry_large = &(entry->io_entry_large); + + is_large_mode = grn_hash_is_large_total_key_size(ctx, hash); + + if (is_large_mode) { + key_exist = (io_entry_large->key_size > 0); + } else { + key_exist = (io_entry_normal->key_size > 0); + } + + if (key_exist > 0) { + if (is_large_mode) { + key_offset = io_entry_large->key.offset; + } else { + key_offset = io_entry_normal->key.offset; + } + } else { + uint64_t segment_id; + grn_hash_header_common *header; + uint64_t curr_key; + uint64_t max_total_size; + + header = hash->header.common; + if (key_size >= GRN_HASH_SEGMENT_SIZE) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "[hash][key][put] too long key: <%.*s>: max=%u: key size=%u", + name_size, name, + GRN_HASH_SEGMENT_SIZE, + key_size); + return ctx->rc; + } + + if (is_large_mode) { + curr_key = header->curr_key_large; + max_total_size = GRN_HASH_KEY_MAX_TOTAL_SIZE_LARGE; + } else { + curr_key = header->curr_key_normal; + max_total_size = GRN_HASH_KEY_MAX_TOTAL_SIZE_NORMAL; + } + + if (key_size > (max_total_size - curr_key)) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_NOT_ENOUGH_SPACE, + "[hash][key][put] total key size is over: <%.*s>: " + "max=%" GRN_FMT_INT64U ": " + "current=%" GRN_FMT_INT64U ": " + "new key size=%u", + name_size, name, + max_total_size, + curr_key, + key_size); + return ctx->rc; + } + key_offset = curr_key; + segment_id = (key_offset + key_size) >> W_OF_KEY_IN_A_SEGMENT; + if ((key_offset >> W_OF_KEY_IN_A_SEGMENT) != segment_id) { + key_offset = segment_id << W_OF_KEY_IN_A_SEGMENT; + if (is_large_mode) { + header->curr_key_large = key_offset; + } else { + header->curr_key_normal = key_offset; + } + } + if (is_large_mode) { + header->curr_key_large += key_size; + io_entry_large->key.offset = key_offset; + } else { + header->curr_key_normal += key_size; + io_entry_normal->key.offset = key_offset; + } + } + + { + void * const key_ptr = grn_io_hash_key_at(ctx, hash, key_offset); + if (!key_ptr) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_hash_name(ctx, hash, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_NO_MEMORY_AVAILABLE, + "[hash][key][put] failed to allocate for new key: <%.*s>: " + "new offset:%" GRN_FMT_INT64U " " + "key size:%u", + name_size, name, + key_offset, + key_size); + return ctx->rc; + } + grn_memcpy(key_ptr, key, key_size); + } + return GRN_SUCCESS; +} + +inline static grn_rc +grn_hash_entry_put_key(grn_ctx *ctx, grn_hash *hash, + grn_hash_entry *entry, uint32_t hash_value, + const void *key, unsigned int key_size) +{ + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + if (grn_hash_is_io_hash(hash)) { + grn_bool is_large_mode; + uint8_t *buffer; + size_t buffer_size; + uint16_t flag; + + is_large_mode = grn_hash_is_large_total_key_size(ctx, hash); + if (is_large_mode) { + buffer = entry->io_entry_large.key.buf; + buffer_size = sizeof(entry->io_entry_large.key.buf); + } else { + buffer = entry->io_entry_normal.key.buf; + buffer_size = sizeof(entry->io_entry_normal.key.buf); + } + + if (key_size <= buffer_size) { + grn_memcpy(buffer, key, key_size); + flag = HASH_IMMEDIATE; + } else { + const grn_rc rc = + grn_io_hash_entry_put_key(ctx, hash, entry, key, key_size); + if (rc) { + return rc; + } + flag = 0; + } + + if (is_large_mode) { + entry->io_entry_large.flag = flag; + entry->io_entry_large.hash_value = hash_value; + entry->io_entry_large.key_size = key_size; + } else { + entry->io_entry_normal.flag = flag; + entry->io_entry_normal.hash_value = hash_value; + entry->io_entry_normal.key_size = key_size; + } + } else { + if (key_size <= sizeof(entry->tiny_entry.key.buf)) { + grn_memcpy(entry->tiny_entry.key.buf, key, key_size); + entry->tiny_entry.flag = HASH_IMMEDIATE; + } else { + grn_ctx * const ctx = hash->ctx; + entry->tiny_entry.key.ptr = GRN_CTX_ALLOC(ctx, key_size); + if (!entry->tiny_entry.key.ptr) { + return GRN_NO_MEMORY_AVAILABLE; + } + grn_memcpy(entry->tiny_entry.key.ptr, key, key_size); + entry->tiny_entry.flag = 0; + } + entry->tiny_entry.hash_value = hash_value; + entry->tiny_entry.key_size = key_size; + } + } else { + if (hash->key_size == sizeof(uint32_t)) { + *(uint32_t *)entry->plain_entry.key = hash_value; + } else { + entry->rich_entry.hash_value = hash_value; + grn_memcpy(entry->rich_entry.key_and_value, key, key_size); + } + } + return GRN_SUCCESS; +} + +/* + * grn_hash_entry_compare_key() returns GRN_TRUE if the entry key equals the + * specified key, or GRN_FALSE otherwise. + */ +inline static grn_bool +grn_hash_entry_compare_key(grn_ctx *ctx, grn_hash *hash, + grn_hash_entry *entry, uint32_t hash_value, + const void *key, unsigned int key_size) +{ + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + if (entry->hash_value != hash_value || + entry->header.key_size != key_size) { + return GRN_FALSE; + } + if (grn_hash_is_io_hash(hash)) { + if (grn_hash_is_large_total_key_size(ctx, hash)) { + if (entry->io_entry_large.flag & HASH_IMMEDIATE) { + return !memcmp(key, entry->io_entry_large.key.buf, key_size); + } else { + const void * const entry_key_ptr = + grn_io_hash_key_at(ctx, hash, entry->io_entry_large.key.offset); + return !memcmp(key, entry_key_ptr, key_size); + } + } else { + if (entry->io_entry_normal.flag & HASH_IMMEDIATE) { + return !memcmp(key, entry->io_entry_normal.key.buf, key_size); + } else { + const void * const entry_key_ptr = + grn_io_hash_key_at(ctx, hash, entry->io_entry_normal.key.offset); + return !memcmp(key, entry_key_ptr, key_size); + } + } + } else { + if (entry->tiny_entry.flag & HASH_IMMEDIATE) { + return !memcmp(key, entry->tiny_entry.key.buf, key_size); + } else { + return !memcmp(key, entry->tiny_entry.key.ptr, key_size); + } + } + } else { + if (entry->hash_value != hash_value) { + return GRN_FALSE; + } + if (key_size == sizeof(uint32_t)) { + return GRN_TRUE; + } else { + return !memcmp(key, entry->rich_entry.key_and_value, key_size); + } + } +} + +inline static char * +get_key(grn_ctx *ctx, grn_hash *hash, entry_str *n) +{ + return grn_hash_entry_get_key(ctx, hash, (grn_hash_entry *)n); +} + +inline static void * +get_value(grn_ctx *ctx, grn_hash *hash, entry_str *n) +{ + return grn_hash_entry_get_value(ctx, hash, (grn_hash_entry *)n); +} + +inline static int +match_key(grn_ctx *ctx, grn_hash *hash, entry_str *ee, uint32_t h, + const char *key, unsigned int len) +{ + return grn_hash_entry_compare_key(ctx, hash, (grn_hash_entry *)ee, + h, key, len); +} + +#define GARBAGE (0xffffffff) + +inline static uint32_t +grn_io_hash_calculate_entry_size(uint32_t key_size, uint32_t value_size, + uint32_t flags) +{ + if (flags & GRN_OBJ_KEY_VAR_SIZE) { + if (flags & GRN_OBJ_KEY_LARGE) { + return (uintptr_t)((grn_io_hash_entry_large *)0)->value + value_size; + } else { + return (uintptr_t)((grn_io_hash_entry_normal *)0)->value + value_size; + } + } else { + if (key_size == sizeof(uint32_t)) { + return (uintptr_t)((grn_plain_hash_entry *)0)->value + value_size; + } else { + return (uintptr_t)((grn_rich_hash_entry *)0)->key_and_value + + key_size + value_size; + } + } +} + +static grn_io * +grn_io_hash_create_io(grn_ctx *ctx, const char *path, + uint32_t header_size, uint32_t entry_size, + uint32_t flags) +{ + uint32_t w_of_element = 0; + grn_io_array_spec array_spec[4]; + + while ((1U << w_of_element) < entry_size) { + w_of_element++; + } + + array_spec[GRN_HASH_KEY_SEGMENT].w_of_element = 0; + if (flags & GRN_OBJ_KEY_LARGE) { + array_spec[GRN_HASH_KEY_SEGMENT].max_n_segments = + GRN_HASH_KEY_MAX_N_SEGMENTS_LARGE; + } else { + array_spec[GRN_HASH_KEY_SEGMENT].max_n_segments = + GRN_HASH_KEY_MAX_N_SEGMENTS_NORMAL; + } + array_spec[GRN_HASH_ENTRY_SEGMENT].w_of_element = w_of_element; + array_spec[GRN_HASH_ENTRY_SEGMENT].max_n_segments = + 1U << (30 - (22 - w_of_element)); + array_spec[GRN_HASH_INDEX_SEGMENT].w_of_element = 2; + array_spec[GRN_HASH_INDEX_SEGMENT].max_n_segments = 1U << (30 - (22 - 2)); + array_spec[GRN_HASH_BITMAP_SEGMENT].w_of_element = 0; + array_spec[GRN_HASH_BITMAP_SEGMENT].max_n_segments = 1U << (30 - (22 + 3)); + return grn_io_create_with_array(ctx, path, header_size, + GRN_HASH_SEGMENT_SIZE, + grn_io_auto, 4, array_spec); +} + +static grn_rc +grn_io_hash_init(grn_ctx *ctx, grn_hash *hash, const char *path, + uint32_t key_size, uint32_t value_size, uint32_t flags, + grn_encoding encoding, uint32_t init_size) +{ + grn_io *io; + grn_hash_header_common *header; + uint32_t header_size, entry_size, max_offset; + + if (key_size <= GRN_HASH_MAX_KEY_SIZE_NORMAL) { + header_size = GRN_HASH_HEADER_SIZE_NORMAL; + } else { + header_size = GRN_HASH_HEADER_SIZE_LARGE; + } + entry_size = grn_io_hash_calculate_entry_size(key_size, value_size, flags); + + io = grn_io_hash_create_io(ctx, path, header_size, entry_size, flags); + if (!io) { + return GRN_NO_MEMORY_AVAILABLE; + } + grn_io_set_type(io, GRN_TABLE_HASH_KEY); + + max_offset = IDX_MASK_IN_A_SEGMENT + 1; + while (max_offset < init_size * 2) { + max_offset *= 2; + } + max_offset--; + + if (encoding == GRN_ENC_DEFAULT) { + encoding = ctx->encoding; + } + + hash->key_size = key_size; + + header = grn_io_header(io); + header->flags = flags; + header->encoding = encoding; + header->key_size = key_size; + header->curr_rec = 0; + header->curr_key_normal = 0; + header->curr_key_large = 0; + header->lock = 0; + header->idx_offset = 0; + header->value_size = value_size; + header->entry_size = entry_size; + header->max_offset = max_offset; + header->n_entries = 0; + header->n_garbages = 0; + header->tokenizer = GRN_ID_NIL; + if (header->flags & GRN_OBJ_KEY_NORMALIZE) { + header->flags &= ~GRN_OBJ_KEY_NORMALIZE; + hash->normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + header->normalizer = grn_obj_id(ctx, hash->normalizer); + } else { + hash->normalizer = NULL; + header->normalizer = GRN_ID_NIL; + } + header->truncated = GRN_FALSE; + GRN_PTR_INIT(&(hash->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL); + { + grn_table_queue *queue; + if (GRN_HASH_IS_LARGE_KEY(hash)) { + queue = &(((grn_hash_header_large *)(header))->queue); + } else { + queue = &(((grn_hash_header_normal *)(header))->queue); + } + grn_table_queue_init(ctx, queue); + } + + hash->obj.header.flags = (header->flags & GRN_OBJ_FLAGS_MASK); + hash->ctx = ctx; + hash->encoding = encoding; + hash->value_size = value_size; + hash->entry_size = entry_size; + hash->n_garbages = &header->n_garbages; + hash->n_entries = &header->n_entries; + hash->max_offset = &header->max_offset; + hash->io = io; + hash->header.common = header; + hash->lock = &header->lock; + hash->tokenizer = NULL; + return GRN_SUCCESS; +} + +#define INITIAL_INDEX_SIZE 256U + +static uint32_t +grn_tiny_hash_calculate_entry_size(uint32_t key_size, uint32_t value_size, + uint32_t flags) +{ + uint32_t entry_size; + if (flags & GRN_OBJ_KEY_VAR_SIZE) { + entry_size = (uintptr_t)((grn_tiny_hash_entry *)0)->value + value_size; + } else { + if (key_size == sizeof(uint32_t)) { + entry_size = (uintptr_t)((grn_plain_hash_entry *)0)->value + value_size; + } else { + entry_size = (uintptr_t)((grn_rich_hash_entry *)0)->key_and_value + + key_size + value_size; + } + } + if (entry_size != sizeof(uint32_t)) { + entry_size += sizeof(uintptr_t) - 1; + entry_size &= ~(sizeof(uintptr_t) - 1); + } + return entry_size; +} + +static grn_rc +grn_tiny_hash_init(grn_ctx *ctx, grn_hash *hash, const char *path, + uint32_t key_size, uint32_t value_size, uint32_t flags, + grn_encoding encoding) +{ + uint32_t entry_size; + + if (path) { + return GRN_INVALID_ARGUMENT; + } + hash->index = GRN_CTX_ALLOC(ctx, INITIAL_INDEX_SIZE * sizeof(grn_id)); + if (!hash->index) { + return GRN_NO_MEMORY_AVAILABLE; + } + + entry_size = grn_tiny_hash_calculate_entry_size(key_size, value_size, flags); + hash->obj.header.flags = flags; + hash->ctx = ctx; + hash->key_size = key_size; + hash->encoding = encoding; + hash->value_size = value_size; + hash->entry_size = entry_size; + hash->n_garbages = &hash->n_garbages_; + hash->n_entries = &hash->n_entries_; + hash->max_offset = &hash->max_offset_; + hash->max_offset_ = INITIAL_INDEX_SIZE - 1; + hash->io = NULL; + hash->header.common = NULL; + hash->n_garbages_ = 0; + hash->n_entries_ = 0; + hash->garbages = GRN_ID_NIL; + hash->tokenizer = NULL; + hash->normalizer = NULL; + GRN_PTR_INIT(&(hash->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL); + grn_tiny_array_init(ctx, &hash->a, entry_size, GRN_TINY_ARRAY_CLEAR); + grn_tiny_bitmap_init(ctx, &hash->bitmap); + return GRN_SUCCESS; +} + +static grn_rc +grn_hash_init(grn_ctx *ctx, grn_hash *hash, const char *path, + uint32_t key_size, uint32_t value_size, uint32_t flags) +{ + if (flags & GRN_HASH_TINY) { + return grn_tiny_hash_init(ctx, hash, path, key_size, value_size, + flags, ctx->encoding); + } else { + return grn_io_hash_init(ctx, hash, path, key_size, value_size, + flags, ctx->encoding, 0); + } +} + +grn_hash * +grn_hash_create(grn_ctx *ctx, const char *path, uint32_t key_size, uint32_t value_size, + uint32_t flags) +{ + grn_hash *hash; + if (!ctx) { + return NULL; + } + if (key_size > GRN_HASH_MAX_KEY_SIZE_LARGE) { + return NULL; + } + hash = (grn_hash *)GRN_CALLOC(sizeof(grn_hash)); + if (!hash) { + return NULL; + } + GRN_DB_OBJ_SET_TYPE(hash, GRN_TABLE_HASH_KEY); + if (grn_hash_init(ctx, hash, path, key_size, value_size, flags)) { + GRN_FREE(hash); + return NULL; + } + return hash; +} + +grn_hash * +grn_hash_open(grn_ctx *ctx, const char *path) +{ + if (ctx) { + grn_io * const io = grn_io_open(ctx, path, grn_io_auto); + if (io) { + grn_hash_header_common * const header = grn_io_header(io); + uint32_t io_type = grn_io_get_type(io); + if (io_type == GRN_TABLE_HASH_KEY) { + grn_hash * const hash = (grn_hash *)GRN_MALLOC(sizeof(grn_hash)); + if (hash) { + if (!(header->flags & GRN_HASH_TINY)) { + GRN_DB_OBJ_SET_TYPE(hash, GRN_TABLE_HASH_KEY); + hash->ctx = ctx; + hash->key_size = header->key_size; + hash->encoding = header->encoding; + hash->value_size = header->value_size; + hash->entry_size = header->entry_size; + hash->n_garbages = &header->n_garbages; + hash->n_entries = &header->n_entries; + hash->max_offset = &header->max_offset; + hash->io = io; + hash->header.common = header; + hash->lock = &header->lock; + hash->tokenizer = grn_ctx_at(ctx, header->tokenizer); + if (header->flags & GRN_OBJ_KEY_NORMALIZE) { + header->flags &= ~GRN_OBJ_KEY_NORMALIZE; + hash->normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + header->normalizer = grn_obj_id(ctx, hash->normalizer); + } else { + hash->normalizer = grn_ctx_at(ctx, header->normalizer); + } + GRN_PTR_INIT(&(hash->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL); + hash->obj.header.flags = header->flags; + return hash; + } else { + GRN_LOG(ctx, GRN_LOG_NOTICE, + "invalid hash flag. (%x)", header->flags); + } + GRN_FREE(hash); + } + } else { + ERR(GRN_INVALID_FORMAT, + "[table][hash] file type must be %#04x: <%#04x>", + GRN_TABLE_HASH_KEY, io_type); + } + grn_io_close(ctx, io); + } + } + return NULL; +} + +/* + * grn_hash_error_if_truncated() logs an error and returns its error code if + * a hash is truncated by another process. + * Otherwise, this function returns GRN_SUCCESS. + * Note that `ctx` and `hash` must be valid. + * + * FIXME: A hash should be reopened if possible. + */ +static grn_rc +grn_hash_error_if_truncated(grn_ctx *ctx, grn_hash *hash) +{ + if (hash->header.common && hash->header.common->truncated) { + ERR(GRN_FILE_CORRUPT, + "hash is truncated, please unmap or reopen the database"); + return GRN_FILE_CORRUPT; + } + return GRN_SUCCESS; +} + +static grn_rc +grn_tiny_hash_fin(grn_ctx *ctx, grn_hash *hash) +{ + if (!hash->index) { + return GRN_INVALID_ARGUMENT; + } + + GRN_OBJ_FIN(ctx, &(hash->token_filters)); + + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + uint32_t num_remaining_entries = *hash->n_entries; + grn_id *hash_ptr; + for (hash_ptr = hash->index; num_remaining_entries; hash_ptr++) { + const grn_id id = *hash_ptr; + if (id && id != GARBAGE) { + grn_tiny_hash_entry * const entry = + (grn_tiny_hash_entry *)grn_tiny_array_get(&hash->a, id); + GRN_ASSERT(entry); + num_remaining_entries--; + if (entry && !(entry->flag & HASH_IMMEDIATE)) { + GRN_CTX_FREE(ctx, entry->key.ptr); + } + } + } + } + grn_tiny_array_fin(&hash->a); + grn_tiny_bitmap_fin(&hash->bitmap); + GRN_CTX_FREE(ctx, hash->index); + return GRN_SUCCESS; +} + +grn_rc +grn_hash_close(grn_ctx *ctx, grn_hash *hash) +{ + grn_rc rc; + if (!ctx || !hash) { return GRN_INVALID_ARGUMENT; } + if (grn_hash_is_io_hash(hash)) { + rc = grn_io_close(ctx, hash->io); + GRN_OBJ_FIN(ctx, &(hash->token_filters)); + } else { + GRN_ASSERT(ctx == hash->ctx); + rc = grn_tiny_hash_fin(ctx, hash); + } + GRN_FREE(hash); + return rc; +} + +grn_rc +grn_hash_remove(grn_ctx *ctx, const char *path) +{ + if (!ctx || !path) { return GRN_INVALID_ARGUMENT; } + return grn_io_remove(ctx, path); +} + +grn_rc +grn_hash_truncate(grn_ctx *ctx, grn_hash *hash) +{ + grn_rc rc; + char *path = NULL; + uint32_t key_size, value_size, flags; + + if (!ctx || !hash) { + return GRN_INVALID_ARGUMENT; + } + rc = grn_hash_error_if_truncated(ctx, hash); + if (rc != GRN_SUCCESS) { + return rc; + } + + if (grn_hash_is_io_hash(hash)) { + const char * const io_path = grn_io_path(hash->io); + if (io_path && *io_path) { + path = GRN_STRDUP(io_path); + if (!path) { + ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path); + return GRN_NO_MEMORY_AVAILABLE; + } + } + } + key_size = hash->key_size; + value_size = hash->value_size; + flags = hash->obj.header.flags; + + if (grn_hash_is_io_hash(hash)) { + if (path) { + /* Only an I/O hash with a valid path uses the `truncated` flag. */ + hash->header.common->truncated = GRN_TRUE; + } + rc = grn_io_close(ctx, hash->io); + if (!rc) { + hash->io = NULL; + if (path) { + rc = grn_io_remove(ctx, path); + } + } + GRN_OBJ_FIN(ctx, &(hash->token_filters)); + } + if (!rc) { + rc = grn_hash_init(ctx, hash, path, key_size, value_size, flags); + } + if (path) { + GRN_FREE(path); + } + return rc; +} + +inline static uint32_t +grn_hash_calculate_hash_value(const void *ptr, uint32_t size) +{ + uint32_t i; + uint32_t hash_value = 0; + for (i = 0; i < size; i++) { + hash_value = (hash_value * 1021) + ((const uint8_t *)ptr)[i]; + } + return hash_value; +} + +inline static uint32_t +grn_hash_calculate_step(uint32_t hash_value) +{ + return (hash_value >> 2) | 0x1010101; +} + +static grn_rc +grn_hash_reset(grn_ctx *ctx, grn_hash *hash, uint32_t expected_n_entries) +{ + grn_id *new_index = NULL; + uint32_t new_index_size = INITIAL_INDEX_SIZE; + grn_id *src_ptr = NULL, *dest_ptr = NULL; + uint32_t src_offset = 0, dest_offset = 0; + const uint32_t n_entries = *hash->n_entries; + const uint32_t max_offset = *hash->max_offset; + + if (!expected_n_entries) { + expected_n_entries = n_entries * 2; + } + if (expected_n_entries > INT_MAX) { + return GRN_NO_MEMORY_AVAILABLE; + } + while (new_index_size <= expected_n_entries) { + new_index_size *= 2; + } + + if (grn_hash_is_io_hash(hash)) { + uint32_t i; + src_offset = hash->header.common->idx_offset; + dest_offset = MAX_INDEX_SIZE - src_offset; + for (i = 0; i < new_index_size; i += (IDX_MASK_IN_A_SEGMENT + 1)) { + /* + * The following grn_io_hash_idx_at() allocates memory for a new segment + * and returns a pointer to the new segment. It's actually bad manners + * but faster than calling grn_io_hash_idx_at() for each element. + */ + dest_ptr = grn_io_hash_idx_at(ctx, hash, i + dest_offset); + if (!dest_ptr) { + return GRN_NO_MEMORY_AVAILABLE; + } + memset(dest_ptr, 0, GRN_HASH_SEGMENT_SIZE); + } + } else { + GRN_ASSERT(ctx == hash->ctx); + new_index = GRN_CTX_ALLOC(ctx, new_index_size * sizeof(grn_id)); + if (!new_index) { + return GRN_NO_MEMORY_AVAILABLE; + } + src_ptr = hash->index; + } + + { + uint32_t src_pos, count; + const uint32_t new_max_offset = new_index_size - 1; + for (count = 0, src_pos = 0; count < n_entries && src_pos <= max_offset; + src_pos++, src_ptr++) { + uint32_t i, step; + grn_id entry_id; + grn_hash_entry *entry; + if (grn_hash_is_io_hash(hash) && !(src_pos & IDX_MASK_IN_A_SEGMENT)) { + src_ptr = grn_io_hash_idx_at(ctx, hash, src_pos + src_offset); + if (!src_ptr) { + return GRN_NO_MEMORY_AVAILABLE; + } + } + entry_id = *src_ptr; + if (!entry_id || (entry_id == GARBAGE)) { + continue; + } + entry = grn_hash_entry_at(ctx, hash, entry_id, GRN_TABLE_ADD); + if (!entry) { + return GRN_NO_MEMORY_AVAILABLE; + } + step = grn_hash_calculate_step(entry->hash_value); + for (i = entry->hash_value; ; i += step) { + i &= new_max_offset; + if (grn_hash_is_io_hash(hash)) { + dest_ptr = grn_io_hash_idx_at(ctx, hash, i + dest_offset); + if (!dest_ptr) { + return GRN_NO_MEMORY_AVAILABLE; + } + } else { + dest_ptr = new_index + i; + } + if (!*dest_ptr) { + break; + } + } + *dest_ptr = entry_id; + count++; + } + *hash->max_offset = new_max_offset; + *hash->n_garbages = 0; + } + + if (grn_hash_is_io_hash(hash)) { + hash->header.common->idx_offset = dest_offset; + } else { + grn_id * const old_index = hash->index; + hash->index = new_index; + GRN_CTX_FREE(ctx, old_index); + } + + return GRN_SUCCESS; +} + +grn_rc +grn_hash_lock(grn_ctx *ctx, grn_hash *hash, int timeout) +{ + static int _ncalls = 0, _ncolls = 0; + uint32_t count; + _ncalls++; + for (count = 0;; count++) { + uint32_t lock; + GRN_ATOMIC_ADD_EX(hash->lock, 1, lock); + if (lock) { + GRN_ATOMIC_ADD_EX(hash->lock, -1, lock); + if (!timeout || (timeout > 0 && timeout == count)) { break; } + if (!(++_ncolls % 1000000) && (_ncolls > _ncalls)) { + if (_ncolls < 0 || _ncalls < 0) { + _ncolls = 0; _ncalls = 0; + } else { + GRN_LOG(ctx, GRN_LOG_NOTICE, "hash(%p) collisions(%d/%d)", hash, _ncolls, _ncalls); + } + } + grn_nanosleep(GRN_LOCK_WAIT_TIME_NANOSECOND); + continue; + } + return GRN_SUCCESS; + } + ERR(GRN_RESOURCE_DEADLOCK_AVOIDED, "grn_hash_lock"); + return ctx->rc; +} + +grn_rc +grn_hash_unlock(grn_ctx *ctx, grn_hash *hash) +{ + uint32_t lock; + GRN_ATOMIC_ADD_EX(hash->lock, -1, lock); + return GRN_SUCCESS; +} + +grn_rc +grn_hash_clear_lock(grn_ctx *ctx, grn_hash *hash) +{ + *hash->lock = 0; + return GRN_SUCCESS; +} + +uint32_t +grn_hash_size(grn_ctx *ctx, grn_hash *hash) +{ + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return 0; + } + return *hash->n_entries; +} + +inline static grn_id +grn_io_hash_add(grn_ctx *ctx, grn_hash *hash, uint32_t hash_value, + const void *key, unsigned int key_size, void **value) +{ + grn_id entry_id; + grn_hash_entry *entry; + grn_hash_header_common * const header = hash->header.common; + grn_id *garbages; + + if (GRN_HASH_IS_LARGE_KEY(hash)) { + garbages = hash->header.large->garbages; + } else { + garbages = hash->header.normal->garbages; + } + + entry_id = garbages[key_size - 1]; + if (entry_id) { + entry = grn_io_hash_entry_at(ctx, hash, entry_id, GRN_TABLE_ADD); + if (!entry) { + return GRN_ID_NIL; + } + garbages[key_size - 1] = *(grn_id *)entry; + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + /* keep entry->io_entry's hash_value, flag, key_size and key. */ + if (grn_hash_is_large_total_key_size(ctx, hash)) { + memset(entry->io_entry_large.value, 0, header->value_size); + } else { + memset(entry->io_entry_normal.value, 0, header->value_size); + } + } else { + memset(entry, 0, header->entry_size); + } + } else { + entry_id = header->curr_rec + 1; + entry = grn_hash_entry_at(ctx, hash, entry_id, GRN_TABLE_ADD); + if (!entry) { + return GRN_ID_NIL; + } + header->curr_rec = entry_id; + } + + if (!grn_io_array_bit_on(ctx, hash->io, GRN_HASH_BITMAP_SEGMENT, entry_id)) { + /* TODO: error handling. */ + } + + if (grn_hash_entry_put_key(ctx, hash, entry, hash_value, key, key_size)) { + grn_hash_delete_by_id(ctx, hash, entry_id, NULL); + return GRN_ID_NIL; + } + + if (value) { + *value = grn_hash_entry_get_value(ctx, hash, entry); + } + return entry_id; +} + +inline static grn_id +grn_tiny_hash_add(grn_ctx *ctx, grn_hash *hash, uint32_t hash_value, + const void *key, unsigned int key_size, void **value) +{ + grn_id entry_id; + grn_hash_entry *entry; + if (hash->garbages) { + entry_id = hash->garbages; + entry = (grn_hash_entry *)grn_tiny_array_get(&hash->a, entry_id); + hash->garbages = *(grn_id *)entry; + memset(entry, 0, hash->entry_size); + } else { + entry_id = hash->a.max + 1; + entry = (grn_hash_entry *)grn_tiny_array_put(&hash->a, entry_id); + if (!entry) { + return GRN_ID_NIL; + } + } + + if (!grn_tiny_bitmap_put_and_set(&hash->bitmap, entry_id, 1)) { + /* TODO: error handling. */ + } + + if (grn_hash_entry_put_key(ctx, hash, entry, hash_value, key, key_size)) { + /* TODO: error handling. */ + } + + if (value) { + *value = grn_hash_entry_get_value(ctx, hash, entry); + } + return entry_id; +} + +grn_id +grn_hash_add(grn_ctx *ctx, grn_hash *hash, const void *key, + unsigned int key_size, void **value, int *added) +{ + uint32_t hash_value; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + if (!key || !key_size) { + return GRN_ID_NIL; + } + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + if (key_size > hash->key_size) { + ERR(GRN_INVALID_ARGUMENT, "too long key"); + return GRN_ID_NIL; + } + hash_value = grn_hash_calculate_hash_value(key, key_size); + } else { + if (key_size != hash->key_size) { + ERR(GRN_INVALID_ARGUMENT, "key size unmatch"); + return GRN_ID_NIL; + } + if (key_size == sizeof(uint32_t)) { + hash_value = *((uint32_t *)key); + } else { + hash_value = grn_hash_calculate_hash_value(key, key_size); + } + } + + { + uint32_t i; + const uint32_t step = grn_hash_calculate_step(hash_value); + grn_id id, *index, *garbage_index = NULL; + grn_hash_entry *entry; + + /* lock */ + if ((*hash->n_entries + *hash->n_garbages) * 2 > *hash->max_offset) { + if (*hash->max_offset > (1 << 29)) { + ERR(GRN_TOO_LARGE_OFFSET, "hash table size limit"); + return GRN_ID_NIL; + } + grn_hash_reset(ctx, hash, 0); + } + + for (i = hash_value; ; i += step) { + index = grn_hash_idx_at(ctx, hash, i); + if (!index) { + return GRN_ID_NIL; + } + id = *index; + if (!id) { + break; + } + if (id == GARBAGE) { + if (!garbage_index) { + garbage_index = index; + } + continue; + } + + entry = grn_hash_entry_at(ctx, hash, id, GRN_TABLE_ADD); + if (!entry) { + return GRN_ID_NIL; + } + if (grn_hash_entry_compare_key(ctx, hash, entry, hash_value, + key, key_size)) { + if (value) { + *value = grn_hash_entry_get_value(ctx, hash, entry); + } + if (added) { + *added = 0; + } + return id; + } + } + + if (grn_hash_is_io_hash(hash)) { + id = grn_io_hash_add(ctx, hash, hash_value, key, key_size, value); + } else { + id = grn_tiny_hash_add(ctx, hash, hash_value, key, key_size, value); + } + if (!id) { + return GRN_ID_NIL; + } + if (garbage_index) { + (*hash->n_garbages)--; + index = garbage_index; + } + *index = id; + (*hash->n_entries)++; + /* unlock */ + + if (added) { + *added = 1; + } + return id; + } +} + +grn_id +grn_hash_get(grn_ctx *ctx, grn_hash *hash, const void *key, + unsigned int key_size, void **value) +{ + uint32_t hash_value; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + if (key_size > hash->key_size) { + return GRN_ID_NIL; + } + hash_value = grn_hash_calculate_hash_value(key, key_size); + } else { + if (key_size != hash->key_size) { + return GRN_ID_NIL; + } + if (key_size == sizeof(uint32_t)) { + hash_value = *((uint32_t *)key); + } else { + hash_value = grn_hash_calculate_hash_value(key, key_size); + } + } + + { + uint32_t i; + const uint32_t step = grn_hash_calculate_step(hash_value); + for (i = hash_value; ; i += step) { + grn_id id; + grn_id * const index = grn_hash_idx_at(ctx, hash, i); + if (!index) { + return GRN_ID_NIL; + } + id = *index; + if (!id) { + return GRN_ID_NIL; + } + if (id != GARBAGE) { + grn_hash_entry * const entry = grn_hash_entry_at(ctx, hash, id, 0); + if (entry) { + if (grn_hash_entry_compare_key(ctx, hash, entry, hash_value, + key, key_size)) { + if (value) { + *value = grn_hash_entry_get_value(ctx, hash, entry); + } + return id; + } + } + } + } + } +} + +inline static grn_hash_entry * +grn_hash_get_entry(grn_ctx *ctx, grn_hash *hash, grn_id id) +{ + if (!grn_hash_bitmap_at(ctx, hash, id)) { + return NULL; + } + return grn_hash_entry_at(ctx, hash, id, 0); +} + +const char * +_grn_hash_key(grn_ctx *ctx, grn_hash *hash, grn_id id, uint32_t *key_size) +{ + grn_hash_entry * const entry = grn_hash_get_entry(ctx, hash, id); + if (!entry) { + *key_size = 0; + return NULL; + } + *key_size = grn_hash_entry_get_key_size(hash, entry); + return grn_hash_entry_get_key(ctx, hash, entry); +} + +int +grn_hash_get_key(grn_ctx *ctx, grn_hash *hash, grn_id id, void *keybuf, int bufsize) +{ + int key_size; + grn_hash_entry *entry; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return 0; + } + entry = grn_hash_get_entry(ctx, hash, id); + if (!entry) { + return 0; + } + key_size = grn_hash_entry_get_key_size(hash, entry); + if (bufsize >= key_size) { + grn_memcpy(keybuf, grn_hash_entry_get_key(ctx, hash, entry), key_size); + } + return key_size; +} + +int +grn_hash_get_key2(grn_ctx *ctx, grn_hash *hash, grn_id id, grn_obj *bulk) +{ + int key_size; + char *key; + grn_hash_entry *entry; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return 0; + } + entry = grn_hash_get_entry(ctx, hash, id); + if (!entry) { + return 0; + } + key_size = grn_hash_entry_get_key_size(hash, entry); + key = grn_hash_entry_get_key(ctx, hash, entry); + if (bulk->header.impl_flags & GRN_OBJ_REFER) { + bulk->u.b.head = key; + bulk->u.b.curr = key + key_size; + } else { + grn_bulk_write(ctx, bulk, key, key_size); + } + return key_size; +} + +int +grn_hash_get_value(grn_ctx *ctx, grn_hash *hash, grn_id id, void *valuebuf) +{ + void *value; + grn_hash_entry *entry; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return 0; + } + entry = grn_hash_get_entry(ctx, hash, id); + if (!entry) { + return 0; + } + value = grn_hash_entry_get_value(ctx, hash, entry); + if (!value) { + return 0; + } + if (valuebuf) { + grn_memcpy(valuebuf, value, hash->value_size); + } + return hash->value_size; +} + +const char * +grn_hash_get_value_(grn_ctx *ctx, grn_hash *hash, grn_id id, uint32_t *size) +{ + const void *value; + grn_hash_entry *entry; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return NULL; + } + entry = grn_hash_get_entry(ctx, hash, id); + if (!entry) { + return NULL; + } + value = grn_hash_entry_get_value(ctx, hash, entry); + if (!value) { + return NULL; + } + if (size) { + *size = hash->value_size; + } + return (const char *)value; +} + +int +grn_hash_get_key_value(grn_ctx *ctx, grn_hash *hash, grn_id id, + void *keybuf, int bufsize, void *valuebuf) +{ + void *value; + int key_size; + grn_hash_entry *entry; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return 0; + } + entry = grn_hash_get_entry(ctx, hash, id); + if (!entry) { + return 0; + } + key_size = grn_hash_entry_get_key_size(hash, entry); + if (bufsize >= key_size) { + grn_memcpy(keybuf, grn_hash_entry_get_key(ctx, hash, entry), key_size); + } + value = grn_hash_entry_get_value(ctx, hash, entry); + if (!value) { + return 0; + } + if (valuebuf) { + grn_memcpy(valuebuf, value, hash->value_size); + } + return key_size; +} + +int +_grn_hash_get_key_value(grn_ctx *ctx, grn_hash *hash, grn_id id, + void **key, void **value) +{ + int key_size; + grn_hash_entry *entry; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return 0; + } + entry = grn_hash_get_entry(ctx, hash, id); + if (!entry) { + return 0; + } + key_size = grn_hash_entry_get_key_size(hash, entry); + *key = grn_hash_entry_get_key(ctx, hash, entry); + *value = grn_hash_entry_get_value(ctx, hash, entry); + return *value ? key_size : 0; +} + +grn_rc +grn_hash_set_value(grn_ctx *ctx, grn_hash *hash, grn_id id, + const void *value, int flags) +{ + void *entry_value; + grn_hash_entry *entry; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + if (!value) { + return GRN_INVALID_ARGUMENT; + } + entry = grn_hash_get_entry(ctx, hash, id); + if (!entry) { + return GRN_NO_MEMORY_AVAILABLE; + } + entry_value = grn_hash_entry_get_value(ctx, hash, entry); + if (!entry_value) { + return GRN_NO_MEMORY_AVAILABLE; + } + + switch (flags & GRN_OBJ_SET_MASK) { + case GRN_OBJ_SET : + grn_memcpy(entry_value, value, hash->value_size); + return GRN_SUCCESS; + case GRN_OBJ_INCR : + switch (hash->value_size) { + case sizeof(int32_t) : + *((int32_t *)entry_value) += *((int32_t *)value); + return GRN_SUCCESS; + case sizeof(int64_t) : + *((int64_t *)entry_value) += *((int64_t *)value); + return GRN_SUCCESS; + default : + return GRN_INVALID_ARGUMENT; + } + break; + case GRN_OBJ_DECR : + switch (hash->value_size) { + case sizeof(int32_t) : + *((int32_t *)entry_value) -= *((int32_t *)value); + return GRN_SUCCESS; + case sizeof(int64_t) : + *((int64_t *)entry_value) -= *((int64_t *)value); + return GRN_SUCCESS; + default : + return GRN_INVALID_ARGUMENT; + } + break; + default : + ERR(GRN_INVALID_ARGUMENT, "flags = %d", flags); + return ctx->rc; + } +} + +#define DELETE_IT do {\ + *ep = GARBAGE;\ + if (grn_hash_is_io_hash(hash)) {\ + uint32_t size = key_size - 1;\ + grn_id *garbages;\ + if (GRN_HASH_IS_LARGE_KEY(hash)) {\ + garbages = hash->header.large->garbages;\ + } else {\ + garbages = hash->header.normal->garbages;\ + }\ + ee->key = garbages[size];\ + garbages[size] = e;\ + grn_io_array_bit_off(ctx, hash->io, GRN_HASH_BITMAP_SEGMENT, e);\ + } else {\ + ee->key = hash->garbages;\ + hash->garbages = e;\ + if ((hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) && !(ee->flag & HASH_IMMEDIATE)) {\ + grn_ctx *ctx = hash->ctx;\ + GRN_CTX_FREE(ctx, ((entry_astr *)ee)->str);\ + }\ + grn_tiny_bitmap_get_and_set(&hash->bitmap, e, 0);\ + }\ + (*hash->n_entries)--;\ + (*hash->n_garbages)++;\ + rc = GRN_SUCCESS;\ +} while (0) + +grn_rc +grn_hash_delete_by_id(grn_ctx *ctx, grn_hash *hash, grn_id id, + grn_table_delete_optarg *optarg) +{ + entry_str *ee; + grn_rc rc; + if (!hash || !id) { return GRN_INVALID_ARGUMENT; } + rc = grn_hash_error_if_truncated(ctx, hash); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = GRN_INVALID_ARGUMENT; + /* lock */ + ee = grn_hash_entry_at(ctx, hash, id, 0); + if (ee) { + grn_id e, *ep; + uint32_t i, key_size, h = ee->key, s = grn_hash_calculate_step(h); + key_size = (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) ? ee->size : hash->key_size; + for (i = h; ; i += s) { + if (!(ep = grn_hash_idx_at(ctx, hash, i))) { return GRN_NO_MEMORY_AVAILABLE; } + if (!(e = *ep)) { break; } + if (e == id) { + DELETE_IT; + break; + } + } + } + /* unlock */ + return rc; +} + +grn_rc +grn_hash_delete(grn_ctx *ctx, grn_hash *hash, const void *key, uint32_t key_size, + grn_table_delete_optarg *optarg) +{ + uint32_t h, i, m, s; + grn_rc rc = grn_hash_error_if_truncated(ctx, hash); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = GRN_INVALID_ARGUMENT; + if (hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + if (key_size > hash->key_size) { return GRN_INVALID_ARGUMENT; } + h = grn_hash_calculate_hash_value(key, key_size); + } else { + if (key_size != hash->key_size) { return GRN_INVALID_ARGUMENT; } + if (key_size == sizeof(uint32_t)) { + h = *((uint32_t *)key); + } else { + h = grn_hash_calculate_hash_value(key, key_size); + } + } + s = grn_hash_calculate_step(h); + { + grn_id e, *ep; + /* lock */ + m = *hash->max_offset; + for (i = h; ; i += s) { + if (!(ep = grn_hash_idx_at(ctx, hash, i))) { return GRN_NO_MEMORY_AVAILABLE; } + if (!(e = *ep)) { break; } + if (e == GARBAGE) { continue; } + { + entry_str * const ee = grn_hash_entry_at(ctx, hash, e, 0); + if (ee && match_key(ctx, hash, ee, h, key, key_size)) { + DELETE_IT; + break; + } + } + } + /* unlock */ + return rc; + } +} + +/* only valid for hash tables, GRN_OBJ_KEY_VAR_SIZE && GRN_HASH_TINY */ +const char * +_grn_hash_strkey_by_val(void *v, uint16_t *size) +{ + entry_astr *n = (entry_astr *)((uintptr_t)v - + (uintptr_t)&((entry_astr *)0)->dummy); + *size = n->size; + return (n->flag & HASH_IMMEDIATE) ? (char *)&n->str : n->str; +} + +void +grn_hash_cursor_close(grn_ctx *ctx, grn_hash_cursor *c) +{ + GRN_ASSERT(c->ctx == ctx); + GRN_FREE(c); +} + +#define HASH_CURR_MAX(hash) \ + ((grn_hash_is_io_hash(hash)) ? (hash)->header.common->curr_rec : (hash)->a.max) + +grn_hash_cursor * +grn_hash_cursor_open(grn_ctx *ctx, grn_hash *hash, + const void *min, uint32_t min_size, + const void *max, uint32_t max_size, + int offset, int limit, int flags) +{ + grn_hash_cursor *c; + if (!hash || !ctx) { return NULL; } + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return NULL; + } + if (!(c = GRN_MALLOCN(grn_hash_cursor, 1))) { return NULL; } + GRN_DB_OBJ_SET_TYPE(c, GRN_CURSOR_TABLE_HASH_KEY); + c->hash = hash; + c->ctx = ctx; + c->obj.header.flags = flags; + c->obj.header.domain = GRN_ID_NIL; + if (flags & GRN_CURSOR_DESCENDING) { + c->dir = -1; + if (max) { + if (!(c->curr_rec = grn_hash_get(ctx, hash, max, max_size, NULL))) { + c->tail = GRN_ID_NIL; + goto exit; + } + if (!(flags & GRN_CURSOR_LT)) { c->curr_rec++; } + } else { + c->curr_rec = HASH_CURR_MAX(hash) + 1; + } + if (min) { + if (!(c->tail = grn_hash_get(ctx, hash, min, min_size, NULL))) { + c->curr_rec = GRN_ID_NIL; + goto exit; + } + if ((flags & GRN_CURSOR_GT)) { c->tail++; } + } else { + c->tail = GRN_ID_NIL + 1; + } + if (c->curr_rec < c->tail) { c->tail = c->curr_rec; } + } else { + c->dir = 1; + if (min) { + if (!(c->curr_rec = grn_hash_get(ctx, hash, min, min_size, NULL))) { + c->tail = GRN_ID_NIL; + goto exit; + } + if (!(flags & GRN_CURSOR_GT)) { c->curr_rec--; } + } else { + c->curr_rec = GRN_ID_NIL; + } + if (max) { + if (!(c->tail = grn_hash_get(ctx, hash, max, max_size, NULL))) { + c->curr_rec = GRN_ID_NIL; + goto exit; + } + if ((flags & GRN_CURSOR_LT)) { c->tail--; } + } else { + c->tail = HASH_CURR_MAX(hash); + } + if (c->tail < c->curr_rec) { c->tail = c->curr_rec; } + } + if (*hash->n_entries != HASH_CURR_MAX(hash)) { + while (offset && c->curr_rec != c->tail) { + c->curr_rec += c->dir; + if (grn_hash_bitmap_at(ctx, c->hash, c->curr_rec)) { offset--; } + } + } else { + c->curr_rec += c->dir * offset; + } +exit : + c->rest = (limit < 0) ? GRN_ARRAY_MAX : limit; + return c; +} + +grn_id +grn_hash_cursor_next(grn_ctx *ctx, grn_hash_cursor *c) +{ + if (c && c->rest) { + while (c->curr_rec != c->tail) { + c->curr_rec += c->dir; + if (*c->hash->n_entries != HASH_CURR_MAX(c->hash)) { + if (!grn_hash_bitmap_at(ctx, c->hash, c->curr_rec)) { continue; } + } + c->rest--; + return c->curr_rec; + } + } + return GRN_ID_NIL; +} + +grn_id +grn_hash_next(grn_ctx *ctx, grn_hash *hash, grn_id id) +{ + grn_id max = HASH_CURR_MAX(hash); + while (++id <= max) { + if (grn_hash_bitmap_at(ctx, hash, id)) { return id; } + } + return GRN_ID_NIL; +} + +grn_id +grn_hash_at(grn_ctx *ctx, grn_hash *hash, grn_id id) +{ + return grn_hash_bitmap_at(ctx, hash, id) ? id : GRN_ID_NIL; +} + +int +grn_hash_cursor_get_key(grn_ctx *ctx, grn_hash_cursor *c, void **key) +{ + int key_size; + entry_str *ee; + if (!c) { return 0; } + ee = grn_hash_entry_at(ctx, c->hash, c->curr_rec, 0); + if (!ee) { return 0; } + key_size = (c->hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) ? ee->size : c->hash->key_size; + *key = get_key(ctx, c->hash, ee); + return key_size; +} + +int +grn_hash_cursor_get_value(grn_ctx *ctx, grn_hash_cursor *c, void **value) +{ + void *v; + entry_str *ee; + if (!c) { return 0; } + ee = grn_hash_entry_at(ctx, c->hash, c->curr_rec, 0); + if (ee && (v = get_value(ctx, c->hash, ee))) { + *value = v; + return c->hash->value_size; + } + return 0; +} + +int +grn_hash_cursor_get_key_value(grn_ctx *ctx, grn_hash_cursor *c, + void **key, uint32_t *key_size, void **value) +{ + entry_str *ee; + if (!c) { return GRN_INVALID_ARGUMENT; } + ee = grn_hash_entry_at(ctx, c->hash, c->curr_rec, 0); + if (!ee) { return GRN_INVALID_ARGUMENT; } + if (key_size) { + *key_size = (c->hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) ? ee->size : c->hash->key_size; + } + if (key) { *key = get_key(ctx, c->hash, ee); } + if (value) { *value = get_value(ctx, c->hash, ee); } + return c->hash->value_size; +} + +grn_rc +grn_hash_cursor_set_value(grn_ctx *ctx, grn_hash_cursor *c, + const void *value, int flags) +{ + if (!c) { return GRN_INVALID_ARGUMENT; } + return grn_hash_set_value(ctx, c->hash, c->curr_rec, value, flags); +} + +grn_rc +grn_hash_cursor_delete(grn_ctx *ctx, grn_hash_cursor *c, + grn_table_delete_optarg *optarg) +{ + if (!c) { return GRN_INVALID_ARGUMENT; } + return grn_hash_delete_by_id(ctx, c->hash, c->curr_rec, optarg); +} + +/* sort */ + +#define PREPARE_VAL(e,ep,es) do {\ + if ((arg->flags & GRN_TABLE_SORT_BY_VALUE)) {\ + ep = ((const uint8_t *)(get_value(ctx, hash, (entry_str *)(e))));\ + es = hash->value_size;\ + } else {\ + ep = ((const uint8_t *)(get_key(ctx, hash, (entry_str *)(e))));\ + es = ((hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE)\ + ? ((entry_str *)(e))->size : hash->key_size); \ + }\ + ep += arg->offset;\ + es -= arg->offset;\ +} while (0) + +#define COMPARE_VAL_(ap,as,bp,bs)\ + (arg->compar\ + ? arg->compar(ctx,\ + (grn_obj *)hash, (void *)(ap), as,\ + (grn_obj *)hash, (void *)(bp), bs, arg->compar_arg)\ + : ((arg->flags & GRN_TABLE_SORT_AS_NUMBER)\ + ? ((arg->flags & GRN_TABLE_SORT_AS_UNSIGNED)\ + ? ((arg->flags & GRN_TABLE_SORT_AS_INT64)\ + ? *((uint64_t *)(ap)) > *((uint64_t *)(bp))\ + : *((uint32_t *)(ap)) > *((uint32_t *)(bp)))\ + : ((arg->flags & GRN_TABLE_SORT_AS_INT64)\ + ? *((int64_t *)(ap)) > *((int64_t *)(bp))\ + : *((int32_t *)(ap)) > *((int32_t *)(bp))))\ + : grn_str_greater(ap, as, bp, bs))) + +#define COMPARE_VAL(ap,as,bp,bs)\ + ((dir) ? COMPARE_VAL_((bp),(bs),(ap),(as)) : COMPARE_VAL_((ap),(as),(bp),(bs))) + +inline static entry ** +pack(grn_ctx *ctx, grn_hash *hash, entry **res, grn_table_sort_optarg *arg, int dir) +{ + uint32_t n; + uint32_t cs, es; + const uint8_t *cp, *ep; + entry **head, **tail, *e, *c; + grn_id id, m = HASH_CURR_MAX(hash); + for (id = m >> 1;;id = (id == m) ? 1 : id + 1) { + if (grn_hash_bitmap_at(ctx, hash, id)) { break; } + } + c = grn_hash_entry_at(ctx, hash, id, 0); + if (!c) { return NULL; } + PREPARE_VAL(c, cp, cs); + head = res; + n = *hash->n_entries - 1; + tail = res + n; + while (n--) { + do { + id = (id == m) ? 1 : id + 1; + } while (!grn_hash_bitmap_at(ctx, hash, id)); + e = grn_hash_entry_at(ctx, hash, id, 0); + if (!e) { return NULL; } + PREPARE_VAL(e, ep, es); + if (COMPARE_VAL(cp, cs, ep, es)) { + *head++ = e; + } else { + *tail-- = e; + } + } + *head = c; + return *hash->n_entries > 2 ? head : NULL; +} + +inline static void +swap(entry **a, entry **b) +{ + entry *c_ = *a; + *a = *b; + *b = c_; +} + +#define SWAP(a,ap,as,b,bp,bs) do {\ + const uint8_t *cp_ = ap;\ + uint32_t cs_ = as;\ + ap = bp; bp = cp_;\ + as = bs; bs = cs_;\ + swap(a,b);\ +} while (0) + +inline static entry ** +part(grn_ctx *ctx, entry **b, entry **e, grn_table_sort_optarg *arg, grn_hash *hash, int dir) +{ + entry **c; + const uint8_t *bp, *cp, *ep; + uint32_t bs, cs, es; + intptr_t d = e - b; + PREPARE_VAL(*b, bp, bs); + PREPARE_VAL(*e, ep, es); + if (COMPARE_VAL(bp, bs, ep, es)) { + SWAP(b, bp, bs, e, ep, es); + } + if (d < 2) { return NULL; } + c = b + (d >> 1); + PREPARE_VAL(*c, cp, cs); + if (COMPARE_VAL(bp, bs, cp, cs)) { + SWAP(b, bp, bs, c, cp, cs); + } else { + if (COMPARE_VAL(cp, cs, ep, es)) { + SWAP(c, cp, cs, e, ep, es); + } + } + if (d < 3) { return NULL; } + b++; + swap(b, c); + c = b; + PREPARE_VAL(*c, cp, cs); + for (;;) { + do { + b++; + PREPARE_VAL(*b, bp, bs); + } while (COMPARE_VAL(cp, cs, bp, bs)); + do { + e--; + PREPARE_VAL(*e, ep, es); + } while (COMPARE_VAL(ep, es, cp, cs)); + if (b >= e) { break; } + SWAP(b, bp, bs, e, ep, es); + } + SWAP(c, cp, cs, e, ep, es); + return e; +} + +static void +_sort(grn_ctx *ctx, entry **head, entry **tail, int limit, + grn_table_sort_optarg *arg, grn_hash *hash, int dir) +{ + entry **c; + if (head < tail && (c = part(ctx, head, tail, arg, hash, dir))) { + intptr_t rest = limit - 1 - (c - head); + _sort(ctx, head, c - 1, limit, arg, hash, dir); + if (rest > 0) { _sort(ctx, c + 1, tail, (int)rest, arg, hash, dir); } + } +} + +static void +sort(grn_ctx *ctx, + grn_hash *hash, entry **res, int limit, grn_table_sort_optarg *arg, int dir) +{ + entry **c = pack(ctx, hash, res, arg, dir); + if (c) { + intptr_t rest = limit - 1 - (c - res); + _sort(ctx, res, c - 1, limit, arg, hash, dir); + if (rest > 0 ) { + _sort(ctx, c + 1, res + *hash->n_entries - 1, (int)rest, arg, hash, dir); + } + } +} + +typedef struct { + grn_id id; + int32_t v; +} val32; + +#define PREPARE_VAL32(id,e,ep) do {\ + (ep)->id = id;\ + (ep)->v = (arg->flags & GRN_TABLE_SORT_BY_ID)\ + ? (int32_t) id\ + : (*((int32_t *)((byte *)((arg->flags & GRN_TABLE_SORT_BY_VALUE)\ + ? get_value(ctx, hash, (e))\ + : get_key(ctx, hash, (e))) + arg->offset)));\ +} while (0) + +#define COMPARE_VAL32_(ap,bp) \ + (arg->compar\ + ? arg->compar(ctx,\ + (grn_obj *)hash, (void *)&(ap)->v, sizeof(uint32_t),\ + (grn_obj *)hash, (void *)&(bp)->v, sizeof(uint32_t),\ + arg->compar_arg)\ + : ((arg->flags & GRN_TABLE_SORT_AS_NUMBER)\ + ? ((arg->flags & GRN_TABLE_SORT_AS_UNSIGNED)\ + ? *((uint32_t *)&(ap)->v) > *((uint32_t *)&(bp)->v)\ + : *((int32_t *)&(ap)->v) > *((int32_t *)&(bp)->v))\ + : memcmp(&(ap)->v, &(bp)->v, sizeof(uint32_t)) > 0)) + +#define COMPARE_VAL32(ap,bp)\ + ((dir) ? COMPARE_VAL32_((bp),(ap)) : COMPARE_VAL32_((ap),(bp))) + +inline static val32 * +pack_val32(grn_ctx *ctx, grn_hash *hash, val32 *res, grn_table_sort_optarg *arg, int dir) +{ + uint32_t n; + entry_str *e, *c; + val32 *head, *tail, cr, er; + grn_id id, m = HASH_CURR_MAX(hash); + for (id = m >> 1;;id = (id == m) ? 1 : id + 1) { + if (grn_hash_bitmap_at(ctx, hash, id)) { break; } + } + c = grn_hash_entry_at(ctx, hash, id, 0); + if (!c) { return NULL; } + PREPARE_VAL32(id, c, &cr); + head = res; + n = *hash->n_entries - 1; + tail = res + n; + while (n--) { + do { + id = (id == m) ? 1 : id + 1; + } while (!grn_hash_bitmap_at(ctx, hash, id)); + e = grn_hash_entry_at(ctx, hash, id, 0); + if (!e) { return NULL; } + PREPARE_VAL32(id, e, &er); + if (COMPARE_VAL32(&cr, &er)) { + *head++ = er; + } else { + *tail-- = er; + } + } + *head = cr; + return *hash->n_entries > 2 ? head : NULL; +} + +#define SWAP_VAL32(ap,bp) do {\ + val32 cr_ = *ap;\ + *ap = *bp;\ + *bp = cr_;\ +} while (0) + +inline static val32 * +part_val32(grn_ctx *ctx, + val32 *b, val32 *e, grn_table_sort_optarg *arg, grn_hash *hash, int dir) +{ + val32 *c; + intptr_t d = e - b; + if (COMPARE_VAL32(b, e)) { SWAP_VAL32(b, e); } + if (d < 2) { return NULL; } + c = b + (d >> 1); + if (COMPARE_VAL32(b, c)) { + SWAP_VAL32(b, c); + } else { + if (COMPARE_VAL32(c, e)) { SWAP_VAL32(c, e); } + } + if (d < 3) { return NULL; } + b++; + SWAP_VAL32(b, c); + c = b; + for (;;) { + do { b++; } while (COMPARE_VAL32(c, b)); + do { e--; } while (COMPARE_VAL32(e, c)); + if (b >= e) { break; } + SWAP_VAL32(b, e); + } + SWAP_VAL32(c, e); + return e; +} + +static void +_sort_val32(grn_ctx *ctx, val32 *head, val32 *tail, int limit, + grn_table_sort_optarg *arg, grn_hash *hash, int dir) +{ + val32 *c; + if (head < tail && (c = part_val32(ctx, head, tail, arg, hash, dir))) { + intptr_t rest = limit - 1 - (c - head); + _sort_val32(ctx, head, c - 1, limit, arg, hash, dir); + if (rest > 0) { _sort_val32(ctx, c + 1, tail, (int)rest, arg, hash, dir); } + } +} + +static void +sort_val32(grn_ctx *ctx, + grn_hash *hash, val32 *res, int limit, grn_table_sort_optarg *arg, int dir) +{ + val32 *c = pack_val32(ctx, hash, res, arg, dir); + if (c) { + intptr_t rest = limit - 1 - (c - res); + _sort_val32(ctx, res, c - 1, limit, arg, hash, dir); + if (rest > 0 ) { + _sort_val32(ctx, c + 1, res + *hash->n_entries - 1, (int)rest, arg, hash, dir); + } + } +} + +inline static grn_id +entry2id(grn_ctx *ctx, grn_hash *hash, entry *e) +{ + entry *e2; + grn_id id, *ep; + uint32_t i, h = e->key, s = grn_hash_calculate_step(h); + for (i = h; ; i += s) { + if (!(ep = grn_hash_idx_at(ctx, hash, i))) { return GRN_ID_NIL; } + if (!(id = *ep)) { break; } + if (id != GARBAGE) { + e2 = grn_hash_entry_at(ctx, hash, id, 0); + if (!e2) { return GRN_ID_NIL; } + if (e2 == e) { break; } + } + } + return id; +} + +int +grn_hash_sort(grn_ctx *ctx, grn_hash *hash, + int limit, grn_array *result, grn_table_sort_optarg *optarg) +{ + entry **res; + if (!result || !*hash->n_entries) { return 0; } + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return 0; + } + if (!(res = GRN_MALLOC(sizeof(entry *) * *hash->n_entries))) { + GRN_LOG(ctx, GRN_LOG_ALERT, "allocation of entries failed on grn_hash_sort !"); + return 0; + } + if (limit < 0) { + limit += *hash->n_entries + 1; + if (limit < 0) { + GRN_LOG(ctx, GRN_LOG_ALERT, "limit is too small in grn_hash_sort !"); + return 0; + } + } + if (limit > *hash->n_entries) { limit = *hash->n_entries; } + /* hash->limit = limit; */ + if (optarg) { + int dir = (optarg->flags & GRN_TABLE_SORT_DESC); + if ((optarg->flags & GRN_TABLE_SORT_BY_ID) || + (optarg->flags & GRN_TABLE_SORT_BY_VALUE) + ? ((hash->value_size - optarg->offset) == sizeof(uint32_t)) + : (!(hash->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) + && hash->key_size == sizeof(uint32_t))) { + if (sizeof(entry *) != sizeof(val32)) { + GRN_FREE(res); + if (!(res = GRN_MALLOC(sizeof(val32) * *hash->n_entries))) { + GRN_LOG(ctx, GRN_LOG_ALERT, "allocation of entries failed on grn_hash_sort !"); + return 0; + } + } + sort_val32(ctx, hash, (val32 *)res, limit, optarg, dir); + { + int i; + grn_id *v; + val32 *rp = (val32 *)res; + for (i = 0; i < limit; i++, rp++) { + if (!grn_array_add(ctx, result, (void **)&v)) { break; } + if (!(*v = rp->id)) { break; } + } + GRN_FREE(res); + return i; + } + } else { + sort(ctx, hash, res, limit, optarg, dir); + } + } else { + grn_table_sort_optarg opt = {0, NULL, NULL, NULL, 0}; + sort(ctx, hash, res, limit, &opt, 0); + } + { + int i; + grn_id *v; + entry **rp = res; + for (i = 0; i < limit; i++, rp++) { + if (!grn_array_add(ctx, result, (void **)&v)) { break; } + if (!(*v = entry2id(ctx, hash, *rp))) { break; } + } + GRN_FREE(res); + return i; + } +} + +void +grn_hash_check(grn_ctx *ctx, grn_hash *hash) +{ + char buf[8]; + grn_hash_header_common *h = hash->header.common; + if (grn_hash_error_if_truncated(ctx, hash) != GRN_SUCCESS) { + return; + } + GRN_OUTPUT_ARRAY_OPEN("RESULT", 1); + GRN_OUTPUT_MAP_OPEN("SUMMARY", 26); + GRN_OUTPUT_CSTR("flags"); + grn_itoh(h->flags, buf, 8); + GRN_OUTPUT_STR(buf, 8); + GRN_OUTPUT_CSTR("key_size"); + GRN_OUTPUT_INT64(hash->key_size); + GRN_OUTPUT_CSTR("value_size"); + GRN_OUTPUT_INT64(hash->value_size); + GRN_OUTPUT_CSTR("tokenizer"); + GRN_OUTPUT_INT64(h->tokenizer); + GRN_OUTPUT_CSTR("normalizer"); + GRN_OUTPUT_INT64(h->normalizer); + GRN_OUTPUT_CSTR("curr_rec"); + GRN_OUTPUT_INT64(h->curr_rec); + GRN_OUTPUT_CSTR("curr_key_normal"); + GRN_OUTPUT_UINT64(h->curr_key_normal); + GRN_OUTPUT_CSTR("curr_key_large"); + GRN_OUTPUT_UINT64(h->curr_key_large); + GRN_OUTPUT_CSTR("idx_offset"); + GRN_OUTPUT_INT64(h->idx_offset); + GRN_OUTPUT_CSTR("entry_size"); + GRN_OUTPUT_INT64(hash->entry_size); + GRN_OUTPUT_CSTR("max_offset"); + GRN_OUTPUT_INT64(*hash->max_offset); + GRN_OUTPUT_CSTR("n_entries"); + GRN_OUTPUT_INT64(*hash->n_entries); + GRN_OUTPUT_CSTR("n_garbages"); + GRN_OUTPUT_INT64(*hash->n_garbages); + GRN_OUTPUT_CSTR("lock"); + GRN_OUTPUT_INT64(h->lock); + GRN_OUTPUT_MAP_CLOSE(); + GRN_OUTPUT_ARRAY_CLOSE(); +} + +/* rhash : grn_hash with subrecs */ + +#ifdef USE_GRN_INDEX2 + +static uint32_t default_flags = GRN_HASH_TINY; + +grn_rc +grn_rhash_init(grn_ctx *ctx, grn_hash *hash, grn_rec_unit record_unit, int record_size, + grn_rec_unit subrec_unit, int subrec_size, unsigned int max_n_subrecs) +{ + grn_rc rc; + record_size = grn_rec_unit_size(record_unit, record_size); + subrec_size = grn_rec_unit_size(subrec_unit, subrec_size); + if (record_unit != grn_rec_userdef && subrec_unit != grn_rec_userdef) { + subrec_size -= record_size; + } + if (!hash) { return GRN_INVALID_ARGUMENT; } + if (record_size < 0) { return GRN_INVALID_ARGUMENT; } + if ((default_flags & GRN_HASH_TINY)) { + rc = grn_tiny_hash_init(ctx, hash, NULL, record_size, + max_n_subrecs * (GRN_RSET_SCORE_SIZE + subrec_size), + default_flags, GRN_ENC_NONE); + } else { + rc = grn_io_hash_init(ctx, hash, NULL, record_size, + max_n_subrecs * (GRN_RSET_SCORE_SIZE + subrec_size), + default_flags, GRN_ENC_NONE, 0); + } + if (rc) { return rc; } + hash->record_unit = record_unit; + hash->subrec_unit = subrec_unit; + hash->subrec_size = subrec_size; + hash->max_n_subrecs = max_n_subrecs; + return rc; +} + +grn_rc +grn_rhash_fin(grn_ctx *ctx, grn_hash *hash) +{ + grn_rc rc; + if (grn_hash_is_io_hash(hash)) { + rc = grn_io_close(ctx, hash->io); + } else { + GRN_ASSERT(ctx == hash->ctx); + rc = grn_tiny_hash_fin(ctx, hash); + } + return rc; +} + +inline static void +subrecs_push(byte *subrecs, int size, int n_subrecs, int score, void *body, int dir) +{ + byte *v; + int *c2; + int n = n_subrecs - 1, n2; + while (n) { + n2 = (n - 1) >> 1; + c2 = GRN_RSET_SUBRECS_NTH(subrecs,size,n2); + if (GRN_RSET_SUBRECS_CMP(score, *c2, dir) > 0) { break; } + GRN_RSET_SUBRECS_COPY(subrecs,size,n,c2); + n = n2; + } + v = subrecs + n * (size + GRN_RSET_SCORE_SIZE); + *((int *)v) = score; + grn_memcpy(v + GRN_RSET_SCORE_SIZE, body, size); +} + +inline static void +subrecs_replace_min(byte *subrecs, int size, int n_subrecs, int score, void *body, int dir) +{ + byte *v; + int n = 0, n1, n2, *c1, *c2; + for (;;) { + n1 = n * 2 + 1; + n2 = n1 + 1; + c1 = n1 < n_subrecs ? GRN_RSET_SUBRECS_NTH(subrecs,size,n1) : NULL; + c2 = n2 < n_subrecs ? GRN_RSET_SUBRECS_NTH(subrecs,size,n2) : NULL; + if (c1 && GRN_RSET_SUBRECS_CMP(score, *c1, dir) > 0) { + if (c2 && + GRN_RSET_SUBRECS_CMP(score, *c2, dir) > 0 && + GRN_RSET_SUBRECS_CMP(*c1, *c2, dir) > 0) { + GRN_RSET_SUBRECS_COPY(subrecs,size,n,c2); + n = n2; + } else { + GRN_RSET_SUBRECS_COPY(subrecs,size,n,c1); + n = n1; + } + } else { + if (c2 && GRN_RSET_SUBRECS_CMP(score, *c2, dir) > 0) { + GRN_RSET_SUBRECS_COPY(subrecs,size,n,c2); + n = n2; + } else { + break; + } + } + } + v = subrecs + n * (size + GRN_RSET_SCORE_SIZE); + grn_memcpy(v, &score, GRN_RSET_SCORE_SIZE); + grn_memcpy(v + GRN_RSET_SCORE_SIZE, body, size); +} + +void +grn_rhash_add_subrec(grn_hash *s, grn_rset_recinfo *ri, int score, void *body, int dir) +{ + int limit = s->max_n_subrecs; + ri->score += score; + ri->n_subrecs += 1; + if (limit) { + int ssize = s->subrec_size; + int n_subrecs = GRN_RSET_N_SUBRECS(ri); + if (limit < n_subrecs) { + if (GRN_RSET_SUBRECS_CMP(score, *ri->subrecs, dir) > 0) { + subrecs_replace_min(ri->subrecs, ssize, limit, score, body, dir); + } + } else { + subrecs_push(ri->subrecs, ssize, n_subrecs, score, body, dir); + } + } +} + +grn_hash * +grn_rhash_group(grn_hash *s, int limit, grn_group_optarg *optarg) +{ + grn_ctx *ctx = s->ctx; + grn_hash *g, h; + grn_rset_recinfo *ri; + grn_rec_unit unit; + grn_hash_cursor *c; + grn_id rh; + byte *key, *ekey, *gkey = NULL; + int funcp, dir; + unsigned int rsize; + if (!s || !s->index) { return NULL; } + if (optarg) { + unit = grn_rec_userdef; + rsize = optarg->key_size; + funcp = optarg->func ? 1 : 0; + dir = (optarg->mode == grn_sort_ascending) ? -1 : 1; + } else { + unit = grn_rec_document; + rsize = grn_rec_unit_size(unit, sizeof(grn_id)); + funcp = 0; + dir = 1; + } + if (funcp) { + gkey = GRN_MALLOC(rsize ? rsize : 8192); + if (!gkey) { + GRN_LOG(ctx, GRN_LOG_ALERT, "allocation for gkey failed !"); + return NULL; + } + } else { + if (s->key_size <= rsize) { return NULL; } + } + if (!(c = grn_hash_cursor_open(s->ctx, s, NULL, 0, NULL, -1, 0))) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_cursor_open on grn_hash_group failed !"); + if (gkey) { GRN_FREE(gkey); } + return NULL; + } + grn_memcpy(&h, s, sizeof(grn_hash)); + g = s; + s = &h; + if (grn_rhash_init(ctx, g, unit, rsize, s->record_unit, s->key_size, limit)) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_rhash_init in grn_hash_group failed !"); + grn_hash_cursor_close(s->ctx, c); + if (gkey) { GRN_FREE(gkey); } + return NULL; + } + while ((rh = grn_hash_cursor_next(ctx, c))) { + grn_hash_cursor_get_key_value(ctx, c, (void **)&key, NULL, (void **)&ri); + if (funcp) { + if (optarg->func((grn_records *)s, + (grn_recordh *)(intptr_t)rh, gkey, optarg->func_arg)) { continue; } + ekey = key; + } else { + gkey = key; + ekey = key + rsize; + } + { + grn_rset_recinfo *gri; + if (grn_hash_add(ctx, g, gkey, rsize, (void **)&gri, NULL)) { + grn_rhash_add_subrec(g, gri, ri->score, ekey, dir); + } + } + } + grn_hash_cursor_close(s->ctx, c); + grn_rhash_fin(s->ctx, s); + if (funcp) { GRN_FREE(gkey); } + return g; +} + +grn_rc +grn_rhash_subrec_info(grn_ctx *ctx, grn_hash *s, grn_id rh, int index, + grn_id *rid, int *section, int *pos, int *score, void **subrec) +{ + grn_rset_posinfo *pi; + grn_rset_recinfo *ri; + int *p, unit_size = GRN_RSET_SCORE_SIZE + s->subrec_size; + if (!s || !rh || index < 0) { return GRN_INVALID_ARGUMENT; } + if ((unsigned int)index >= s->max_n_subrecs) { return GRN_INVALID_ARGUMENT; } + { + entry_str *ee; + if (!grn_hash_bitmap_at(ctx, s, rh)) { return GRN_INVALID_ARGUMENT; } + ee = grn_hash_entry_at(ctx, s, rh, 0); + if (!ee) { return GRN_INVALID_ARGUMENT; } + pi = (grn_rset_posinfo *)get_key(ctx, s, ee); + ri = get_value(ctx, s, ee); + if (!pi || !ri) { return GRN_INVALID_ARGUMENT; } + } + if (index >= ri->n_subrecs) { return GRN_INVALID_ARGUMENT; } + p = (int *)(ri->subrecs + index * unit_size); + if (score) { *score = p[0]; } + if (subrec) { *subrec = &p[1]; } + switch (s->record_unit) { + case grn_rec_document : + if (rid) { *rid = pi->rid; } + if (section) { *section = (s->subrec_unit != grn_rec_userdef) ? p[1] : 0; } + if (pos) { *pos = (s->subrec_unit == grn_rec_position) ? p[2] : 0; } + break; + case grn_rec_section : + if (rid) { *rid = pi->rid; } + if (section) { *section = pi->sid; } + if (pos) { *pos = (s->subrec_unit == grn_rec_position) ? p[1] : 0; } + break; + default : + pi = (grn_rset_posinfo *)&p[1]; + switch (s->subrec_unit) { + case grn_rec_document : + if (rid) { *rid = pi->rid; } + if (section) { *section = 0; } + if (pos) { *pos = 0; } + break; + case grn_rec_section : + if (rid) { *rid = pi->rid; } + if (section) { *section = pi->sid; } + if (pos) { *pos = 0; } + break; + case grn_rec_position : + if (rid) { *rid = pi->rid; } + if (section) { *section = pi->sid; } + if (pos) { *pos = pi->pos; } + break; + default : + if (rid) { *rid = 0; } + if (section) { *section = 0; } + if (pos) { *pos = 0; } + break; + } + break; + } + return GRN_SUCCESS; +} +#endif /* USE_GRN_INDEX2 */ + +grn_bool +grn_hash_is_large_total_key_size(grn_ctx *ctx, grn_hash *hash) +{ + return (hash->header.common->flags & GRN_OBJ_KEY_LARGE) == GRN_OBJ_KEY_LARGE; +} + +uint64_t +grn_hash_total_key_size(grn_ctx *ctx, grn_hash *hash) +{ + if (grn_hash_is_large_total_key_size(ctx, hash)) { + return hash->header.common->curr_key_large; + } else { + return hash->header.common->curr_key_normal; + } +} + +uint64_t +grn_hash_max_total_key_size(grn_ctx *ctx, grn_hash *hash) +{ + if (grn_hash_is_large_total_key_size(ctx, hash)) { + return GRN_HASH_KEY_MAX_TOTAL_SIZE_LARGE; + } else { + return GRN_HASH_KEY_MAX_TOTAL_SIZE_NORMAL; + } +} diff --git a/storage/mroonga/vendor/groonga/lib/icudump.c b/storage/mroonga/vendor/groonga/lib/icudump.c new file mode 100644 index 00000000..91751f94 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/icudump.c @@ -0,0 +1,298 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2010 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_UNICODE 0x110000 +#define BUF_SIZE 0x100 + +static int +ucs2utf(unsigned int i, unsigned char *buf) +{ + unsigned char *p = buf; + if (i < 0x80) { + *p++ = i; + } else { + if (i < 0x800) { + *p++ = (i >> 6) | 0xc0; + } else { + if (i < 0x00010000) { + *p++ = (i >> 12) | 0xe0; + } else { + if (i < 0x00200000) { + *p++ = (i >> 18) | 0xf0; + } else { + if (i < 0x04000000) { + *p++ = (i >> 24) | 0xf8; + } else if (i < 0x80000000) { + *p++ = (i >> 30) | 0xfc; + *p++ = ((i >> 24) & 0x3f) | 0x80; + } + *p++ = ((i >> 18) & 0x3f) | 0x80; + } + *p++ = ((i >> 12) & 0x3f) | 0x80; + } + *p++ = ((i >> 6) & 0x3f) | 0x80; + } + *p++ = (0x3f & i) | 0x80; + } + *p = '\0'; + return (p - buf); +} + +void +blockcode(void) +{ + UChar32 ch; + unsigned char *p, src[7]; + UBlockCode code, lc = -1; + for (ch = 1; ch < MAX_UNICODE; ch++) { + if (!U_IS_UNICODE_CHAR(ch)) { continue; } + code = ublock_getCode(ch); + if (code != lc) { + ucs2utf(ch, src); + for (p = src; *p; p++) { + printf("%x:", *p); + } + printf("\t%04x\t%d\n", ch, code); + } + lc = code; + } +} + +int +normalize(const char *str, char *res, UNormalizationMode mode) +{ + UErrorCode rc; + int32_t ulen, nlen; + UChar ubuf[BUF_SIZE], nbuf[BUF_SIZE]; + rc = U_ZERO_ERROR; + u_strFromUTF8(ubuf, BUF_SIZE, &ulen, str, -1, &rc); + if (rc != U_ZERO_ERROR /*&& rc != U_STRING_NOT_TERMINATED_WARNING*/) { + return -1; + } + rc = U_ZERO_ERROR; + nlen = unorm_normalize(ubuf, ulen, mode, 0, nbuf, BUF_SIZE, &rc); + if (rc != U_ZERO_ERROR /*&& rc != U_STRING_NOT_TERMINATED_WARNING*/) { + return -1; + } + rc = U_ZERO_ERROR; + u_strToUTF8(res, BUF_SIZE, NULL, nbuf, nlen, &rc); + if (rc != U_ZERO_ERROR /*&& rc != U_BUFFER_OVERFLOW_ERROR*/) { + return -1; + } + return 0; +} + +void +dump(UNormalizationMode mode) +{ + UChar32 ch; + char str[7], norm[BUF_SIZE]; + for (ch = 1; ch < MAX_UNICODE; ch++) { + if (!U_IS_UNICODE_CHAR(ch)) { continue; } + ucs2utf(ch, (unsigned char *)str); + if (normalize(str, norm, mode)) { + printf("ch=%04x error occure\n", ch); + continue; + } + if (strcmp(norm, str)) { + printf("%04x\t%s\t%s\n", ch, str, norm); + } + } +} + +void +ccdump(void) +{ + UChar32 ch; + char str[7], nfd[BUF_SIZE], nfc[BUF_SIZE]; + for (ch = 1; ch < MAX_UNICODE; ch++) { + if (!U_IS_UNICODE_CHAR(ch)) { continue; } + ucs2utf(ch, (unsigned char *)str); + if (normalize(str, nfd, UNORM_NFD)) { + printf("ch=%04x error occure\n", ch); + continue; + } + if (normalize(str, nfc, UNORM_NFC)) { + printf("ch=%04x error occure\n", ch); + continue; + } + if (strcmp(nfd, nfc)) { + printf("%04x\t%s\t%s\n", ch, nfd, nfc); + } + } +} + +enum { + ctype_null = 0, + ctype_alpha, + ctype_digit, + ctype_symbol, + ctype_hiragana, + ctype_katakana, + ctype_kanji, + ctype_others +}; + +static const char *ctypes[] = { + "GRN_CHAR_NULL", + "GRN_CHAR_ALPHA", + "GRN_CHAR_DIGIT", + "GRN_CHAR_SYMBOL", + "GRN_CHAR_HIRAGANA", + "GRN_CHAR_KATAKANA", + "GRN_CHAR_KANJI", + "GRN_CHAR_OTHERS" +}; + +void +gcdump(void) +{ + UChar32 ch; + unsigned char *p, src[7]; + int ctype, lc = -1; + for (ch = 1; ch < MAX_UNICODE; ch++) { + UCharCategory cat; + UBlockCode code; + if (!U_IS_UNICODE_CHAR(ch)) { continue; } + code = ublock_getCode(ch); + switch (code) { + case UBLOCK_CJK_RADICALS_SUPPLEMENT: /* cjk radicals */ + case UBLOCK_KANGXI_RADICALS: /* kanji radicals */ + case UBLOCK_BOPOMOFO: /* bopomofo letter */ + case UBLOCK_HANGUL_COMPATIBILITY_JAMO: /* hangul letter */ + case UBLOCK_KANBUN: /* kaeri ten used in kanbun ex. re-ten */ + case UBLOCK_BOPOMOFO_EXTENDED: /* bopomofo extended letter */ + case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A: /* cjk letter */ + case UBLOCK_CJK_UNIFIED_IDEOGRAPHS: /* cjk letter */ + case UBLOCK_YI_SYLLABLES: /* Yi syllables */ + case UBLOCK_YI_RADICALS: /* Yi radicals */ + case UBLOCK_HANGUL_SYLLABLES: /* hangul syllables */ + case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS: /* cjk letter */ + case UBLOCK_CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B: /* cjk letter */ + case UBLOCK_CJK_COMPATIBILITY_IDEOGRAPHS_SUPPLEMENT: /* cjk letter */ + case UBLOCK_CJK_STROKES: /* kakijun*/ + ctype = ctype_kanji; + break; + case UBLOCK_CJK_SYMBOLS_AND_PUNCTUATION: /* symbols ex. JIS mark */ + case UBLOCK_ENCLOSED_CJK_LETTERS_AND_MONTHS: /* ex. (kabu) */ + case UBLOCK_CJK_COMPATIBILITY: /* symbols ex. ton doll */ + case UBLOCK_CJK_COMPATIBILITY_FORMS: /* symbols ex. tategaki kagi-kakko */ + ctype = ctype_symbol; + break; + case UBLOCK_HIRAGANA: + ctype = ctype_hiragana; + break; + case UBLOCK_KATAKANA: + case UBLOCK_KATAKANA_PHONETIC_EXTENSIONS: + ctype = ctype_katakana; + break; + default: + cat = u_charType(ch); + switch (cat) { + case U_UPPERCASE_LETTER: + case U_LOWERCASE_LETTER: + case U_TITLECASE_LETTER: + case U_MODIFIER_LETTER: + case U_OTHER_LETTER: + ctype = ctype_alpha; + break; + case U_DECIMAL_DIGIT_NUMBER: + case U_LETTER_NUMBER: + case U_OTHER_NUMBER: + ctype = ctype_digit; + break; + case U_DASH_PUNCTUATION: + case U_START_PUNCTUATION: + case U_END_PUNCTUATION: + case U_CONNECTOR_PUNCTUATION: + case U_OTHER_PUNCTUATION: + case U_MATH_SYMBOL: + case U_CURRENCY_SYMBOL: + case U_MODIFIER_SYMBOL: + case U_OTHER_SYMBOL: + ctype = ctype_symbol; + break; + default: + ctype = ctype_others; + break; + } + break; + } + if (ctype != lc) { + ucs2utf(ch, src); + for (p = src; *p; p++) { + printf("%x:", *p); + } + printf("\t%04x\t%s\n", ch, ctypes[ctype]); + } + lc = ctype; + } +} + +struct option options[] = { + {"bc", 0, NULL, 'b'}, + {"nfd", 0, NULL, 'd'}, + {"nfkd", 0, NULL, 'D'}, + {"nfc", 0, NULL, 'c'}, + {"nfkc", 0, NULL, 'C'}, + {"cc", 0, NULL, 'o'}, + {"gc", 0, NULL, 'g'}, + {"version", 0, NULL, 'v'}, +}; + +int +main(int argc, char **argv) +{ + switch (getopt_long(argc, argv, "bdDcCogv", options, NULL)) { + case 'b' : + blockcode(); + break; + case 'd' : + dump(UNORM_NFD); + break; + case 'D' : + dump(UNORM_NFKD); + break; + case 'c' : + dump(UNORM_NFC); + break; + case 'C' : + dump(UNORM_NFKC); + break; + case 'o' : + ccdump(); + break; + case 'g' : + gcdump(); + break; + case 'v' : + printf("%s\n", U_UNICODE_VERSION); + break; + default : + fputs("usage: icudump --[bc|nfd|nfkd|nfc|nfkc|cc|gc|version]\n", stderr); + break; + } + return 0; +} diff --git a/storage/mroonga/vendor/groonga/lib/id.c b/storage/mroonga/vendor/groonga/lib/id.c new file mode 100644 index 00000000..96eae9f9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/id.c @@ -0,0 +1,36 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_db.h" + +grn_bool +grn_id_is_builtin(grn_ctx *ctx, grn_id id) +{ + if (id == GRN_ID_NIL) { + return GRN_FALSE; + } else { + return id < GRN_N_RESERVED_TYPES; + } +} + +grn_bool +grn_id_is_builtin_type(grn_ctx *ctx, grn_id id) +{ + return GRN_DB_OBJECT <= id && id <= GRN_DB_WGS84_GEO_POINT; +} diff --git a/storage/mroonga/vendor/groonga/lib/ii.c b/storage/mroonga/vendor/groonga/lib/ii.c new file mode 100644 index 00000000..2abd0747 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ii.c @@ -0,0 +1,12816 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include +#include +#include +#include + +#ifdef WIN32 +# include +# include +#endif /* WIN32 */ + +#include "grn_ii.h" +#include "grn_ctx_impl.h" +#include "grn_token_cursor.h" +#include "grn_pat.h" +#include "grn_db.h" +#include "grn_output.h" +#include "grn_scorer.h" +#include "grn_util.h" + +#ifdef GRN_WITH_ONIGMO +# define GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH +#endif + +#ifdef GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH +# include "grn_string.h" +# include +#endif + +#define MAX_PSEG 0x20000 +#define MAX_PSEG_SMALL 0x00200 +/* MAX_PSEG_MEDIUM has enough space for the following source: + * * Single source. + * * Source is a fixed size column or _key of a table. + * * Source column is a scalar column. + * * Lexicon doesn't have tokenizer. + */ +#define MAX_PSEG_MEDIUM 0x10000 +#define S_CHUNK (1 << GRN_II_W_CHUNK) +#define W_SEGMENT 18 +#define S_SEGMENT (1 << W_SEGMENT) +#define W_ARRAY_ELEMENT 3 +#define S_ARRAY_ELEMENT (1 << W_ARRAY_ELEMENT) +#define W_ARRAY (W_SEGMENT - W_ARRAY_ELEMENT) +#define ARRAY_MASK_IN_A_SEGMENT ((1 << W_ARRAY) - 1) + +#define S_GARBAGE (1<<12) + +#define CHUNK_SPLIT 0x80000000 +#define CHUNK_SPLIT_THRESHOLD 0x60000 + +#define MAX_N_ELEMENTS 5 + +#define DEFINE_NAME(ii) \ + const char *name; \ + char name_buffer[GRN_TABLE_MAX_KEY_SIZE]; \ + int name_size; \ + do { \ + if (DB_OBJ(ii)->id == GRN_ID_NIL) { \ + name = "(temporary)"; \ + name_size = strlen(name); \ + } else { \ + name_size = grn_obj_name(ctx, (grn_obj *)ii, \ + name_buffer, GRN_TABLE_MAX_KEY_SIZE); \ + name = name_buffer; \ + } \ + } while (GRN_FALSE) + +#define LSEG(pos) ((pos) >> 16) +#define LPOS(pos) (((pos) & 0xffff) << 2) +#define SEG2POS(seg,pos) ((((uint32_t)(seg)) << 16) + (((uint32_t)(pos)) >> 2)) + +#ifndef S_IRUSR +# define S_IRUSR 0400 +#endif /* S_IRUSR */ +#ifndef S_IWUSR +# define S_IWUSR 0200 +#endif /* S_IWUSR */ + +static grn_bool grn_ii_cursor_set_min_enable = GRN_TRUE; +static double grn_ii_select_too_many_index_match_ratio = -1; +static double grn_ii_estimate_size_for_query_reduce_ratio = 0.9; +static grn_bool grn_ii_overlap_token_skip_enable = GRN_FALSE; +static uint32_t grn_ii_builder_block_threshold_force = 0; +static uint32_t grn_ii_max_n_segments_small = MAX_PSEG_SMALL; +static uint32_t grn_ii_max_n_chunks_small = GRN_II_MAX_CHUNK_SMALL; + +void +grn_ii_init_from_env(void) +{ + { + char grn_ii_cursor_set_min_enable_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_II_CURSOR_SET_MIN_ENABLE", + grn_ii_cursor_set_min_enable_env, + GRN_ENV_BUFFER_SIZE); + if (strcmp(grn_ii_cursor_set_min_enable_env, "no") == 0) { + grn_ii_cursor_set_min_enable = GRN_FALSE; + } else { + grn_ii_cursor_set_min_enable = GRN_TRUE; + } + } + + { + char grn_ii_select_too_many_index_match_ratio_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_II_SELECT_TOO_MANY_INDEX_MATCH_RATIO", + grn_ii_select_too_many_index_match_ratio_env, + GRN_ENV_BUFFER_SIZE); + if (grn_ii_select_too_many_index_match_ratio_env[0]) { + grn_ii_select_too_many_index_match_ratio = + atof(grn_ii_select_too_many_index_match_ratio_env); + } + } + + { + char grn_ii_estimate_size_for_query_reduce_ratio_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_II_ESTIMATE_SIZE_FOR_QUERY_REDUCE_RATIO", + grn_ii_estimate_size_for_query_reduce_ratio_env, + GRN_ENV_BUFFER_SIZE); + if (grn_ii_estimate_size_for_query_reduce_ratio_env[0]) { + grn_ii_estimate_size_for_query_reduce_ratio = + atof(grn_ii_estimate_size_for_query_reduce_ratio_env); + } + } + + { + char grn_ii_overlap_token_skip_enable_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_II_OVERLAP_TOKEN_SKIP_ENABLE", + grn_ii_overlap_token_skip_enable_env, + GRN_ENV_BUFFER_SIZE); + if (grn_ii_overlap_token_skip_enable_env[0]) { + grn_ii_overlap_token_skip_enable = GRN_TRUE; + } else { + grn_ii_overlap_token_skip_enable = GRN_FALSE; + } + } + + { + char grn_ii_builder_block_threshold_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_II_BUILDER_BLOCK_THRESHOLD", + grn_ii_builder_block_threshold_env, + GRN_ENV_BUFFER_SIZE); + if (grn_ii_builder_block_threshold_env[0]) { + grn_ii_builder_block_threshold_force = + grn_atoui(grn_ii_builder_block_threshold_env, + grn_ii_builder_block_threshold_env + + strlen(grn_ii_builder_block_threshold_env), + NULL); + } else { + grn_ii_builder_block_threshold_force = 0; + } + } + + { + char grn_ii_max_n_segments_small_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_II_MAX_N_SEGMENTS_SMALL", + grn_ii_max_n_segments_small_env, + GRN_ENV_BUFFER_SIZE); + if (grn_ii_max_n_segments_small_env[0]) { + grn_ii_max_n_segments_small = + grn_atoui(grn_ii_max_n_segments_small_env, + grn_ii_max_n_segments_small_env + + strlen(grn_ii_max_n_segments_small_env), + NULL); + if (grn_ii_max_n_segments_small > MAX_PSEG) { + grn_ii_max_n_segments_small = MAX_PSEG; + } + } + } + + { + char grn_ii_max_n_chunks_small_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_II_MAX_N_CHUNKS_SMALL", + grn_ii_max_n_chunks_small_env, + GRN_ENV_BUFFER_SIZE); + if (grn_ii_max_n_chunks_small_env[0]) { + grn_ii_max_n_chunks_small = + grn_atoui(grn_ii_max_n_chunks_small_env, + grn_ii_max_n_chunks_small_env + + strlen(grn_ii_max_n_chunks_small_env), + NULL); + if (grn_ii_max_n_chunks_small > GRN_II_MAX_CHUNK) { + grn_ii_max_n_chunks_small = GRN_II_MAX_CHUNK; + } + } + } +} + +void +grn_ii_cursor_set_min_enable_set(grn_bool enable) +{ + grn_ii_cursor_set_min_enable = enable; +} + +grn_bool +grn_ii_cursor_set_min_enable_get(void) +{ + return grn_ii_cursor_set_min_enable; +} + +/* segment */ + +inline static uint32_t +segment_get(grn_ctx *ctx, grn_ii *ii) +{ + uint32_t pseg; + if (ii->header->bgqtail == ((ii->header->bgqhead + 1) & (GRN_II_BGQSIZE - 1))) { + pseg = ii->header->bgqbody[ii->header->bgqtail]; + ii->header->bgqtail = (ii->header->bgqtail + 1) & (GRN_II_BGQSIZE - 1); + } else { + pseg = ii->header->pnext; +#ifndef CUT_OFF_COMPATIBILITY + if (!pseg) { + int i; + uint32_t pmax = 0; + char *used; + uint32_t max_segment = ii->seg->header->max_segment; + used = GRN_CALLOC(max_segment); + if (!used) { return max_segment; } + for (i = 0; i < GRN_II_MAX_LSEG && i < max_segment; i++) { + if ((pseg = ii->header->ainfo[i]) != GRN_II_PSEG_NOT_ASSIGNED) { + if (pseg > pmax) { pmax = pseg; } + used[pseg] = 1; + } + if ((pseg = ii->header->binfo[i]) != GRN_II_PSEG_NOT_ASSIGNED) { + if (pseg > pmax) { pmax = pseg; } + used[pseg] = 1; + } + } + for (pseg = 0; pseg < max_segment && used[pseg]; pseg++) ; + GRN_FREE(used); + ii->header->pnext = pmax + 1; + } else +#endif /* CUT_OFF_COMPATIBILITY */ + if (ii->header->pnext < ii->seg->header->max_segment) { + ii->header->pnext++; + } + } + return pseg; +} + +inline static grn_rc +segment_get_clear(grn_ctx *ctx, grn_ii *ii, uint32_t *pseg) +{ + uint32_t seg = segment_get(ctx, ii); + if (seg < ii->seg->header->max_segment) { + void *p = NULL; + GRN_IO_SEG_REF(ii->seg, seg, p); + if (!p) { return GRN_NO_MEMORY_AVAILABLE; } + memset(p, 0, S_SEGMENT); + GRN_IO_SEG_UNREF(ii->seg, seg); + *pseg = seg; + return GRN_SUCCESS; + } else { + return GRN_NO_MEMORY_AVAILABLE; + } +} + +inline static grn_rc +buffer_segment_new(grn_ctx *ctx, grn_ii *ii, uint32_t *segno) +{ + uint32_t lseg, pseg; + if (*segno < GRN_II_MAX_LSEG) { + if (ii->header->binfo[*segno] != GRN_II_PSEG_NOT_ASSIGNED) { + return GRN_INVALID_ARGUMENT; + } + lseg = *segno; + } else { + for (lseg = 0; lseg < GRN_II_MAX_LSEG; lseg++) { + if (ii->header->binfo[lseg] == GRN_II_PSEG_NOT_ASSIGNED) { break; } + } + if (lseg == GRN_II_MAX_LSEG) { return GRN_NO_MEMORY_AVAILABLE; } + *segno = lseg; + } + pseg = segment_get(ctx, ii); + if (pseg < ii->seg->header->max_segment) { + ii->header->binfo[lseg] = pseg; + if (lseg >= ii->header->bmax) { ii->header->bmax = lseg + 1; } + return GRN_SUCCESS; + } else { + return GRN_NO_MEMORY_AVAILABLE; + } +} + +static grn_rc +buffer_segment_reserve(grn_ctx *ctx, grn_ii *ii, + uint32_t *lseg0, uint32_t *pseg0, + uint32_t *lseg1, uint32_t *pseg1) +{ + uint32_t i = 0; + for (;; i++) { + if (i == GRN_II_MAX_LSEG) { + DEFINE_NAME(ii); + MERR("[ii][buffer][segment][reserve] " + "couldn't find a free buffer: <%.*s>: max:<%u>", + name_size, name, + GRN_II_MAX_LSEG); + return ctx->rc; + } + if (ii->header->binfo[i] == GRN_II_PSEG_NOT_ASSIGNED) { break; } + } + *lseg0 = i++; + for (;; i++) { + if (i == GRN_II_MAX_LSEG) { + DEFINE_NAME(ii); + MERR("[ii][buffer][segment][reserve] " + "couldn't find two free buffers: " + "<%.*s>: " + "found:<%u>, max:<%u>", + name_size, name, + *lseg0, GRN_II_MAX_LSEG); + return ctx->rc; + } + if (ii->header->binfo[i] == GRN_II_PSEG_NOT_ASSIGNED) { break; } + } + *lseg1 = i; + if ((*pseg0 = segment_get(ctx, ii)) == ii->seg->header->max_segment) { + DEFINE_NAME(ii); + MERR("[ii][buffer][segment][reserve] " + "couldn't allocate a free segment: <%.*s>: " + "buffer:<%u>, max:<%u>", + name_size, name, + *lseg0, ii->seg->header->max_segment); + return ctx->rc; + } + if ((*pseg1 = segment_get(ctx, ii)) == ii->seg->header->max_segment) { + DEFINE_NAME(ii); + MERR("[ii][buffer][segment][reserve] " + "couldn't allocate two free segments: " + "<%.*s>: " + "found:<%u>, not-found:<%u>, max:<%u>", + name_size, name, + *lseg0, *lseg1, ii->seg->header->max_segment); + return ctx->rc; + } + /* + { + uint32_t pseg; + char *used = GRN_CALLOC(ii->seg->header->max_segment); + if (!used) { return GRN_NO_MEMORY_AVAILABLE; } + for (i = 0; i < GRN_II_MAX_LSEG; i++) { + if ((pseg = ii->header->ainfo[i]) != GRN_II_PSEG_NOT_ASSIGNED) { + used[pseg] = 1; + } + if ((pseg = ii->header->binfo[i]) != GRN_II_PSEG_NOT_ASSIGNED) { + used[pseg] = 1; + } + } + for (pseg = 0;; pseg++) { + if (pseg == ii->seg->header->max_segment) { + GRN_FREE(used); + return GRN_NO_MEMORY_AVAILABLE; + } + if (!used[pseg]) { break; } + } + *pseg0 = pseg++; + for (;; pseg++) { + if (pseg == ii->seg->header->max_segment) { + GRN_FREE(used); + return GRN_NO_MEMORY_AVAILABLE; + } + if (!used[pseg]) { break; } + } + *pseg1 = pseg; + GRN_FREE(used); + } + */ + return ctx->rc; +} + +#define BGQENQUE(lseg) do {\ + if (ii->header->binfo[lseg] != GRN_II_PSEG_NOT_ASSIGNED) {\ + ii->header->bgqbody[ii->header->bgqhead] = ii->header->binfo[lseg];\ + ii->header->bgqhead = (ii->header->bgqhead + 1) & (GRN_II_BGQSIZE - 1);\ + GRN_ASSERT(ii->header->bgqhead != ii->header->bgqtail);\ + }\ +} while (0) + +inline static void +buffer_segment_update(grn_ii *ii, uint32_t lseg, uint32_t pseg) +{ + BGQENQUE(lseg); + // smb_wmb(); + ii->header->binfo[lseg] = pseg; + if (lseg >= ii->header->bmax) { ii->header->bmax = lseg + 1; } +} + +inline static void +buffer_segment_clear(grn_ii *ii, uint32_t lseg) +{ + BGQENQUE(lseg); + // smb_wmb(); + ii->header->binfo[lseg] = GRN_II_PSEG_NOT_ASSIGNED; +} + +/* chunk */ + +#define HEADER_CHUNK_AT(ii,offset) \ + ((((ii)->header->chunks[((offset) >> 3)]) >> ((offset) & 7)) & 1) + +#define HEADER_CHUNK_ON(ii,offset) \ + (((ii)->header->chunks[((offset) >> 3)]) |= (1 << ((offset) & 7))) + +#define HEADER_CHUNK_OFF(ii,offset) \ + (((ii)->header->chunks[((offset) >> 3)]) &= ~(1 << ((offset) & 7))) + +#define N_GARBAGES_TH 1 + +#define N_GARBAGES ((S_GARBAGE - (sizeof(uint32_t) * 4))/(sizeof(uint32_t))) + +typedef struct { + uint32_t head; + uint32_t tail; + uint32_t nrecs; + uint32_t next; + uint32_t recs[N_GARBAGES]; +} grn_ii_ginfo; + +#define WIN_MAP(chunk,ctx,iw,seg,pos,size,mode)\ + grn_io_win_map(chunk, ctx, iw,\ + ((seg) >> GRN_II_N_CHUNK_VARIATION),\ + (((seg) & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << GRN_II_W_LEAST_CHUNK) + (pos),\ + size, mode) +/* +static int new_histogram[32]; +static int free_histogram[32]; +*/ +static grn_rc +chunk_new(grn_ctx *ctx, grn_ii *ii, uint32_t *res, uint32_t size) +{ + uint32_t n_chunks; + + n_chunks = ii->chunk->header->max_segment; + + /* + if (size) { + int m, es = size - 1; + GRN_BIT_SCAN_REV(es, m); + m++; + new_histogram[m]++; + } + */ + if (size > S_CHUNK) { + int i, j; + uint32_t n = (size + S_CHUNK - 1) >> GRN_II_W_CHUNK; + for (i = 0, j = -1; i < n_chunks; i++) { + if (HEADER_CHUNK_AT(ii, i)) { + j = i; + } else { + if (i == j + n) { + j++; + *res = j << GRN_II_N_CHUNK_VARIATION; + for (; j <= i; j++) { HEADER_CHUNK_ON(ii, j); } + return GRN_SUCCESS; + } + } + } + { + DEFINE_NAME(ii); + MERR("[ii][chunk][new] index is full: " + "<%.*s>: " + "size:<%u>, n-chunks:<%u>", + name_size, name, + size, n_chunks); + } + return ctx->rc; + } else { + uint32_t *vp; + int m, aligned_size; + if (size > (1 << GRN_II_W_LEAST_CHUNK)) { + int es = size - 1; + GRN_BIT_SCAN_REV(es, m); + m++; + } else { + m = GRN_II_W_LEAST_CHUNK; + } + aligned_size = 1 << (m - GRN_II_W_LEAST_CHUNK); + if (ii->header->ngarbages[m - GRN_II_W_LEAST_CHUNK] > N_GARBAGES_TH) { + grn_ii_ginfo *ginfo; + uint32_t *gseg; + grn_io_win iw, iw_; + iw_.addr = NULL; + gseg = &ii->header->garbages[m - GRN_II_W_LEAST_CHUNK]; + while (*gseg != GRN_II_PSEG_NOT_ASSIGNED) { + ginfo = WIN_MAP(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr); + //GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo); + if (!ginfo) { + if (iw_.addr) { grn_io_win_unmap(&iw_); } + { + DEFINE_NAME(ii); + MERR("[ii][chunk][new] failed to allocate garbage segment: " + "<%.*s>: " + "n-garbages:<%u>, size:<%u>, n-chunks:<%u>", + name_size, name, + ii->header->ngarbages[m - GRN_II_W_LEAST_CHUNK], + size, + n_chunks); + } + return ctx->rc; + } + if (ginfo->next != GRN_II_PSEG_NOT_ASSIGNED || + ginfo->nrecs > N_GARBAGES_TH) { + *res = ginfo->recs[ginfo->tail]; + if (++ginfo->tail == N_GARBAGES) { ginfo->tail = 0; } + ginfo->nrecs--; + ii->header->ngarbages[m - GRN_II_W_LEAST_CHUNK]--; + if (!ginfo->nrecs) { + HEADER_CHUNK_OFF(ii, *gseg); + *gseg = ginfo->next; + } + if (iw_.addr) { grn_io_win_unmap(&iw_); } + grn_io_win_unmap(&iw); + return GRN_SUCCESS; + } + if (iw_.addr) { grn_io_win_unmap(&iw_); } + iw_ = iw; + gseg = &ginfo->next; + } + if (iw_.addr) { grn_io_win_unmap(&iw_); } + } + vp = &ii->header->free_chunks[m - GRN_II_W_LEAST_CHUNK]; + if (*vp == GRN_II_PSEG_NOT_ASSIGNED) { + int i = 0; + while (HEADER_CHUNK_AT(ii, i)) { + if (++i >= n_chunks) { + DEFINE_NAME(ii); + MERR("[ii][chunk][new] failed to find a free chunk: " + "<%.*s>: " + "index:<%u>, size:<%u>, n-chunks:<%u>", + name_size, name, + m - GRN_II_W_LEAST_CHUNK, + size, + n_chunks); + return ctx->rc; + } + } + HEADER_CHUNK_ON(ii, i); + *vp = i << GRN_II_N_CHUNK_VARIATION; + } + *res = *vp; + *vp += 1 << (m - GRN_II_W_LEAST_CHUNK); + if (!(*vp & ((1 << GRN_II_N_CHUNK_VARIATION) - 1))) { + *vp = GRN_II_PSEG_NOT_ASSIGNED; + } + return GRN_SUCCESS; + } +} + +static grn_rc +chunk_free(grn_ctx *ctx, grn_ii *ii, + uint32_t offset, uint32_t dummy, uint32_t size) +{ + /* + if (size) { + int m, es = size - 1; + GRN_BIT_SCAN_REV(es, m); + m++; + free_histogram[m]++; + } + */ + grn_io_win iw, iw_; + grn_ii_ginfo *ginfo= 0; + uint32_t seg, m, *gseg; + seg = offset >> GRN_II_N_CHUNK_VARIATION; + if (size > S_CHUNK) { + int n = (size + S_CHUNK - 1) >> GRN_II_W_CHUNK; + for (; n--; seg++) { HEADER_CHUNK_OFF(ii, seg); } + return GRN_SUCCESS; + } + if (size > (1 << GRN_II_W_LEAST_CHUNK)) { + int es = size - 1; + GRN_BIT_SCAN_REV(es, m); + m++; + } else { + m = GRN_II_W_LEAST_CHUNK; + } + gseg = &ii->header->garbages[m - GRN_II_W_LEAST_CHUNK]; + iw_.addr = NULL; + while (*gseg != GRN_II_PSEG_NOT_ASSIGNED) { + ginfo = WIN_MAP(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr); + // GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo); + if (!ginfo) { + if (iw_.addr) { grn_io_win_unmap(&iw_); } + return GRN_NO_MEMORY_AVAILABLE; + } + if (ginfo->nrecs < N_GARBAGES) { break; } + if (iw_.addr) { grn_io_win_unmap(&iw_); } + iw_ = iw; + gseg = &ginfo->next; + } + if (*gseg == GRN_II_PSEG_NOT_ASSIGNED) { + grn_rc rc; + if ((rc = chunk_new(ctx, ii, gseg, S_GARBAGE))) { + if (iw_.addr) { grn_io_win_unmap(&iw_); } + return rc; + } + ginfo = WIN_MAP(ii->chunk, ctx, &iw, *gseg, 0, S_GARBAGE, grn_io_rdwr); + /* + uint32_t i = 0; + while (HEADER_CHUNK_AT(ii, i)) { + if (++i >= ii->chunk->header->max_segment) { + return GRN_NO_MEMORY_AVAILABLE; + } + } + HEADER_CHUNK_ON(ii, i); + *gseg = i; + GRN_IO_SEG_MAP2(ii->chunk, *gseg, ginfo); + */ + if (!ginfo) { + if (iw_.addr) { grn_io_win_unmap(&iw_); } + return GRN_NO_MEMORY_AVAILABLE; + } + ginfo->head = 0; + ginfo->tail = 0; + ginfo->nrecs = 0; + ginfo->next = GRN_II_PSEG_NOT_ASSIGNED; + } + if (iw_.addr) { grn_io_win_unmap(&iw_); } + ginfo->recs[ginfo->head] = offset; + if (++ginfo->head == N_GARBAGES) { ginfo->head = 0; } + ginfo->nrecs++; + grn_io_win_unmap(&iw); + ii->header->ngarbages[m - GRN_II_W_LEAST_CHUNK]++; + return GRN_SUCCESS; +} + +#define UNIT_SIZE 0x80 +#define UNIT_MASK (UNIT_SIZE - 1) + +/* */ +static uint8_t * +pack_1(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + v = *p++ << 7; + v += *p++ << 6; + v += *p++ << 5; + v += *p++ << 4; + v += *p++ << 3; + v += *p++ << 2; + v += *p++ << 1; + *rp++ = v + *p++; + return rp; +} +static uint8_t * +unpack_1(uint32_t *p, uint8_t *dp) +{ + *p++ = (*dp >> 7); + *p++ = ((*dp >> 6) & 0x1); + *p++ = ((*dp >> 5) & 0x1); + *p++ = ((*dp >> 4) & 0x1); + *p++ = ((*dp >> 3) & 0x1); + *p++ = ((*dp >> 2) & 0x1); + *p++ = ((*dp >> 1) & 0x1); + *p++ = (*dp++ & 0x1); + return dp; +} +static uint8_t * +pack_2(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + v = *p++ << 6; + v += *p++ << 4; + v += *p++ << 2; + *rp++ = v + *p++; + v = *p++ << 6; + v += *p++ << 4; + v += *p++ << 2; + *rp++ = v + *p++; + return rp; +} +static uint8_t * +unpack_2(uint32_t *p, uint8_t *dp) +{ + *p++ = (*dp >> 6); + *p++ = ((*dp >> 4) & 0x3); + *p++ = ((*dp >> 2) & 0x3); + *p++ = (*dp++ & 0x3); + *p++ = (*dp >> 6); + *p++ = ((*dp >> 4) & 0x3); + *p++ = ((*dp >> 2) & 0x3); + *p++ = (*dp++ & 0x3); + return dp; +} +static uint8_t * +pack_3(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + v = *p++ << 5; + v += *p++ << 2; + *rp++ = v + (*p >> 1); v = *p++ << 7; + v += *p++ << 4; + v += *p++ << 1; + *rp++ = v + (*p >> 2); v = *p++ << 6; + v += *p++ << 3; + *rp++ = v + *p++; + return rp; +} +static uint8_t * +unpack_3(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + *p++ = (*dp >> 5); + *p++ = ((*dp >> 2) & 0x7); + v = ((*dp++ << 1) & 0x7); *p++ = v + (*dp >> 7); + *p++ = ((*dp >> 4) & 0x7); + *p++ = ((*dp >> 1) & 0x7); + v = ((*dp++ << 2) & 0x7); *p++ = v + (*dp >> 6); + *p++ = ((*dp >> 3) & 0x7); + *p++ = (*dp++ & 0x7); + return dp; +} +static uint8_t * +pack_4(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + v = *p++ << 4; + *rp++ = v + *p++; + v = *p++ << 4; + *rp++ = v + *p++; + v = *p++ << 4; + *rp++ = v + *p++; + v = *p++ << 4; + *rp++ = v + *p++; + return rp; +} +static uint8_t * +unpack_4(uint32_t *p, uint8_t *dp) +{ + *p++ = (*dp >> 4); + *p++ = (*dp++ & 0xf); + *p++ = (*dp >> 4); + *p++ = (*dp++ & 0xf); + *p++ = (*dp >> 4); + *p++ = (*dp++ & 0xf); + *p++ = (*dp >> 4); + *p++ = (*dp++ & 0xf); + return dp; +} +static uint8_t * +pack_5(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + v = *p++ << 3; + *rp++ = v + (*p >> 2); v = *p++ << 6; + v += *p++ << 1; + *rp++ = v + (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 1); v = *p++ << 7; + v += *p++ << 2; + *rp++ = v + (*p >> 3); v = *p++ << 5; + *rp++ = v + *p++; + return rp; +} +static uint8_t * +unpack_5(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + *p++ = (*dp >> 3); + v = ((*dp++ << 2) & 0x1f); *p++ = v + (*dp >> 6); + *p++ = ((*dp >> 1) & 0x1f); + v = ((*dp++ << 4) & 0x1f); *p++ = v + (*dp >> 4); + v = ((*dp++ << 1) & 0x1f); *p++ = v + (*dp >> 7); + *p++ = ((*dp >> 2) & 0x1f); + v = ((*dp++ << 3) & 0x1f); *p++ = v + (*dp >> 5); + *p++ = (*dp++ & 0x1f); + return dp; +} +static uint8_t * +pack_6(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + v = *p++ << 2; + *rp++ = v + (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 2); v = *p++ << 6; + *rp++ = v + *p++; + v = *p++ << 2; + *rp++ = v + (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 2); v = *p++ << 6; + *rp++ = v + *p++; + return rp; +} +static uint8_t * +unpack_6(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + *p++ = (*dp >> 2); + v = ((*dp++ << 4) & 0x3f); *p++ = v + (*dp >> 4); + v = ((*dp++ << 2) & 0x3f); *p++ = v + (*dp >> 6); + *p++ = (*dp++ & 0x3f); + *p++ = (*dp >> 2); + v = ((*dp++ << 4) & 0x3f); *p++ = v + (*dp >> 4); + v = ((*dp++ << 2) & 0x3f); *p++ = v + (*dp >> 6); + *p++ = (*dp++ & 0x3f); + return dp; +} +static uint8_t * +pack_7(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + v = *p++ << 1; + *rp++ = v + (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 1); v = *p++ << 7; + *rp++ = v + *p++; + return rp; +} +static uint8_t * +unpack_7(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + *p++ = (*dp >> 1); + v = ((*dp++ << 6) & 0x7f); *p++ = v + (*dp >> 2); + v = ((*dp++ << 5) & 0x7f); *p++ = v + (*dp >> 3); + v = ((*dp++ << 4) & 0x7f); *p++ = v + (*dp >> 4); + v = ((*dp++ << 3) & 0x7f); *p++ = v + (*dp >> 5); + v = ((*dp++ << 2) & 0x7f); *p++ = v + (*dp >> 6); + v = ((*dp++ << 1) & 0x7f); *p++ = v + (*dp >> 7); + *p++ = (*dp++ & 0x7f); + return dp; +} +static uint8_t * +pack_8(uint32_t *p, uint8_t *rp) +{ + *rp++ = *p++; + *rp++ = *p++; + *rp++ = *p++; + *rp++ = *p++; + *rp++ = *p++; + *rp++ = *p++; + *rp++ = *p++; + *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_8(uint32_t *p, uint8_t *dp) +{ + *p++ = *dp++; + *p++ = *dp++; + *p++ = *dp++; + *p++ = *dp++; + *p++ = *dp++; + *p++ = *dp++; + *p++ = *dp++; + *p++ = *dp++; + return dp; +} +static uint8_t * +pack_9(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_9(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 1; *p++ = v + (*dp >> 7); + v = ((*dp++ << 2) & 0x1ff); *p++ = v + (*dp >> 6); + v = ((*dp++ << 3) & 0x1ff); *p++ = v + (*dp >> 5); + v = ((*dp++ << 4) & 0x1ff); *p++ = v + (*dp >> 4); + v = ((*dp++ << 5) & 0x1ff); *p++ = v + (*dp >> 3); + v = ((*dp++ << 6) & 0x1ff); *p++ = v + (*dp >> 2); + v = ((*dp++ << 7) & 0x1ff); *p++ = v + (*dp >> 1); + v = ((*dp++ << 8) & 0x1ff); *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_10(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_10(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 4) & 0x3ff); *p++ = v + (*dp >> 4); + v = ((*dp++ << 6) & 0x3ff); *p++ = v + (*dp >> 2); + v = ((*dp++ << 8) & 0x3ff); *p++ = v + *dp++; + v = *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 4) & 0x3ff); *p++ = v + (*dp >> 4); + v = ((*dp++ << 6) & 0x3ff); *p++ = v + (*dp >> 2); + v = ((*dp++ << 8) & 0x3ff); *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_11(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_11(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 3; *p++ = v + (*dp >> 5); + v = ((*dp++ << 6) & 0x7ff); *p++ = v + (*dp >> 2); + v = ((*dp++ << 9) & 0x7ff); v += *dp++ << 1; *p++ = v + (*dp >> 7); + v = ((*dp++ << 4) & 0x7ff); *p++ = v + (*dp >> 4); + v = ((*dp++ << 7) & 0x7ff); *p++ = v + (*dp >> 1); + v = ((*dp++ << 10) & 0x7ff); v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 5) & 0x7ff); *p++ = v + (*dp >> 3); + v = ((*dp++ << 8) & 0x7ff); *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_12(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_12(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 8) & 0xfff); *p++ = v + *dp++; + v = *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 8) & 0xfff); *p++ = v + *dp++; + v = *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 8) & 0xfff); *p++ = v + *dp++; + v = *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 8) & 0xfff); *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_13(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_13(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 5; *p++ = v + (*dp >> 3); + v = ((*dp++ << 10) & 0x1fff); v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 7) & 0x1fff); *p++ = v + (*dp >> 1); + v = ((*dp++ << 12) & 0x1fff); v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 9) & 0x1fff); v += *dp++ << 1; *p++ = v + (*dp >> 7); + v = ((*dp++ << 6) & 0x1fff); *p++ = v + (*dp >> 2); + v = ((*dp++ << 11) & 0x1fff); v += *dp++ << 3; *p++ = v + (*dp >> 5); + v = ((*dp++ << 8) & 0x1fff); *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_14(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_14(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 12) & 0x3fff); v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 10) & 0x3fff); v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 8) & 0x3fff); *p++ = v + *dp++; + v = *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 12) & 0x3fff); v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 10) & 0x3fff); v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 8) & 0x3fff); *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_15(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_15(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 7; *p++ = v + (*dp >> 1); + v = ((*dp++ << 14) & 0x7fff); v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 13) & 0x7fff); v += *dp++ << 5; *p++ = v + (*dp >> 3); + v = ((*dp++ << 12) & 0x7fff); v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 11) & 0x7fff); v += *dp++ << 3; *p++ = v + (*dp >> 5); + v = ((*dp++ << 10) & 0x7fff); v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 9) & 0x7fff); v += *dp++ << 1; *p++ = v + (*dp >> 7); + v = ((*dp++ << 8) & 0x7fff); *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_16(uint32_t *p, uint8_t *rp) +{ + *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_16(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 8; *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_17(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_17(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7); + v = ((*dp++ << 10) & 0x1ffff); v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 11) & 0x1ffff); v += *dp++ << 3; *p++ = v + (*dp >> 5); + v = ((*dp++ << 12) & 0x1ffff); v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 13) & 0x1ffff); v += *dp++ << 5; *p++ = v + (*dp >> 3); + v = ((*dp++ << 14) & 0x1ffff); v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 15) & 0x1ffff); v += *dp++ << 7; *p++ = v + (*dp >> 1); + v = ((*dp++ << 16) & 0x1ffff); v += *dp++ << 8; *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_18(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_18(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 12) & 0x3ffff); v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 14) & 0x3ffff); v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 16) & 0x3ffff); v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 12) & 0x3ffff); v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 14) & 0x3ffff); v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 16) & 0x3ffff); v += *dp++ << 8; *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_19(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_19(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 11; v += *dp++ << 3; *p++ = v + (*dp >> 5); + v = ((*dp++ << 14) & 0x7ffff); v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 17) & 0x7ffff); v += *dp++ << 9; v += *dp++ << 1; + *p++ = v + (*dp >> 7); + v = ((*dp++ << 12) & 0x7ffff); v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 15) & 0x7ffff); v += *dp++ << 7; *p++ = v + (*dp >> 1); + v = ((*dp++ << 18) & 0x7ffff); v += *dp++ << 10; v += *dp++ << 2; + *p++ = v + (*dp >> 6); + v = ((*dp++ << 13) & 0x7ffff); v += *dp++ << 5; *p++ = v + (*dp >> 3); + v = ((*dp++ << 16) & 0x7ffff); v += *dp++ << 8; *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_20(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_20(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 16) & 0xfffff); v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 16) & 0xfffff); v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 16) & 0xfffff); v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 16) & 0xfffff); v += *dp++ << 8; *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_21(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_21(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 13; v += *dp++ << 5; *p++ = v + (*dp >> 3); + v = ((*dp++ << 18) & 0x1fffff); v += *dp++ << 10; v += *dp++ << 2; + *p++ = v + (*dp >> 6); + v = ((*dp++ << 15) & 0x1fffff); v += *dp++ << 7; *p++ = v + (*dp >> 1); + v = ((*dp++ << 20) & 0x1fffff); v += *dp++ << 12; v += *dp++ << 4; + *p++ = v + (*dp >> 4); + v = ((*dp++ << 17) & 0x1fffff); v += *dp++ << 9; v += *dp++ << 1; + *p++ = v + (*dp >> 7); + v = ((*dp++ << 14) & 0x1fffff); v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 19) & 0x1fffff); v += *dp++ << 11; v += *dp++ << 3; + *p++ = v + (*dp >> 5); + v = ((*dp++ << 16) & 0x1fffff); v += *dp++ << 8; *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_22(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_22(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 20) & 0x3fffff); v += *dp++ << 12; v += *dp++ << 4; + *p++ = v + (*dp >> 4); + v = ((*dp++ << 18) & 0x3fffff); v += *dp++ << 10; v += *dp++ << 2; + *p++ = v + (*dp >> 6); + v = ((*dp++ << 16) & 0x3fffff); v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 20) & 0x3fffff); v += *dp++ << 12; v += *dp++ << 4; + *p++ = v + (*dp >> 4); + v = ((*dp++ << 18) & 0x3fffff); v += *dp++ << 10; v += *dp++ << 2; + *p++ = v + (*dp >> 6); + v = ((*dp++ << 16) & 0x3fffff); v += *dp++ << 8; *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_23(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 21); *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_23(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 15; v += *dp++ << 7; *p++ = v + (*dp >> 1); + v = ((*dp++ << 22) & 0x7fffff); v += *dp++ << 14; v += *dp++ << 6; + *p++ = v + (*dp >> 2); + v = ((*dp++ << 21) & 0x7fffff); v += *dp++ << 13; v += *dp++ << 5; + *p++ = v + (*dp >> 3); + v = ((*dp++ << 20) & 0x7fffff); v += *dp++ << 12; v += *dp++ << 4; + *p++ = v + (*dp >> 4); + v = ((*dp++ << 19) & 0x7fffff); v += *dp++ << 11; v += *dp++ << 3; + *p++ = v + (*dp >> 5); + v = ((*dp++ << 18) & 0x7fffff); v += *dp++ << 10; v += *dp++ << 2; + *p++ = v + (*dp >> 6); + v = ((*dp++ << 17) & 0x7fffff); v += *dp++ << 9; v += *dp++ << 1; + *p++ = v + (*dp >> 7); + v = ((*dp++ << 16) & 0x7fffff); v += *dp++ << 8; *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_24(uint32_t *p, uint8_t *rp) +{ + *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_24(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_25(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 17); *rp++ = (*p >> 9); *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 21); *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 23); *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_25(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 17; v += *dp++ << 9; v += *dp++ << 1; *p++ = v + (*dp >> 7); + v = ((*dp++ << 18) & 0x1ffffff); v += *dp++ << 10; v += *dp++ << 2; + *p++ = v + (*dp >> 6); + v = ((*dp++ << 19) & 0x1ffffff); v += *dp++ << 11; v += *dp++ << 3; + *p++ = v + (*dp >> 5); + v = ((*dp++ << 20) & 0x1ffffff); v += *dp++ << 12; v += *dp++ << 4; + *p++ = v + (*dp >> 4); + v = ((*dp++ << 21) & 0x1ffffff); v += *dp++ << 13; v += *dp++ << 5; + *p++ = v + (*dp >> 3); + v = ((*dp++ << 22) & 0x1ffffff); v += *dp++ << 14; v += *dp++ << 6; + *p++ = v + (*dp >> 2); + v = ((*dp++ << 23) & 0x1ffffff); v += *dp++ << 15; v += *dp++ << 7; + *p++ = v + (*dp >> 1); + v = ((*dp++ << 24) & 0x1ffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_26(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 18); *rp++ = (*p >> 10); *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_26(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 18; v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 20) & 0x3ffffff); v += *dp++ << 12; v += *dp++ << 4; + *p++ = v + (*dp >> 4); + v = ((*dp++ << 22) & 0x3ffffff); v += *dp++ << 14; v += *dp++ << 6; + *p++ = v + (*dp >> 2); + v = ((*dp++ << 24) & 0x3ffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + v = *dp++ << 18; v += *dp++ << 10; v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 20) & 0x3ffffff); v += *dp++ << 12; v += *dp++ << 4; + *p++ = v + (*dp >> 4); + v = ((*dp++ << 22) & 0x3ffffff); v += *dp++ << 14; v += *dp++ << 6; + *p++ = v + (*dp >> 2); + v = ((*dp++ << 24) & 0x3ffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_27(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 19); *rp++ = (*p >> 11); *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 25); *rp++ = (*p >> 17); *rp++ = (*p >> 9); + *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 23); *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); + *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 21); *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_27(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 19; v += *dp++ << 11; v += *dp++ << 3; *p++ = v + (*dp >> 5); + v = ((*dp++ << 22) & 0x7ffffff); v += *dp++ << 14; v += *dp++ << 6; + *p++ = v + (*dp >> 2); + v = ((*dp++ << 25) & 0x7ffffff); v += *dp++ << 17; v += *dp++ << 9; + v += *dp++ << 1; *p++ = v + (*dp >> 7); + v = ((*dp++ << 20) & 0x7ffffff); v += *dp++ << 12; v += *dp++ << 4; + *p++ = v + (*dp >> 4); + v = ((*dp++ << 23) & 0x7ffffff); v += *dp++ << 15; v += *dp++ << 7; + *p++ = v + (*dp >> 1); + v = ((*dp++ << 26) & 0x7ffffff); v += *dp++ << 18; v += *dp++ << 10; + v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 21) & 0x7ffffff); v += *dp++ << 13; v += *dp++ << 5; + *p++ = v + (*dp >> 3); + v = ((*dp++ << 24) & 0x7ffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_28(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 20); *rp++ = (*p >> 12); *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_28(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 24) & 0xfffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + v = *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 24) & 0xfffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + v = *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 24) & 0xfffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + v = *dp++ << 20; v += *dp++ << 12; v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 24) & 0xfffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_29(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 21); *rp++ = (*p >> 13); *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); + *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 23); *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 28); *rp++ = (*p >> 20); *rp++ = (*p >> 12); + *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 25); *rp++ = (*p >> 17); *rp++ = (*p >> 9); + *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 27); *rp++ = (*p >> 19); *rp++ = (*p >> 11); + *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_29(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 21; v += *dp++ << 13; v += *dp++ << 5; *p++ = v + (*dp >> 3); + v = ((*dp++ << 26) & 0x1fffffff); v += *dp++ << 18; v += *dp++ << 10; + v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 23) & 0x1fffffff); v += *dp++ << 15; v += *dp++ << 7; + *p++ = v + (*dp >> 1); + v = ((*dp++ << 28) & 0x1fffffff); v += *dp++ << 20; v += *dp++ << 12; + v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 25) & 0x1fffffff); v += *dp++ << 17; v += *dp++ << 9; + v += *dp++ << 1; *p++ = v + (*dp >> 7); + v = ((*dp++ << 22) & 0x1fffffff); v += *dp++ << 14; v += *dp++ << 6; + *p++ = v + (*dp >> 2); + v = ((*dp++ << 27) & 0x1fffffff); v += *dp++ << 19; v += *dp++ << 11; + v += *dp++ << 3; *p++ = v + (*dp >> 5); + v = ((*dp++ << 24) & 0x1fffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_30(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 28); *rp++ = (*p >> 20); *rp++ = (*p >> 12); + *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); + *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 22); *rp++ = (*p >> 14); *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 28); *rp++ = (*p >> 20); *rp++ = (*p >> 12); + *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); + *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); + *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_30(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 22; v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 28) & 0x3fffffff); v += *dp++ << 20; v += *dp++ << 12; + v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 26) & 0x3fffffff); v += *dp++ << 18; v += *dp++ << 10; + v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 24) & 0x3fffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + v = *dp++ << 22; v += *dp++ << 14; v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 28) & 0x3fffffff); v += *dp++ << 20; v += *dp++ << 12; + v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 26) & 0x3fffffff); v += *dp++ << 18; v += *dp++ << 10; + v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 24) & 0x3fffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_31(uint32_t *p, uint8_t *rp) +{ + uint8_t v; + *rp++ = (*p >> 23); *rp++ = (*p >> 15); *rp++ = (*p >> 7); v = *p++ << 1; + *rp++ = v + (*p >> 30); *rp++ = (*p >> 22); *rp++ = (*p >> 14); + *rp++ = (*p >> 6); v = *p++ << 2; + *rp++ = v + (*p >> 29); *rp++ = (*p >> 21); *rp++ = (*p >> 13); + *rp++ = (*p >> 5); v = *p++ << 3; + *rp++ = v + (*p >> 28); *rp++ = (*p >> 20); *rp++ = (*p >> 12); + *rp++ = (*p >> 4); v = *p++ << 4; + *rp++ = v + (*p >> 27); *rp++ = (*p >> 19); *rp++ = (*p >> 11); + *rp++ = (*p >> 3); v = *p++ << 5; + *rp++ = v + (*p >> 26); *rp++ = (*p >> 18); *rp++ = (*p >> 10); + *rp++ = (*p >> 2); v = *p++ << 6; + *rp++ = v + (*p >> 25); *rp++ = (*p >> 17); *rp++ = (*p >> 9); + *rp++ = (*p >> 1); v = *p++ << 7; + *rp++ = v + (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); + *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_31(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 23; v += *dp++ << 15; v += *dp++ << 7; *p++ = v + (*dp >> 1); + v = ((*dp++ << 30) & 0x7fffffff); v += *dp++ << 22; v += *dp++ << 14; + v += *dp++ << 6; *p++ = v + (*dp >> 2); + v = ((*dp++ << 29) & 0x7fffffff); v += *dp++ << 21; v += *dp++ << 13; + v += *dp++ << 5; *p++ = v + (*dp >> 3); + v = ((*dp++ << 28) & 0x7fffffff); v += *dp++ << 20; v += *dp++ << 12; + v += *dp++ << 4; *p++ = v + (*dp >> 4); + v = ((*dp++ << 27) & 0x7fffffff); v += *dp++ << 19; v += *dp++ << 11; + v += *dp++ << 3; *p++ = v + (*dp >> 5); + v = ((*dp++ << 26) & 0x7fffffff); v += *dp++ << 18; v += *dp++ << 10; + v += *dp++ << 2; *p++ = v + (*dp >> 6); + v = ((*dp++ << 25) & 0x7fffffff); v += *dp++ << 17; v += *dp++ << 9; + v += *dp++ << 1; *p++ = v + (*dp >> 7); + v = ((*dp++ << 24) & 0x7fffffff); v += *dp++ << 16; v += *dp++ << 8; + *p++ = v + *dp++; + return dp; +} +static uint8_t * +pack_32(uint32_t *p, uint8_t *rp) +{ + *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + *rp++ = (*p >> 24); *rp++ = (*p >> 16); *rp++ = (*p >> 8); *rp++ = *p++; + return rp; +} +static uint8_t * +unpack_32(uint32_t *p, uint8_t *dp) +{ + uint32_t v; + v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + v = *dp++ << 24; v += *dp++ << 16; v += *dp++ << 8; *p++ = v + *dp++; + return dp; +} +/* */ + +static uint8_t * +pack_(uint32_t *p, uint32_t i, int w, uint8_t *rp) +{ + while (i >= 8) { + switch (w) { + case 0 : break; + case 1 : rp = pack_1(p, rp); break; + case 2 : rp = pack_2(p, rp); break; + case 3 : rp = pack_3(p, rp); break; + case 4 : rp = pack_4(p, rp); break; + case 5 : rp = pack_5(p, rp); break; + case 6 : rp = pack_6(p, rp); break; + case 7 : rp = pack_7(p, rp); break; + case 8 : rp = pack_8(p, rp); break; + case 9 : rp = pack_9(p, rp); break; + case 10 : rp = pack_10(p, rp); break; + case 11 : rp = pack_11(p, rp); break; + case 12 : rp = pack_12(p, rp); break; + case 13 : rp = pack_13(p, rp); break; + case 14 : rp = pack_14(p, rp); break; + case 15 : rp = pack_15(p, rp); break; + case 16 : rp = pack_16(p, rp); break; + case 17 : rp = pack_17(p, rp); break; + case 18 : rp = pack_18(p, rp); break; + case 19 : rp = pack_19(p, rp); break; + case 20 : rp = pack_20(p, rp); break; + case 21 : rp = pack_21(p, rp); break; + case 22 : rp = pack_22(p, rp); break; + case 23 : rp = pack_23(p, rp); break; + case 24 : rp = pack_24(p, rp); break; + case 25 : rp = pack_25(p, rp); break; + case 26 : rp = pack_26(p, rp); break; + case 27 : rp = pack_27(p, rp); break; + case 28 : rp = pack_28(p, rp); break; + case 29 : rp = pack_29(p, rp); break; + case 30 : rp = pack_30(p, rp); break; + case 31 : rp = pack_31(p, rp); break; + case 32 : rp = pack_32(p, rp); break; + } + p += 8; + i -= 8; + } + { + int b; + uint8_t v; + uint32_t *pe = p + i; + for (b = 8 - w, v = 0; p < pe;) { + if (b > 0) { + v += *p++ << b; + b -= w; + } else if (b < 0) { + *rp++ = v + (*p >> -b); + b += 8; + v = 0; + } else { + *rp++ = v + *p++; + b = 8 - w; + v = 0; + } + } + if (b + w != 8) { *rp++ = v; } + return rp; + } +} + +static uint8_t * +pack(uint32_t *p, uint32_t i, uint8_t *freq, uint8_t *rp) +{ + int32_t k, w; + uint8_t ebuf[UNIT_SIZE], *ep = ebuf; + uint32_t s, *pe = p + i, r, th = i - (i >> 3); + for (w = 0, s = 0; w <= 32; w++) { + if ((s += freq[w]) >= th) { break; } + } + if (i == s) { + *rp++ = w; + return pack_(p, i, w, rp); + } + r = 1 << w; + *rp++ = w + 0x80; + *rp++ = i - s; + if (r >= UNIT_SIZE) { + uint32_t first, *last = &first; + for (k = 0; p < pe; p++, k++) { + if (*p >= r) { + GRN_B_ENC(*p - r, ep); + *last = k; + last = p; + } + } + *last = 0; + *rp++ = (uint8_t) first; + } else { + for (k = 0; p < pe; p++, k++) { + if (*p >= r) { + *ep++ = k; + GRN_B_ENC(*p - r, ep); + *p = 0; + } + } + } + rp = pack_(p - i, i, w, rp); + grn_memcpy(rp, ebuf, ep - ebuf); + return rp + (ep - ebuf); +} + +int +grn_p_enc(grn_ctx *ctx, uint32_t *data, uint32_t data_size, uint8_t **res) +{ + uint8_t *rp, freq[33]; + uint32_t j, *dp, *dpe, d, w, buf[UNIT_SIZE]; + *res = rp = GRN_MALLOC(data_size * sizeof(uint32_t) * 2); + GRN_B_ENC(data_size, rp); + memset(freq, 0, 33); + for (j = 0, dp = data, dpe = dp + data_size; dp < dpe; j++, dp++) { + if (j == UNIT_SIZE) { + rp = pack(buf, j, freq, rp); + memset(freq, 0, 33); + j = 0; + } + if ((d = buf[j] = *dp)) { + GRN_BIT_SCAN_REV(d, w); + freq[w + 1]++; + } else { + freq[0]++; + } + } + if (j) { rp = pack(buf, j, freq, rp); } + return rp - *res; +} + +#define USE_P_ENC (1<<0) /* Use PForDelta */ +#define CUT_OFF (1<<1) /* Deprecated */ +#define ODD (1<<2) /* Variable size data */ + +typedef struct { + uint32_t *data; + uint32_t data_size; + uint32_t flags; +} datavec; + +static grn_rc +datavec_reset(grn_ctx *ctx, datavec *dv, uint32_t dvlen, + size_t unitsize, size_t totalsize) +{ + int i; + if (!dv[0].data || dv[dvlen].data < dv[0].data + totalsize) { + if (dv[0].data) { GRN_FREE(dv[0].data); } + if (!(dv[0].data = GRN_MALLOC(totalsize * sizeof(uint32_t)))) { + MERR("[ii][data-vector][reset] failed to allocate data: " + "length:<%u>, " + "unit-size:<%" GRN_FMT_SIZE ">, " + "total-size:<%" GRN_FMT_SIZE ">", + dvlen, + unitsize, + totalsize); + return ctx->rc; + } + dv[dvlen].data = dv[0].data + totalsize; + } + for (i = 1; i < dvlen; i++) { + dv[i].data = dv[i - 1].data + unitsize; + } + return GRN_SUCCESS; +} + +static grn_rc +datavec_init(grn_ctx *ctx, datavec *dv, uint32_t dvlen, + size_t unitsize, size_t totalsize) +{ + int i; + if (!totalsize) { + memset(dv, 0, sizeof(datavec) * (dvlen + 1)); + return GRN_SUCCESS; + } + if (!(dv[0].data = GRN_MALLOC(totalsize * sizeof(uint32_t)))) { + MERR("[ii][data-vector][init] failed to allocate data: " + "length:<%u>, " + "unit-size:<%" GRN_FMT_SIZE ">, " + "total-size:<%" GRN_FMT_SIZE ">", + dvlen, + unitsize, + totalsize); + return ctx->rc; + } + dv[dvlen].data = dv[0].data + totalsize; + for (i = 1; i < dvlen; i++) { + dv[i].data = dv[i - 1].data + unitsize; + } + return GRN_SUCCESS; +} + +static void +datavec_fin(grn_ctx *ctx, datavec *dv) +{ + if (dv[0].data) { GRN_FREE(dv[0].data); } +} + +size_t +grn_p_encv(grn_ctx *ctx, datavec *dv, uint32_t dvlen, uint8_t *res) +{ + uint8_t *rp = res, freq[33]; + uint32_t pgap, usep, l, df, data_size, *dp, *dpe; + if (!dvlen || !(df = dv[0].data_size)) { return 0; } + for (usep = 0, data_size = 0, l = 0; l < dvlen; l++) { + uint32_t dl = dv[l].data_size; + if (dl < df || ((dl > df) && (l != dvlen - 1))) { + /* invalid argument */ + return 0; + } + usep += (dv[l].flags & USE_P_ENC) << l; + data_size += dl; + } + pgap = data_size - df * dvlen; + if (!usep) { + GRN_B_ENC((df << 1) + 1, rp); + for (l = 0; l < dvlen; l++) { + for (dp = dv[l].data, dpe = dp + dv[l].data_size; dp < dpe; dp++) { + GRN_B_ENC(*dp, rp); + } + } + } else { + uint32_t buf[UNIT_SIZE]; + GRN_B_ENC((usep << 1), rp); + GRN_B_ENC(df, rp); + if (dv[dvlen - 1].flags & ODD) { + GRN_B_ENC(pgap, rp); + } else { + GRN_ASSERT(!pgap); + } + for (l = 0; l < dvlen; l++) { + dp = dv[l].data; + dpe = dp + dv[l].data_size; + if ((dv[l].flags & USE_P_ENC)) { + uint32_t j = 0, d; + memset(freq, 0, 33); + while (dp < dpe) { + if (j == UNIT_SIZE) { + rp = pack(buf, j, freq, rp); + memset(freq, 0, 33); + j = 0; + } + if ((d = buf[j++] = *dp++)) { + uint32_t w; + GRN_BIT_SCAN_REV(d, w); + freq[w + 1]++; + } else { + freq[0]++; + } + } + if (j) { rp = pack(buf, j, freq, rp); } + } else { + while (dp < dpe) { GRN_B_ENC(*dp++, rp); } + } + } + } + return rp - res; +} + +#define GRN_B_DEC_CHECK(v,p,pe) do { \ + uint8_t *_p = (uint8_t *)p; \ + uint32_t _v; \ + if (_p >= pe) { return 0; } \ + _v = *_p++; \ + switch (_v >> 4) { \ + case 0x08 : \ + if (_v == 0x8f) { \ + if (_p + sizeof(uint32_t) > pe) { return 0; } \ + grn_memcpy(&_v, _p, sizeof(uint32_t)); \ + _p += sizeof(uint32_t); \ + } \ + break; \ + case 0x09 : \ + if (_p + 3 > pe) { return 0; } \ + _v = (_v - 0x90) * 0x100 + *_p++; \ + _v = _v * 0x100 + *_p++; \ + _v = _v * 0x100 + *_p++ + 0x20408f; \ + break; \ + case 0x0a : \ + case 0x0b : \ + if (_p + 2 > pe) { return 0; } \ + _v = (_v - 0xa0) * 0x100 + *_p++; \ + _v = _v * 0x100 + *_p++ + 0x408f; \ + break; \ + case 0x0c : \ + case 0x0d : \ + case 0x0e : \ + case 0x0f : \ + if (_p + 1 > pe) { return 0; } \ + _v = (_v - 0xc0) * 0x100 + *_p++ + 0x8f; \ + break; \ + } \ + v = _v; \ + p = _p; \ +} while (0) + +static uint8_t * +unpack(uint8_t *dp, uint8_t *dpe, int i, uint32_t *rp) +{ + uint8_t ne = 0, k = 0, w = *dp++; + uint32_t m, *p = rp; + if (w & 0x80) { + ne = *dp++; + w -= 0x80; + m = (1 << w) - 1; + if (m >= UNIT_MASK) { k = *dp++; } + } else { + m = (1 << w) - 1; + } + if (w) { + while (i >= 8) { + if (dp + w > dpe) { return NULL; } + switch (w) { + case 1 : dp = unpack_1(p, dp); break; + case 2 : dp = unpack_2(p, dp); break; + case 3 : dp = unpack_3(p, dp); break; + case 4 : dp = unpack_4(p, dp); break; + case 5 : dp = unpack_5(p, dp); break; + case 6 : dp = unpack_6(p, dp); break; + case 7 : dp = unpack_7(p, dp); break; + case 8 : dp = unpack_8(p, dp); break; + case 9 : dp = unpack_9(p, dp); break; + case 10 : dp = unpack_10(p, dp); break; + case 11 : dp = unpack_11(p, dp); break; + case 12 : dp = unpack_12(p, dp); break; + case 13 : dp = unpack_13(p, dp); break; + case 14 : dp = unpack_14(p, dp); break; + case 15 : dp = unpack_15(p, dp); break; + case 16 : dp = unpack_16(p, dp); break; + case 17 : dp = unpack_17(p, dp); break; + case 18 : dp = unpack_18(p, dp); break; + case 19 : dp = unpack_19(p, dp); break; + case 20 : dp = unpack_20(p, dp); break; + case 21 : dp = unpack_21(p, dp); break; + case 22 : dp = unpack_22(p, dp); break; + case 23 : dp = unpack_23(p, dp); break; + case 24 : dp = unpack_24(p, dp); break; + case 25 : dp = unpack_25(p, dp); break; + case 26 : dp = unpack_26(p, dp); break; + case 27 : dp = unpack_27(p, dp); break; + case 28 : dp = unpack_28(p, dp); break; + case 29 : dp = unpack_29(p, dp); break; + case 30 : dp = unpack_30(p, dp); break; + case 31 : dp = unpack_31(p, dp); break; + case 32 : dp = unpack_32(p, dp); break; + } + i -= 8; + p += 8; + } + { + int b; + uint32_t v, *pe; + for (b = 8 - w, v = 0, pe = p + i; p < pe && dp < dpe;) { + if (b > 0) { + *p++ = v + ((*dp >> b) & m); + b -= w; + v = 0; + } else if (b < 0) { + v += (*dp++ << -b) & m; + b += 8; + } else { + *p++ = v + (*dp++ & m); + b = 8 - w; + v = 0; + } + } + if (b + w != 8) { dp++; } + } + } else { + memset(p, 0, sizeof(uint32_t) * i); + } + if (ne) { + if (m >= UNIT_MASK) { + uint32_t *pp; + while (ne--) { + pp = &rp[k]; + k = *pp; + GRN_B_DEC_CHECK(*pp, dp, dpe); + *pp += (m + 1); + } + } else { + while (ne--) { + k = *dp++; + GRN_B_DEC_CHECK(rp[k], dp, dpe); + rp[k] += (m + 1); + } + } + } + return dp; +} + +int +grn_p_dec(grn_ctx *ctx, uint8_t *data, uint32_t data_size, uint32_t nreq, uint32_t **res) +{ + uint8_t *dp = data, *dpe = data + data_size; + uint32_t rest, orig_size, *rp, *rpe; + GRN_B_DEC(orig_size, dp); + if (!orig_size) { + if (!nreq || nreq > data_size) { nreq = data_size; } + if ((*res = rp = GRN_MALLOC(nreq * 4))) { + for (rpe = rp + nreq; dp < data + data_size && rp < rpe; rp++) { + GRN_B_DEC(*rp, dp); + } + } + return rp - *res; + } else { + if (!(*res = rp = GRN_MALLOC(orig_size * sizeof(uint32_t)))) { + return 0; + } + if (!nreq || nreq > orig_size) { nreq = orig_size; } + for (rest = nreq; rest >= UNIT_SIZE; rest -= UNIT_SIZE) { + if (!(dp = unpack(dp, dpe, UNIT_SIZE, rp))) { return 0; } + rp += UNIT_SIZE; + } + if (rest) { if (!(dp = unpack(dp, dpe, rest, rp))) { return 0; } } + GRN_ASSERT(data + data_size == dp); + return nreq; + } +} + +int +grn_p_decv(grn_ctx *ctx, uint8_t *data, uint32_t data_size, datavec *dv, uint32_t dvlen) +{ + size_t size; + uint32_t df, l, i, *rp, nreq; + uint8_t *dp = data, *dpe = data + data_size; + if (!data_size) { + dv[0].data_size = 0; + return 0; + } + for (nreq = 0; nreq < dvlen; nreq++) { + if (dv[nreq].flags & CUT_OFF) { break; } + } + if (!nreq) { return 0; } + GRN_B_DEC_CHECK(df, dp, dpe); + if ((df & 1)) { + df >>= 1; + size = nreq == dvlen ? data_size : df * nreq; + if (dv[dvlen].data < dv[0].data + size) { + if (dv[0].data) { GRN_FREE(dv[0].data); } + if (!(rp = GRN_MALLOC(size * sizeof(uint32_t)))) { return 0; } + dv[dvlen].data = rp + size; + } else { + rp = dv[0].data; + } + for (l = 0; l < dvlen; l++) { + if (dv[l].flags & CUT_OFF) { break; } + dv[l].data = rp; + if (l < dvlen - 1) { + for (i = 0; i < df; i++, rp++) { GRN_B_DEC_CHECK(*rp, dp, dpe); } + } else { + for (i = 0; dp < dpe; i++, rp++) { GRN_B_DEC_CHECK(*rp, dp, dpe); } + } + dv[l].data_size = i; + } + } else { + uint32_t n, rest, usep = df >> 1; + GRN_B_DEC_CHECK(df, dp, dpe); + if (dv[dvlen -1].flags & ODD) { + GRN_B_DEC_CHECK(rest, dp, dpe); + } else { + rest = 0; + } + size = df * nreq + (nreq == dvlen ? rest : 0); + if (dv[dvlen].data < dv[0].data + size) { + if (dv[0].data) { GRN_FREE(dv[0].data); } + if (!(rp = GRN_MALLOC(size * sizeof(uint32_t)))) { return 0; } + dv[dvlen].data = rp + size; + } else { + rp = dv[0].data; + } + for (l = 0; l < dvlen; l++) { + if (dv[l].flags & CUT_OFF) { break; } + dv[l].data = rp; + dv[l].data_size = n = (l < dvlen - 1) ? df : df + rest; + if (usep & (1 << l)) { + for (; n >= UNIT_SIZE; n -= UNIT_SIZE) { + if (!(dp = unpack(dp, dpe, UNIT_SIZE, rp))) { return 0; } + rp += UNIT_SIZE; + } + if (n) { + if (!(dp = unpack(dp, dpe, n, rp))) { return 0; } + rp += n; + } + dv[l].flags |= USE_P_ENC; + } else { + for (; n; n--, rp++) { + GRN_B_DEC_CHECK(*rp, dp, dpe); + } + } + } + GRN_ASSERT(dp == dpe); + if (dp != dpe) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "data_size=%d, %" GRN_FMT_LLD, + data_size, (long long int)(dpe - dp)); + } + } + return rp - dv[0].data; +} + +int +grn_b_enc(grn_ctx *ctx, uint32_t *data, uint32_t data_size, uint8_t **res) +{ + uint8_t *rp; + uint32_t *dp, i; + *res = rp = GRN_MALLOC(data_size * sizeof(uint32_t) * 2); + GRN_B_ENC(data_size, rp); + for (i = data_size, dp = data; i; i--, dp++) { + GRN_B_ENC(*dp, rp); + } + return rp - *res; +} + +int +grn_b_dec(grn_ctx *ctx, uint8_t *data, uint32_t data_size, uint32_t **res) +{ + uint32_t i, *rp, orig_size; + uint8_t *dp = data; + GRN_B_DEC(orig_size, dp); + *res = rp = GRN_MALLOC(orig_size * sizeof(uint32_t)); + for (i = orig_size; i; i--, rp++) { + GRN_B_DEC(*rp, dp); + } + return orig_size; +} + +/* buffer */ + +typedef struct { + uint32_t tid; + uint32_t size_in_chunk; + uint32_t pos_in_chunk; + uint16_t size_in_buffer; + uint16_t pos_in_buffer; +} buffer_term; + +typedef struct { + uint16_t step; + uint16_t jump; +} buffer_rec; + +typedef struct { + uint32_t chunk; + uint32_t chunk_size; + uint32_t buffer_free; + uint16_t nterms; + uint16_t nterms_void; +} buffer_header; + +struct grn_ii_buffer { + buffer_header header; + buffer_term terms[(S_SEGMENT - sizeof(buffer_header))/sizeof(buffer_term)]; +}; + +typedef struct grn_ii_buffer buffer; + +inline static uint32_t +buffer_open(grn_ctx *ctx, grn_ii *ii, uint32_t pos, buffer_term **bt, buffer **b) +{ + byte *p = NULL; + uint16_t lseg = (uint16_t) (LSEG(pos)); + uint32_t pseg = ii->header->binfo[lseg]; + if (pseg != GRN_II_PSEG_NOT_ASSIGNED) { + GRN_IO_SEG_REF(ii->seg, pseg, p); + if (!p) { return GRN_II_PSEG_NOT_ASSIGNED; } + if (b) { *b = (buffer *)p; } + if (bt) { *bt = (buffer_term *)(p + LPOS(pos)); } + } + return pseg; +} + +inline static grn_rc +buffer_close(grn_ctx *ctx, grn_ii *ii, uint32_t pseg) +{ + if (pseg >= ii->seg->header->max_segment) { + GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid pseg buffer_close(%d)", pseg); + return GRN_INVALID_ARGUMENT; + } + GRN_IO_SEG_UNREF(ii->seg, pseg); + return GRN_SUCCESS; +} + +typedef struct { + uint32_t rid; + uint32_t sid; +} docid; + +#define BUFFER_REC_DEL(r) ((r)->jump = 1) +#define BUFFER_REC_DELETED(r) ((r)->jump == 1) + +#define BUFFER_REC_AT(b,pos) ((buffer_rec *)(b) + (pos)) +#define BUFFER_REC_POS(b,rec) ((uint16_t)((rec) - (buffer_rec *)(b))) + +inline static void +buffer_term_dump(grn_ctx *ctx, grn_ii *ii, buffer *b, buffer_term *bt) +{ + int pos, rid, sid; + uint8_t *p; + buffer_rec *r; + + if (!grn_logger_pass(ctx, GRN_LOG_DEBUG)) { + return; + } + + GRN_LOG(ctx, GRN_LOG_DEBUG, + "b=(%x %u %u %u)", b->header.chunk, b->header.chunk_size, + b->header.buffer_free, b->header.nterms); + GRN_LOG(ctx, GRN_LOG_DEBUG, + "bt=(%u %u %u %u %u)", bt->tid, bt->size_in_chunk, bt->pos_in_chunk, + bt->size_in_buffer, bt->pos_in_buffer); + for (pos = bt->pos_in_buffer; pos; pos = r->step) { + r = BUFFER_REC_AT(b, pos); + p = GRN_NEXT_ADDR(r); + GRN_B_DEC(rid, p); + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + GRN_B_DEC(sid, p); + } else { + sid = 1; + } + GRN_LOG(ctx, GRN_LOG_DEBUG, + "%d=(%d:%d),(%d:%d)", pos, r->jump, r->step, rid, sid); + } +} + +inline static grn_rc +check_jump(grn_ctx *ctx, grn_ii *ii, buffer *b, buffer_rec *r, int j) +{ + uint16_t i = BUFFER_REC_POS(b, r); + uint8_t *p; + buffer_rec *r2; + docid id, id2; + if (!j) { return GRN_SUCCESS; } + p = GRN_NEXT_ADDR(r); + GRN_B_DEC(id.rid, p); + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + GRN_B_DEC(id.sid, p); + } else { + id.sid = 1; + } + if (j == 1) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "deleting! %d(%d:%d)", i, id.rid, id.sid); + return GRN_SUCCESS; + } + r2 = BUFFER_REC_AT(b, j); + p = GRN_NEXT_ADDR(r2); + GRN_B_DEC(id2.rid, p); + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + GRN_B_DEC(id2.sid, p); + } else { + id2.sid = 1; + } + if (r2->step == i) { + GRN_LOG(ctx, GRN_LOG_EMERG, "cycle! %d(%d:%d)<->%d(%d:%d)", + i, id.rid, id.sid, j, id2.rid, id2.sid); + return GRN_FILE_CORRUPT; + } + if (id2.rid < id.rid || (id2.rid == id.rid && id2.sid <= id.sid)) { + GRN_LOG(ctx, GRN_LOG_CRIT, + "invalid jump! %d(%d:%d)(%d:%d)->%d(%d:%d)(%d:%d)", + i, r->jump, r->step, id.rid, id.sid, j, r2->jump, r2->step, + id2.rid, id2.sid); + return GRN_FILE_CORRUPT; + } + return GRN_SUCCESS; +} + +inline static grn_rc +set_jump_r(grn_ctx *ctx, grn_ii *ii, buffer *b, buffer_rec *from, int to) +{ + int i, j, max_jump = 100; + buffer_rec *r, *r2; + for (r = from, j = to; j > 1 && max_jump--; r = BUFFER_REC_AT(b, r->step)) { + r2 = BUFFER_REC_AT(b, j); + if (r == r2) { break; } + if (BUFFER_REC_DELETED(r2)) { break; } + if (j == (i = r->jump)) { break; } + if (j == r->step) { break; } + if (check_jump(ctx, ii, b, r, j)) { + ERR(GRN_FILE_CORRUPT, "check_jump failed"); + return ctx->rc; + } + r->jump = j; + j = i; + if (!r->step) { return GRN_FILE_CORRUPT; } + } + return GRN_SUCCESS; +} + +#define GET_NUM_BITS(x,n) do {\ + n = x;\ + n = (n & 0x55555555) + ((n >> 1) & 0x55555555);\ + n = (n & 0x33333333) + ((n >> 2) & 0x33333333);\ + n = (n & 0x0F0F0F0F) + ((n >> 4) & 0x0F0F0F0F);\ + n = (n & 0x00FF00FF) + ((n >> 8) & 0x00FF00FF);\ + n = (n & 0x0000FFFF) + ((n >>16) & 0x0000FFFF);\ +} while (0) + +inline static grn_rc +buffer_put(grn_ctx *ctx, grn_ii *ii, buffer *b, buffer_term *bt, + buffer_rec *rnew, uint8_t *bs, grn_ii_updspec *u, int size) +{ + uint8_t *p; + docid id_curr = {0, 0}, id_start = {0, 0}, id_post = {0, 0}; + buffer_rec *r_curr, *r_start = NULL; + uint16_t last = 0, *lastp = &bt->pos_in_buffer, pos = BUFFER_REC_POS(b, rnew); + int vdelta = 0, delta, delta0 = 0, vhops = 0, nhops = 0, reset = 1; + grn_memcpy(GRN_NEXT_ADDR(rnew), bs, size - sizeof(buffer_rec)); + for (;;) { + if (!*lastp) { + rnew->step = 0; + rnew->jump = 0; + // smb_wmb(); + *lastp = pos; + if (bt->size_in_buffer++ > 1) { + buffer_rec *rhead = BUFFER_REC_AT(b, bt->pos_in_buffer); + rhead->jump = pos; + if (!(bt->size_in_buffer & 1)) { + int n; + buffer_rec *r = BUFFER_REC_AT(b, rhead->step), *r2; + GET_NUM_BITS(bt->size_in_buffer, n); + while (n-- && (r->jump > 1)) { + r2 = BUFFER_REC_AT(b, r->jump); + if (BUFFER_REC_DELETED(r2)) { break; } + r = r2; + } + if (r != rnew) { set_jump_r(ctx, ii, b, r, last); } + } + } + break; + } + r_curr = BUFFER_REC_AT(b, *lastp); + p = GRN_NEXT_ADDR(r_curr); + GRN_B_DEC(id_curr.rid, p); + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + GRN_B_DEC(id_curr.sid, p); + } else { + id_curr.sid = 1; + } + if (id_curr.rid < id_post.rid || + (id_curr.rid == id_post.rid && id_curr.sid < id_post.sid)) { + { + DEFINE_NAME(ii); + CRIT(GRN_FILE_CORRUPT, + "[ii][buffer][put] loop is found: " + "<%.*s>: " + "(%d:%d)->(%d:%d)", + name_size, name, + id_post.rid, id_post.sid, id_curr.rid, id_curr.sid); + } + buffer_term_dump(ctx, ii, b, bt); + bt->pos_in_buffer = 0; + bt->size_in_buffer = 0; + lastp = &bt->pos_in_buffer; + continue; + } + id_post.rid = id_curr.rid; + id_post.sid = id_curr.sid; + if (u->rid < id_curr.rid || (u->rid == id_curr.rid && u->sid <= id_curr.sid)) { + uint16_t step = *lastp, jump = r_curr->jump; + if (u->rid == id_curr.rid) { + if (u->sid == 0) { + while (id_curr.rid == u->rid) { + BUFFER_REC_DEL(r_curr); + if (!(step = r_curr->step)) { break; } + r_curr = BUFFER_REC_AT(b, step); + p = GRN_NEXT_ADDR(r_curr); + GRN_B_DEC(id_curr.rid, p); + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + GRN_B_DEC(id_curr.sid, p); + } else { + id_curr.sid = 1; + } + } + } else if (u->sid == id_curr.sid) { + BUFFER_REC_DEL(r_curr); + step = r_curr->step; + } + } + rnew->step = step; + rnew->jump = check_jump(ctx, ii, b, rnew, jump) ? 0 : jump; + // smb_wmb(); + *lastp = pos; + break; + } + + if (reset) { + r_start = r_curr; + id_start.rid = id_curr.rid; + id_start.sid = id_curr.sid; + if (!(delta0 = u->rid - id_start.rid)) { delta0 = u->sid - id_start.sid; } + nhops = 0; + vhops = 1; + vdelta = delta0 >> 1; + } else { + if (!(delta = id_curr.rid - id_start.rid)) { + delta = id_curr.sid - id_start.sid; + } + if (vdelta < delta) { + vdelta += (delta0 >> ++vhops); + r_start = r_curr; + } + if (nhops > vhops) { + set_jump_r(ctx, ii, b, r_start, *lastp); + } else { + nhops++; + } + } + + last = *lastp; + lastp = &r_curr->step; + reset = 0; + { + uint16_t posj = r_curr->jump; + if (posj > 1) { + buffer_rec *rj = BUFFER_REC_AT(b, posj); + if (!BUFFER_REC_DELETED(rj)) { + docid idj; + p = GRN_NEXT_ADDR(rj); + GRN_B_DEC(idj.rid, p); + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + GRN_B_DEC(idj.sid, p); + } else { + idj.sid = 1; + } + if (idj.rid < u->rid || (idj.rid == u->rid && idj.sid < u->sid)) { + last = posj; + lastp = &rj->step; + } else { + reset = 1; + } + } + } + } + } + return ctx->rc; +} + +/* array */ + +inline static uint32_t * +array_at(grn_ctx *ctx, grn_ii *ii, uint32_t id) +{ + byte *p = NULL; + uint32_t seg, pseg; + if (id > GRN_ID_MAX) { return NULL; } + seg = id >> W_ARRAY; + if ((pseg = ii->header->ainfo[seg]) == GRN_II_PSEG_NOT_ASSIGNED) { + return NULL; + } + GRN_IO_SEG_REF(ii->seg, pseg, p); + if (!p) { return NULL; } + return (uint32_t *)(p + (id & ARRAY_MASK_IN_A_SEGMENT) * S_ARRAY_ELEMENT); +} + +inline static uint32_t * +array_get(grn_ctx *ctx, grn_ii *ii, uint32_t id) +{ + byte *p = NULL; + uint16_t seg; + uint32_t pseg; + if (id > GRN_ID_MAX) { return NULL; } + seg = id >> W_ARRAY; + if ((pseg = ii->header->ainfo[seg]) == GRN_II_PSEG_NOT_ASSIGNED) { + if (segment_get_clear(ctx, ii, &pseg)) { return NULL; } + ii->header->ainfo[seg] = pseg; + if (seg >= ii->header->amax) { ii->header->amax = seg + 1; } + } + GRN_IO_SEG_REF(ii->seg, pseg, p); + if (!p) { return NULL; } + return (uint32_t *)(p + (id & ARRAY_MASK_IN_A_SEGMENT) * S_ARRAY_ELEMENT); +} + +inline static void +array_unref(grn_ii *ii, uint32_t id) +{ + GRN_IO_SEG_UNREF(ii->seg, ii->header->ainfo[id >> W_ARRAY]); +} + +/* updspec */ + +grn_ii_updspec * +grn_ii_updspec_open(grn_ctx *ctx, uint32_t rid, uint32_t sid) +{ + grn_ii_updspec *u; + if (!(u = GRN_MALLOC(sizeof(grn_ii_updspec)))) { return NULL; } + u->rid = rid; + u->sid = sid; + u->weight = 0; + u->tf = 0; + u->atf = 0; + u->pos = NULL; + u->tail = NULL; + // u->vnodes = NULL; + return u; +} + +#define GRN_II_MAX_TF 0x1ffff + +grn_rc +grn_ii_updspec_add(grn_ctx *ctx, grn_ii_updspec *u, int pos, int32_t weight) +{ + struct _grn_ii_pos *p; + u->atf++; + if (u->tf >= GRN_II_MAX_TF) { return GRN_SUCCESS; } + if (!(p = GRN_MALLOC(sizeof(struct _grn_ii_pos)))) { + return GRN_NO_MEMORY_AVAILABLE; + } + u->weight += weight; + p->pos = pos; + p->next = NULL; + if (u->tail) { + u->tail->next = p; + } else { + u->pos = p; + } + u->tail = p; + u->tf++; + return GRN_SUCCESS; +} + +int +grn_ii_updspec_cmp(grn_ii_updspec *a, grn_ii_updspec *b) +{ + struct _grn_ii_pos *pa, *pb; + if (a->rid != b->rid) { return a->rid - b->rid; } + if (a->sid != b->sid) { return a->sid - b->sid; } + if (a->weight != b->weight) { return a->weight - b->weight; } + if (a->tf != b->tf) { return a->tf - b->tf; } + for (pa = a->pos, pb = b->pos; pa && pb; pa = pa->next, pb = pb->next) { + if (pa->pos != pb->pos) { return pa->pos - pb->pos; } + } + if (pa) { return 1; } + if (pb) { return -1; } + return 0; +} + +grn_rc +grn_ii_updspec_close(grn_ctx *ctx, grn_ii_updspec *u) +{ + struct _grn_ii_pos *p = u->pos, *q; + while (p) { + q = p->next; + GRN_FREE(p); + p = q; + } + GRN_FREE(u); + return GRN_SUCCESS; +} + +inline static uint8_t * +encode_rec(grn_ctx *ctx, grn_ii *ii, grn_ii_updspec *u, unsigned int *size, int deletep) +{ + uint8_t *br, *p; + struct _grn_ii_pos *pp; + uint32_t lpos, tf, weight; + if (deletep) { + tf = 0; + weight = 0; + } else { + tf = u->tf; + weight = u->weight; + } + if (!(br = GRN_MALLOC((tf + 4) * 5))) { + return NULL; + } + p = br; + GRN_B_ENC(u->rid, p); + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + GRN_B_ENC(u->sid, p); + } else { + u->sid = 1; + } + GRN_B_ENC(tf, p); + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { GRN_B_ENC(weight, p); } + if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) { + for (lpos = 0, pp = u->pos; pp && tf--; lpos = pp->pos, pp = pp->next) { + GRN_B_ENC(pp->pos - lpos, p); + } + } + while (((intptr_t)p & 0x03)) { *p++ = 0; } + *size = (unsigned int) ((p - br) + sizeof(buffer_rec)); + return br; +} + +typedef struct { + grn_ii *ii; + grn_hash *h; +} lexicon_deletable_arg; + +#ifdef CASCADE_DELETE_LEXICON +static int +lexicon_deletable(grn_ctx *ctx, grn_obj *lexicon, grn_id tid, void *arg) +{ + uint32_t *a; + grn_hash *h = ((lexicon_deletable_arg *)arg)->h; + grn_ii *ii = ((lexicon_deletable_arg *)arg)->ii; + if (!h) { return 0; } + if ((a = array_at(ctx, ii, tid))) { + if (a[0]) { + array_unref(ii, tid); + return 0; + } + array_unref(ii, tid); + } + { + grn_ii_updspec **u; + if (!grn_hash_get(ctx, h, &tid, sizeof(grn_id), (void **) &u)) { + return (ERRP(ctx, GRN_ERROR)) ? 0 : 1; + } + if (!(*u)->tf || !(*u)->sid) { return 1; } + return 0; + } +} +#endif /* CASCADE_DELETE_LEXICON */ + +inline static void +lexicon_delete(grn_ctx *ctx, grn_ii *ii, uint32_t tid, grn_hash *h) +{ +#ifdef CASCADE_DELETE_LEXICON + lexicon_deletable_arg arg = {ii, h}; + grn_table_delete_optarg optarg = {0, lexicon_deletable, &arg}; + _grn_table_delete_by_id(ctx, ii->lexicon, tid, &optarg); +#endif /* CASCADE_DELETE_LEXICON */ +} + +typedef struct { + grn_id rid; + uint32_t sid; + uint32_t tf; + uint32_t weight; + uint32_t flags; +} docinfo; + +#define GETNEXTC() do {\ + if (sdf) {\ + uint32_t dgap = *srp++;\ + cid.rid += dgap;\ + if (dgap) { cid.sid = 0; }\ + snp += cid.tf;\ + cid.tf = 1 + *stp++;\ + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { cid.weight = *sop++; }\ + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {\ + cid.sid += 1 + *ssp++;\ + } else {\ + cid.sid = 1;\ + }\ + sdf--;\ + } else {\ + cid.rid = 0;\ + }\ +} while (0) + +#define PUTNEXT_(id) do {\ + uint32_t dgap = id.rid - lid.rid;\ + uint32_t sgap = (dgap ? id.sid : id.sid - lid.sid) - 1;\ + *ridp++ = dgap;\ + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {\ + *sidp++ = sgap;\ + }\ + *tfp++ = id.tf - 1;\ + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { *weightp++ = id.weight; }\ + lid.rid = id.rid;\ + lid.sid = id.sid;\ +} while (0) + +#define PUTNEXTC() do {\ + if (cid.rid) {\ + if (cid.tf) {\ + if (lid.rid > cid.rid || (lid.rid == cid.rid && lid.sid >= cid.sid)) {\ + DEFINE_NAME(ii);\ + CRIT(GRN_FILE_CORRUPT,\ + "[ii][broken] posting in list is larger than posting in chunk: "\ + "<%.*s>: (%d:%d) -> (%d:%d)",\ + name_size, name, lid.rid, lid.sid, cid.rid, cid.sid);\ + break;\ + }\ + PUTNEXT_(cid);\ + if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {\ + uint32_t i;\ + for (i = 0; i < cid.tf; i++) {\ + *posp++ = snp[i];\ + spos += snp[i];\ + }\ + }\ + } else {\ + DEFINE_NAME(ii);\ + CRIT(GRN_FILE_CORRUPT,\ + "[ii][broken] invalid posting in chunk: <%.*s>: (%d,%d)",\ + name_size, name, bt->tid, cid.rid);\ + break;\ + }\ + }\ + GETNEXTC();\ +} while (0) + +#define GETNEXTB() do {\ + if (nextb) {\ + uint32_t lrid = bid.rid, lsid = bid.sid;\ + buffer_rec *br = BUFFER_REC_AT(sb, nextb);\ + sbp = GRN_NEXT_ADDR(br);\ + GRN_B_DEC(bid.rid, sbp);\ + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) {\ + GRN_B_DEC(bid.sid, sbp);\ + } else {\ + bid.sid = 1;\ + }\ + if (lrid > bid.rid || (lrid == bid.rid && lsid >= bid.sid)) {\ + DEFINE_NAME(ii);\ + CRIT(GRN_FILE_CORRUPT,\ + "[ii][broken] postings in block aren't sorted: "\ + "<%.*s>: (%d:%d) -> (%d:%d)",\ + name_size, name, lrid, lsid, bid.rid, bid.sid);\ + break;\ + }\ + nextb = br->step;\ + } else {\ + bid.rid = 0;\ + }\ +} while (0) + +#define PUTNEXTB() do {\ + if (bid.rid && bid.sid) {\ + GRN_B_DEC(bid.tf, sbp);\ + if (bid.tf > 0) {\ + if (lid.rid > bid.rid || (lid.rid == bid.rid && lid.sid >= bid.sid)) {\ + DEFINE_NAME(ii);\ + CRIT(GRN_FILE_CORRUPT,\ + "[ii][broken] posting in list is larger than posting in buffer: "\ + "<%.*s>: (%d:%d) -> (%d:%d)",\ + name_size, name, lid.rid, lid.sid, bid.rid, bid.sid);\ + break;\ + }\ + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) {\ + GRN_B_DEC(bid.weight, sbp);\ + }\ + PUTNEXT_(bid);\ + if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) {\ + while (bid.tf--) { GRN_B_DEC(*posp, sbp); spos += *posp++; }\ + }\ + }\ + }\ + GETNEXTB();\ +} while (0) + +#define MERGE_BC(cond) do {\ + if (bid.rid) {\ + if (cid.rid) {\ + if (cid.rid < bid.rid) {\ + PUTNEXTC();\ + if (ctx->rc != GRN_SUCCESS) { break; }\ + } else {\ + if (bid.rid < cid.rid) {\ + PUTNEXTB();\ + if (ctx->rc != GRN_SUCCESS) { break; }\ + } else {\ + if (bid.sid) {\ + if (cid.sid < bid.sid) {\ + PUTNEXTC();\ + if (ctx->rc != GRN_SUCCESS) { break; }\ + } else {\ + if (bid.sid == cid.sid) { GETNEXTC(); }\ + PUTNEXTB();\ + if (ctx->rc != GRN_SUCCESS) { break; }\ + }\ + } else {\ + GETNEXTC();\ + }\ + }\ + }\ + } else {\ + PUTNEXTB();\ + if (ctx->rc != GRN_SUCCESS) { break; }\ + }\ + } else {\ + if (cid.rid) {\ + PUTNEXTC();\ + if (ctx->rc != GRN_SUCCESS) { break; }\ + } else {\ + break;\ + }\ + }\ +} while (cond) + +typedef struct { + uint32_t segno; + uint32_t size; + uint32_t dgap; +} chunk_info; + +static grn_rc +chunk_flush(grn_ctx *ctx, grn_ii *ii, chunk_info *cinfo, uint8_t *enc, uint32_t encsize) +{ + uint8_t *dc; + uint32_t dcn; + grn_io_win dw; + if (encsize) { + chunk_new(ctx, ii, &dcn, encsize); + if (ctx->rc == GRN_SUCCESS) { + if ((dc = WIN_MAP(ii->chunk, ctx, &dw, dcn, 0, encsize, grn_io_wronly))) { + grn_memcpy(dc, enc, encsize); + grn_io_win_unmap(&dw); + cinfo->segno = dcn; + cinfo->size = encsize; + } else { + chunk_free(ctx, ii, dcn, 0, encsize); + { + DEFINE_NAME(ii); + MERR("[ii][chunk][flush] failed to allocate a destination chunk: " + "<%.*s> :" + "segment:<%u>, size:<%u>", + name_size, name, + dcn, encsize); + } + } + } + } else { + cinfo->segno = 0; + cinfo->size = 0; + } + return ctx->rc; +} + +static grn_rc +chunk_merge(grn_ctx *ctx, grn_ii *ii, buffer *sb, buffer_term *bt, + chunk_info *cinfo, grn_id rid, datavec *dv, + uint16_t *nextbp, uint8_t **sbpp, docinfo *bidp, int32_t *balance) +{ + grn_io_win sw; + uint64_t spos = 0; + uint32_t segno = cinfo->segno, size = cinfo->size, sdf = 0, ndf = 0; + uint32_t *ridp = NULL, *sidp = NULL, *tfp, *weightp = NULL, *posp = NULL; + docinfo cid = {0, 0, 0, 0, 0}, lid = {0, 0, 0, 0, 0}, bid = *bidp; + uint8_t *scp = WIN_MAP(ii->chunk, ctx, &sw, segno, 0, size, grn_io_rdonly); + + if (scp) { + uint16_t nextb = *nextbp; + uint32_t snn = 0, *srp, *ssp = NULL, *stp, *sop = NULL, *snp; + uint8_t *sbp = *sbpp; + datavec rdv[MAX_N_ELEMENTS + 1]; + size_t bufsize = S_SEGMENT * ii->n_elements; + datavec_init(ctx, rdv, ii->n_elements, 0, 0); + if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) { + rdv[ii->n_elements - 1].flags = ODD; + } + bufsize += grn_p_decv(ctx, scp, cinfo->size, rdv, ii->n_elements); + // (df in chunk list) = a[1] - sdf; + { + int j = 0; + sdf = rdv[j].data_size; + srp = rdv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { ssp = rdv[j++].data; } + stp = rdv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { sop = rdv[j++].data; } + snn = rdv[j].data_size; + snp = rdv[j].data; + } + datavec_reset(ctx, dv, ii->n_elements, sdf + S_SEGMENT, bufsize); + if (ctx->rc == GRN_SUCCESS) { + { + int j = 0; + ridp = dv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { sidp = dv[j++].data; } + tfp = dv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { weightp = dv[j++].data; } + posp = dv[j].data; + } + GETNEXTC(); + MERGE_BC(bid.rid <= rid || cid.rid); + if (ctx->rc == GRN_SUCCESS) { + *sbpp = sbp; + *nextbp = nextb; + *bidp = bid; + GRN_ASSERT(posp < dv[ii->n_elements].data); + ndf = ridp - dv[0].data; + } + } + datavec_fin(ctx, rdv); + grn_io_win_unmap(&sw); + } else { + DEFINE_NAME(ii); + MERR("[ii][chunk][merge] failed to allocate a source chunk: " + "<%.*s> :" + "record:<%u>, segment:<%u>, size:<%u>", + name_size, name, + rid, + segno, + size); + } + if (ctx->rc == GRN_SUCCESS) { + int j = 0; + uint8_t *enc; + uint32_t encsize; + uint32_t np = posp - dv[ii->n_elements - 1].data; + uint32_t f_s = (ndf < 3) ? 0 : USE_P_ENC; + uint32_t f_d = ((ndf < 16) || (ndf <= (lid.rid >> 8))) ? 0 : USE_P_ENC; + dv[j].data_size = ndf; dv[j++].flags = f_d; + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + dv[j].data_size = ndf; dv[j++].flags = f_s; + } + dv[j].data_size = ndf; dv[j++].flags = f_s; + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { + dv[j].data_size = ndf; dv[j++].flags = f_s; + } + if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) { + uint32_t f_p = ((np < 32) || (np <= (spos >> 13))) ? 0 : USE_P_ENC; + dv[j].data_size = np; dv[j].flags = f_p|ODD; + } + if ((enc = GRN_MALLOC((ndf * 4 + np) * 2))) { + encsize = grn_p_encv(ctx, dv, ii->n_elements, enc); + chunk_flush(ctx, ii, cinfo, enc, encsize); + if (ctx->rc == GRN_SUCCESS) { + chunk_free(ctx, ii, segno, 0, size); + } + GRN_FREE(enc); + } else { + DEFINE_NAME(ii); + MERR("[ii][chunk][merge] failed to allocate a encode buffer: " + "<%.*s> :" + "record:<%u>, segment:<%u>, size:<%u>", + name_size, name, + rid, + segno, + size); + } + } + *balance += (ndf - sdf); + return ctx->rc; +} + +static void +buffer_merge_dump_datavec(grn_ctx *ctx, + grn_ii *ii, + datavec *dv, + datavec *rdv) +{ + int i, j; + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + for (i = 0; i < ii->n_elements; i++) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "rdv[%d] data_size=%d, flags=%d", + i, rdv[i].data_size, rdv[i].flags); + GRN_BULK_REWIND(&buffer); + for (j = 0; j < rdv[i].data_size;) { + grn_text_printf(ctx, &buffer, " %d", rdv[i].data[j]); + j++; + if (!(j % 32) || j == rdv[i].data_size) { + GRN_LOG(ctx, GRN_LOG_DEBUG, + "rdv[%d].data[%d]%.*s", + i, j, + (int)GRN_TEXT_LEN(&buffer), + GRN_TEXT_VALUE(&buffer)); + GRN_BULK_REWIND(&buffer); + } + } + } + + for (i = 0; i < ii->n_elements; i++) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "dv[%d] data_size=%d, flags=%d", + i, dv[i].data_size, dv[i].flags); + GRN_BULK_REWIND(&buffer); + for (j = 0; j < dv[i].data_size;) { + grn_text_printf(ctx, &buffer, " %d", dv[i].data[j]); + j++; + if (!(j % 32) || j == dv[i].data_size) { + GRN_LOG(ctx, GRN_LOG_DEBUG, + "dv[%d].data[%d]%.*s", + i, j, + (int)GRN_TEXT_LEN(&buffer), + GRN_TEXT_VALUE(&buffer)); + GRN_BULK_REWIND(&buffer); + } + } + } + + GRN_OBJ_FIN(ctx, &buffer); +} + +/* If dc doesn't have enough space, program may be crashed. + * TODO: Support auto space extension or max size check. + */ +static grn_rc +buffer_merge(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h, + buffer *sb, uint8_t *sc, buffer *db, uint8_t *dc) +{ + buffer_term *bt; + uint8_t *sbp = NULL, *dcp = dc; + datavec dv[MAX_N_ELEMENTS + 1]; + datavec rdv[MAX_N_ELEMENTS + 1]; + uint16_t n = db->header.nterms, nterms_void = 0; + size_t unitsize = (S_SEGMENT + sb->header.chunk_size / sb->header.nterms) * 2; + // size_t unitsize = (S_SEGMENT + sb->header.chunk_size) * 2 + (1<<24); + size_t totalsize = unitsize * ii->n_elements; + //todo : realloc + datavec_init(ctx, dv, ii->n_elements, unitsize, totalsize); + if (ctx->rc != GRN_SUCCESS) { + DEFINE_NAME(ii); + ERR(ctx->rc, + "[ii][buffer][merge] failed to initialize data vector: " + "<%.*s>: " + "unit-size:<%" GRN_FMT_SIZE ">, " + "total-size:<%" GRN_FMT_SIZE ">", + name_size, name, + unitsize, + totalsize); + return ctx->rc; + } + datavec_init(ctx, rdv, ii->n_elements, 0, 0); + if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) { + rdv[ii->n_elements - 1].flags = ODD; + } + for (bt = db->terms; n; n--, bt++) { + uint16_t nextb; + uint64_t spos = 0; + int32_t balance = 0; + uint32_t *ridp, *sidp = NULL, *tfp, *weightp = NULL, *posp, nchunks = 0; + uint32_t nvchunks = 0; + chunk_info *cinfo = NULL; + grn_id crid = GRN_ID_NIL; + docinfo cid = {0, 0, 0, 0, 0}, lid = {0, 0, 0, 0, 0}, bid = {0, 0}; + uint32_t sdf = 0, snn = 0, ndf; + uint32_t *srp = NULL, *ssp = NULL, *stp = NULL, *sop = NULL, *snp = NULL; + if (!bt->tid) { + nterms_void++; + continue; + } + if (!bt->pos_in_buffer) { + GRN_ASSERT(!bt->size_in_buffer); + if (bt->size_in_chunk) { + grn_memcpy(dcp, sc + bt->pos_in_chunk, bt->size_in_chunk); + bt->pos_in_chunk = (uint32_t)(dcp - dc); + dcp += bt->size_in_chunk; + } + continue; + } + nextb = bt->pos_in_buffer; + GETNEXTB(); + if (sc && bt->size_in_chunk) { + uint8_t *scp = sc + bt->pos_in_chunk; + uint8_t *sce = scp + bt->size_in_chunk; + size_t size = S_SEGMENT * ii->n_elements; + if ((bt->tid & CHUNK_SPLIT)) { + int i; + GRN_B_DEC(nchunks, scp); + if (!(cinfo = GRN_MALLOCN(chunk_info, nchunks + 1))) { + datavec_fin(ctx, dv); + datavec_fin(ctx, rdv); + { + DEFINE_NAME(ii); + MERR("[ii][buffer][merge] failed to allocate chunk info: " + "<%.*s> :" + "segment:<%u>, " + "n-chunks:<%u>, " + "unit-size:<%" GRN_FMT_SIZE ">, " + "total-size:<%" GRN_FMT_SIZE ">", + name_size, name, + seg, + nchunks, + unitsize, + totalsize); + } + return ctx->rc; + } + for (i = 0; i < nchunks; i++) { + GRN_B_DEC(cinfo[i].segno, scp); + GRN_B_DEC(cinfo[i].size, scp); + GRN_B_DEC(cinfo[i].dgap, scp); + crid += cinfo[i].dgap; + if (bid.rid <= crid) { + chunk_merge(ctx, ii, sb, bt, &cinfo[i], crid, dv, + &nextb, &sbp, &bid, &balance); + if (ctx->rc != GRN_SUCCESS) { + if (cinfo) { GRN_FREE(cinfo); } + datavec_fin(ctx, dv); + datavec_fin(ctx, rdv); + { + DEFINE_NAME(ii); + ERR(ctx->rc, + "[ii][buffer][merge] failed to merge chunk: " + "<%.*s>: " + "chunk:<%u>, " + "n-chunks:<%u>", + name_size, name, + i, + nchunks); + } + return ctx->rc; + } + } + if (cinfo[i].size) { + nvchunks++; + } else { + crid -= cinfo[i].dgap; + cinfo[i + 1].dgap += cinfo[i].dgap; + } + } + } + if (sce > scp) { + size += grn_p_decv(ctx, scp, sce - scp, rdv, ii->n_elements); + { + int j = 0; + sdf = rdv[j].data_size; + srp = rdv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { ssp = rdv[j++].data; } + stp = rdv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { sop = rdv[j++].data; } + snn = rdv[j].data_size; + snp = rdv[j].data; + } + datavec_reset(ctx, dv, ii->n_elements, sdf + S_SEGMENT, size); + if (ctx->rc != GRN_SUCCESS) { + if (cinfo) { GRN_FREE(cinfo); } + datavec_fin(ctx, dv); + datavec_fin(ctx, rdv); + { + DEFINE_NAME(ii); + ERR(ctx->rc, + "[ii][buffer][merge] failed to reset data vector: " + "<%.*s>: " + "unit-size:<%" GRN_FMT_SIZE ">, " + "total-size:<%" GRN_FMT_SIZE ">", + name_size, name, + (size_t)(sdf + S_SEGMENT), + size); + } + return ctx->rc; + } + } + } + { + int j = 0; + ridp = dv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { sidp = dv[j++].data; } + tfp = dv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { weightp = dv[j++].data; } + posp = dv[j].data; + } + GETNEXTC(); + MERGE_BC(1); + if (ctx->rc != GRN_SUCCESS) { + if (cinfo) { GRN_FREE(cinfo); } + datavec_fin(ctx, dv); + datavec_fin(ctx, rdv); + { + DEFINE_NAME(ii); + ERR(ctx->rc, + "[ii][buffer][merge] failed to merge chunk: <%.*s>", + name_size, name); + } + return ctx->rc; + } + GRN_ASSERT(posp < dv[ii->n_elements].data); + ndf = ridp - dv[0].data; + /* + { + grn_obj buf; + uint32_t rid, sid, tf, i, pos, *pp; + GRN_TEXT_INIT(&buf, 0); + rid = 0; + pp = dv[3].data; + for (i = 0; i < ndf; i++) { + GRN_BULK_REWIND(&buf); + rid += dv[0].data[i]; + if (dv[0].data[i]) { sid = 0; } + sid += dv[1].data[i] + 1; + tf = dv[2].data[i] + 1; + pos = 0; + grn_text_itoa(ctx, &buf, rid); + GRN_TEXT_PUTC(ctx, &buf, ':'); + grn_text_itoa(ctx, &buf, sid); + GRN_TEXT_PUTC(ctx, &buf, ':'); + grn_text_itoa(ctx, &buf, tf); + GRN_TEXT_PUTC(ctx, &buf, ':'); + while (tf--) { + pos += *pp++; + grn_text_itoa(ctx, &buf, pos); + if (tf) { GRN_TEXT_PUTC(ctx, &buf, ','); } + } + GRN_TEXT_PUTC(ctx, &buf, '\0'); + GRN_LOG(ctx, GRN_LOG_DEBUG, "Posting:%s", GRN_TEXT_VALUE(&buf)); + } + GRN_OBJ_FIN(ctx, &buf); + } + */ + { + grn_id tid = bt->tid & GRN_ID_MAX; + uint32_t *a = array_at(ctx, ii, tid); + if (!a) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "array_entry not found tid=%d", tid); + memset(bt, 0, sizeof(buffer_term)); + nterms_void++; + } else { + if (!ndf && !nvchunks) { + a[0] = 0; + a[1] = 0; + lexicon_delete(ctx, ii, tid, h); + memset(bt, 0, sizeof(buffer_term)); + nterms_void++; + } else if ((ii->header->flags & GRN_OBJ_WITH_SECTION) + && !nvchunks && ndf == 1 && lid.rid < 0x100000 && + lid.sid < 0x800 && lid.tf == 1 && lid.weight == 0) { + a[0] = (lid.rid << 12) + (lid.sid << 1) + 1; + a[1] = (ii->header->flags & GRN_OBJ_WITH_POSITION) ? posp[-1] : 0; + memset(bt, 0, sizeof(buffer_term)); + nterms_void++; + } else if (!(ii->header->flags & GRN_OBJ_WITH_SECTION) + && !nvchunks && ndf == 1 && lid.tf == 1 && lid.weight == 0) { + a[0] = (lid.rid << 1) + 1; + a[1] = (ii->header->flags & GRN_OBJ_WITH_POSITION) ? posp[-1] : 0; + memset(bt, 0, sizeof(buffer_term)); + nterms_void++; + } else { + int j = 0; + uint8_t *dcp0; + uint32_t encsize; + uint32_t f_s = (ndf < 3) ? 0 : USE_P_ENC; + uint32_t f_d = ((ndf < 16) || (ndf <= (lid.rid >> 8))) ? 0 : USE_P_ENC; + dv[j].data_size = ndf; dv[j++].flags = f_d; + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + dv[j].data_size = ndf; dv[j++].flags = f_s; + } + dv[j].data_size = ndf; dv[j++].flags = f_s; + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { + dv[j].data_size = ndf; dv[j++].flags = f_s; + } + if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) { + uint32_t np = posp - dv[ii->n_elements - 1].data; + uint32_t f_p = ((np < 32) || (np <= (spos >> 13))) ? 0 : USE_P_ENC; + dv[j].data_size = np; dv[j].flags = f_p|ODD; + } + dcp0 = dcp; + a[1] = (bt->size_in_chunk ? a[1] : 0) + (ndf - sdf) + balance; + if (nvchunks) { + int i; + GRN_B_ENC(nvchunks, dcp); + for (i = 0; i < nchunks; i++) { + if (cinfo[i].size) { + GRN_B_ENC(cinfo[i].segno, dcp); + GRN_B_ENC(cinfo[i].size, dcp); + GRN_B_ENC(cinfo[i].dgap, dcp); + } + } + } + encsize = grn_p_encv(ctx, dv, ii->n_elements, dcp); + + if (grn_logger_pass(ctx, GRN_LOG_DEBUG)) { + if (sb->header.chunk_size + S_SEGMENT <= (dcp - dc) + encsize) { + GRN_LOG(ctx, GRN_LOG_DEBUG, + "cs(%d)+(%d)=(%d)" + "<=(%" GRN_FMT_LLD ")+(%d)=" + "(%" GRN_FMT_LLD ")", + sb->header.chunk_size, + S_SEGMENT, + sb->header.chunk_size + S_SEGMENT, + (long long int)(dcp - dc), + encsize, + (long long int)((dcp - dc) + encsize)); + buffer_merge_dump_datavec(ctx, ii, dv, rdv); + } + } + + if (encsize > CHUNK_SPLIT_THRESHOLD && + (cinfo || (cinfo = GRN_MALLOCN(chunk_info, nchunks + 1))) && + !chunk_flush(ctx, ii, &cinfo[nchunks], dcp, encsize)) { + int i; + cinfo[nchunks].dgap = lid.rid - crid; + nvchunks++; + dcp = dcp0; + GRN_B_ENC(nvchunks, dcp); + for (i = 0; i <= nchunks; i++) { + if (cinfo[i].size) { + GRN_B_ENC(cinfo[i].segno, dcp); + GRN_B_ENC(cinfo[i].size, dcp); + GRN_B_ENC(cinfo[i].dgap, dcp); + } + } + GRN_LOG(ctx, GRN_LOG_DEBUG, "split (%d) encsize=%d", tid, encsize); + bt->tid |= CHUNK_SPLIT; + } else { + dcp += encsize; + if (!nvchunks) { + bt->tid &= ~CHUNK_SPLIT; + } + } + bt->pos_in_chunk = (uint32_t)(dcp0 - dc); + bt->size_in_chunk = (uint32_t)(dcp - dcp0); + bt->size_in_buffer = 0; + bt->pos_in_buffer = 0; + } + array_unref(ii, tid); + } + } + if (cinfo) { GRN_FREE(cinfo); } + } + datavec_fin(ctx, rdv); + datavec_fin(ctx, dv); + db->header.chunk_size = (uint32_t)(dcp - dc); + db->header.buffer_free = + S_SEGMENT - sizeof(buffer_header) - db->header.nterms * sizeof(buffer_term); + db->header.nterms_void = nterms_void; + return ctx->rc; +} + +static void +fake_map(grn_ctx *ctx, grn_io *io, grn_io_win *iw, void *addr, uint32_t seg, uint32_t size) +{ + iw->ctx = ctx; + iw->diff = 0; + iw->io = io; + iw->mode = grn_io_wronly; + iw->segment = ((seg) >> GRN_II_N_CHUNK_VARIATION); + iw->offset = (((seg) & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << GRN_II_W_LEAST_CHUNK); + iw->size = size; + iw->cached = 0; + iw->addr = addr; +} + +static grn_rc +buffer_flush(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) +{ + grn_io_win sw, dw; + buffer *sb, *db = NULL; + uint8_t *dc, *sc = NULL; + uint32_t ds, pseg, scn, dcn = 0; + if (ii->header->binfo[seg] == GRN_II_PSEG_NOT_ASSIGNED) { + DEFINE_NAME(ii); + CRIT(GRN_FILE_CORRUPT, + "[ii][buffer][flush] invalid segment: " + "<%.*s> :" + "request:<%u>, max:<%u>", + name_size, name, + seg, ii->seg->header->max_segment); + return ctx->rc; + } + if ((ds = segment_get(ctx, ii)) == ii->seg->header->max_segment) { + DEFINE_NAME(ii); + MERR("[ii][buffer][flush] segment is full: " + "<%.*s> :" + "request:<%u>, max:<%u>", + name_size, name, + seg, ii->seg->header->max_segment); + return ctx->rc; + } + pseg = buffer_open(ctx, ii, SEG2POS(seg, 0), NULL, &sb); + if (pseg == GRN_II_PSEG_NOT_ASSIGNED) { + DEFINE_NAME(ii); + MERR("[ii][buffer][flush] failed to open buffer: " + "<%.*s> :" + "segment:<%u>, position:<%u>, max:<%u>", + name_size, name, + seg, SEG2POS(seg, 0), ii->seg->header->max_segment); + return ctx->rc; + } + { + GRN_IO_SEG_REF(ii->seg, ds, db); + if (db) { + uint32_t actual_chunk_size = 0; + uint32_t max_dest_chunk_size = sb->header.chunk_size + S_SEGMENT; + if ((dc = GRN_MALLOC(max_dest_chunk_size * 2))) { + if ((scn = sb->header.chunk) == GRN_II_PSEG_NOT_ASSIGNED || + (sc = WIN_MAP(ii->chunk, ctx, &sw, scn, 0, + sb->header.chunk_size, grn_io_rdonly))) { + uint16_t n = sb->header.nterms; + memset(db, 0, S_SEGMENT); + grn_memcpy(db->terms, sb->terms, n * sizeof(buffer_term)); + db->header.nterms = n; + buffer_merge(ctx, ii, seg, h, sb, sc, db, dc); + if (ctx->rc == GRN_SUCCESS) { + actual_chunk_size = db->header.chunk_size; + if (actual_chunk_size > 0) { + chunk_new(ctx, ii, &dcn, actual_chunk_size); + } + if (ctx->rc == GRN_SUCCESS) { + grn_rc rc; + db->header.chunk = + actual_chunk_size ? dcn : GRN_II_PSEG_NOT_ASSIGNED; + fake_map(ctx, ii->chunk, &dw, dc, dcn, actual_chunk_size); + rc = grn_io_win_unmap(&dw); + if (rc == GRN_SUCCESS) { + buffer_segment_update(ii, seg, ds); + ii->header->total_chunk_size += actual_chunk_size; + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { + grn_io_win_unmap(&sw); + chunk_free(ctx, ii, scn, 0, sb->header.chunk_size); + ii->header->total_chunk_size -= sb->header.chunk_size; + } + } else { + GRN_FREE(dc); + if (actual_chunk_size) { + chunk_free(ctx, ii, dcn, 0, actual_chunk_size); + } + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { grn_io_win_unmap(&sw); } + { + DEFINE_NAME(ii); + ERR(rc, + "[ii][buffer][flush] failed to unmap a destination chunk: " + "<%.*s> : " + "segment:<%u>, destination-segment:<%u>, actual-size:<%u>", + name_size, name, + seg, + dcn, + actual_chunk_size); + } + } + } else { + GRN_FREE(dc); + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { grn_io_win_unmap(&sw); } + } + } else { + GRN_FREE(dc); + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { grn_io_win_unmap(&sw); } + } + } else { + GRN_FREE(dc); + { + DEFINE_NAME(ii); + MERR("[ii][buffer][flush] failed to map a source chunk: " + "<%.*s> :" + "segment:<%u>, source-segment:<%u>, chunk-size:<%u>", + name_size, name, + seg, + scn, + sb->header.chunk_size); + } + } + } else { + DEFINE_NAME(ii); + MERR("[ii][buffer][flush] failed to allocate a destination chunk: " + "<%.*s> :" + "segment:<%u>, destination-segment:<%u>", + name_size, name, + seg, + ds); + } + GRN_IO_SEG_UNREF(ii->seg, ds); + } else { + DEFINE_NAME(ii); + MERR("[ii][buffer][flush] failed to allocate a destination segment: " + "<%.*s> :" + "segment:<%u>, destination-segment:<%u>", + name_size, name, + seg, + ds); + } + buffer_close(ctx, ii, pseg); + } + return ctx->rc; +} + +void +grn_ii_buffer_check(grn_ctx *ctx, grn_ii *ii, uint32_t seg) +{ + grn_io_win sw; + buffer *sb; + uint8_t *sc = NULL; + uint32_t pseg, scn, nterms_with_corrupt_chunk = 0, nterm_with_chunk = 0; + uint32_t ndeleted_terms_with_value = 0; + buffer_term *bt; + uint8_t *sbp = NULL; + datavec rdv[MAX_N_ELEMENTS + 1]; + uint16_t n; + int nterms_void = 0; + int size_in_buffer = 0; + grn_obj buf; + size_t lower_bound; + int64_t nloops = 0, nviolations = 0; + if (ii->header->binfo[seg] == GRN_II_PSEG_NOT_ASSIGNED) { + GRN_OUTPUT_BOOL(GRN_FALSE); + return; + } + pseg = buffer_open(ctx, ii, SEG2POS(seg, 0), NULL, &sb); + if (pseg == GRN_II_PSEG_NOT_ASSIGNED) { + GRN_OUTPUT_BOOL(GRN_FALSE); + return; + } + lower_bound = + (sb->header.buffer_free + sizeof(buffer_term) * sb->header.nterms) + / sizeof(buffer_rec); + datavec_init(ctx, rdv, ii->n_elements, 0, 0); + if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) { + rdv[ii->n_elements - 1].flags = ODD; + } + GRN_OUTPUT_MAP_OPEN("BUFFER", -1); + GRN_OUTPUT_CSTR("buffer id"); + GRN_OUTPUT_INT64(seg); + if ((scn = sb->header.chunk) == GRN_II_PSEG_NOT_ASSIGNED) { + GRN_OUTPUT_CSTR("void chunk size"); + GRN_OUTPUT_INT64(sb->header.chunk_size); + } else { + if ((sc = WIN_MAP(ii->chunk, ctx, &sw, scn, 0, sb->header.chunk_size, + grn_io_rdonly))) { + GRN_OUTPUT_CSTR("chunk size"); + GRN_OUTPUT_INT64(sb->header.chunk_size); + } else { + GRN_OUTPUT_CSTR("unmappable chunk size"); + GRN_OUTPUT_INT64(sb->header.chunk_size); + } + } + GRN_OUTPUT_CSTR("buffer term"); + GRN_OUTPUT_ARRAY_OPEN("TERMS", sb->header.nterms); + + GRN_OBJ_INIT(&buf, GRN_BULK, 0, ii->lexicon->header.domain); + for (bt = sb->terms, n = sb->header.nterms; n; n--, bt++) { + grn_id tid, tid_; + char key[GRN_TABLE_MAX_KEY_SIZE]; + int key_size; + uint16_t nextb; + uint32_t nchunks = 0; + chunk_info *cinfo = NULL; + grn_id crid = GRN_ID_NIL; + docinfo bid = {0, 0}; + uint32_t sdf = 0, snn = 0; + uint32_t *srp = NULL, *ssp = NULL, *stp = NULL, *sop = NULL, *snp = NULL; + if (!bt->tid && !bt->pos_in_buffer && !bt->size_in_buffer) { + nterms_void++; + continue; + } + GRN_OUTPUT_ARRAY_OPEN("TERM", -1); + tid = (bt->tid & GRN_ID_MAX); + key_size = grn_table_get_key(ctx, ii->lexicon, tid, key, + GRN_TABLE_MAX_KEY_SIZE); + tid_ = grn_table_get(ctx, ii->lexicon, key, key_size); + GRN_TEXT_SET(ctx, &buf, key, key_size); + GRN_OUTPUT_OBJ(&buf, NULL); + GRN_OUTPUT_INT64(bt->tid); + GRN_OUTPUT_INT64(tid_); + nextb = bt->pos_in_buffer; + size_in_buffer += bt->size_in_buffer; + if (tid != tid_ && (bt->size_in_buffer || bt->size_in_chunk)) { + ndeleted_terms_with_value++; + } + GETNEXTB(); + GRN_OUTPUT_INT64(bt->size_in_buffer); + GRN_OUTPUT_INT64(bt->size_in_chunk); + if (sc && bt->size_in_chunk) { + uint8_t *scp = sc + bt->pos_in_chunk; + uint8_t *sce = scp + bt->size_in_chunk; + size_t size = S_SEGMENT * ii->n_elements; + if ((bt->tid & CHUNK_SPLIT)) { + int i; + GRN_B_DEC(nchunks, scp); + if (!(cinfo = GRN_MALLOCN(chunk_info, nchunks + 1))) { + datavec_fin(ctx, rdv); + GRN_OBJ_FIN(ctx, &buf); + return; + } + for (i = 0; i < nchunks; i++) { + GRN_B_DEC(cinfo[i].segno, scp); + GRN_B_DEC(cinfo[i].size, scp); + GRN_B_DEC(cinfo[i].dgap, scp); + crid += cinfo[i].dgap; + } + } + if (sce > scp) { + size += grn_p_decv(ctx, scp, sce - scp, rdv, ii->n_elements); + { + int j = 0; + sdf = rdv[j].data_size; + GRN_OUTPUT_INT64(sdf); + srp = rdv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { ssp = rdv[j++].data; } + if (sdf != rdv[j].data_size) { + nterms_with_corrupt_chunk++; + } + stp = rdv[j++].data; + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { sop = rdv[j++].data; } + GRN_OUTPUT_INT64(rdv[j].data_size); + snn = rdv[j].data_size; + snp = rdv[j].data; + } + nterm_with_chunk++; + } + } + { + uint16_t pos; + grn_id rid, sid, rid_ = 0, sid_ = 0; + uint8_t *p; + buffer_rec *r; + for (pos = bt->pos_in_buffer; pos; pos = r->step) { + if (pos < lower_bound) { + nviolations++; + } + r = BUFFER_REC_AT(sb, pos); + p = GRN_NEXT_ADDR(r); + GRN_B_DEC(rid, p); + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + GRN_B_DEC(sid, p); + } else { + sid = 1; + } + if (rid < rid_ || (rid == rid_ && sid < sid_)) { + nloops++; + } + rid_ = rid; + sid_ = sid; + } + } + GRN_OUTPUT_ARRAY_CLOSE(); + if (cinfo) { GRN_FREE(cinfo); } + } + GRN_OBJ_FIN(ctx, &buf); + + GRN_OUTPUT_ARRAY_CLOSE(); + GRN_OUTPUT_CSTR("buffer free"); + GRN_OUTPUT_INT64(sb->header.buffer_free); + GRN_OUTPUT_CSTR("size in buffer"); + GRN_OUTPUT_INT64(size_in_buffer); + GRN_OUTPUT_CSTR("nterms"); + GRN_OUTPUT_INT64(sb->header.nterms); + if (nterms_void != sb->header.nterms_void) { + GRN_OUTPUT_CSTR("nterms void gap"); + GRN_OUTPUT_INT64(nterms_void - sb->header.nterms_void); + } + GRN_OUTPUT_CSTR("nterms with chunk"); + GRN_OUTPUT_INT64(nterm_with_chunk); + if (nterms_with_corrupt_chunk) { + GRN_OUTPUT_CSTR("nterms with corrupt chunk"); + GRN_OUTPUT_INT64(nterms_with_corrupt_chunk); + } + if (ndeleted_terms_with_value) { + GRN_OUTPUT_CSTR("number of deleted terms with value"); + GRN_OUTPUT_INT64(ndeleted_terms_with_value); + } + if (nloops) { + GRN_OUTPUT_CSTR("number of loops"); + GRN_OUTPUT_INT64(nloops); + } + if (nviolations) { + GRN_OUTPUT_CSTR("number of violations"); + GRN_OUTPUT_INT64(nviolations); + } + GRN_OUTPUT_MAP_CLOSE(); + datavec_fin(ctx, rdv); + if (sc) { grn_io_win_unmap(&sw); } + buffer_close(ctx, ii, pseg); +} + +typedef struct { + buffer_term *bt; + const char *key; + uint32_t key_size; +} term_sort; + +static int +term_compar(const void *t1, const void *t2) +{ + int r; + const term_sort *x = (term_sort *)t1, *y = (term_sort *)t2; + if (x->key_size > y->key_size) { + r = memcmp(x->key, y->key, y->key_size); + return r ? r : x->key_size - y->key_size; + } else { + r = memcmp(x->key, y->key, x->key_size); + return r ? r : x->key_size - y->key_size; + } +} + +static grn_rc +term_split(grn_ctx *ctx, grn_obj *lexicon, buffer *sb, buffer *db0, buffer *db1) +{ + uint16_t i, n, *nt; + buffer_term *bt; + uint32_t s, th = (sb->header.chunk_size + sb->header.nterms) >> 1; + term_sort *ts = GRN_MALLOC(sb->header.nterms * sizeof(term_sort)); + if (!ts) { return GRN_NO_MEMORY_AVAILABLE; } + for (i = 0, n = sb->header.nterms, bt = sb->terms; n; bt++, n--) { + if (bt->tid) { + grn_id tid = bt->tid & GRN_ID_MAX; + ts[i].key = _grn_table_key(ctx, lexicon, tid, &ts[i].key_size); + ts[i].bt = bt; + i++; + } + } + qsort(ts, i, sizeof(term_sort), term_compar); + memset(db0, 0, S_SEGMENT); + bt = db0->terms; + nt = &db0->header.nterms; + for (s = 0; n + 1 < i && s <= th; n++, bt++) { + grn_memcpy(bt, ts[n].bt, sizeof(buffer_term)); + (*nt)++; + s += ts[n].bt->size_in_chunk + 1; + } + memset(db1, 0, S_SEGMENT); + bt = db1->terms; + nt = &db1->header.nterms; + for (; n < i; n++, bt++) { + grn_memcpy(bt, ts[n].bt, sizeof(buffer_term)); + (*nt)++; + } + GRN_FREE(ts); + GRN_LOG(ctx, GRN_LOG_DEBUG, "d0=%d d1=%d", + db0->header.nterms, db1->header.nterms); + return GRN_SUCCESS; +} + +static void +array_update(grn_ctx *ctx, grn_ii *ii, uint32_t dls, buffer *db) +{ + uint16_t n; + buffer_term *bt; + uint32_t *a, pos = SEG2POS(dls, sizeof(buffer_header)); + for (n = db->header.nterms, bt = db->terms; n; n--, bt++) { + if (bt->tid) { + grn_id tid = bt->tid & GRN_ID_MAX; + if ((a = array_at(ctx, ii, tid))) { + a[0] = pos; + array_unref(ii, tid); + } else { + GRN_LOG(ctx, GRN_LOG_WARNING, "array_at failed (%d)", tid); + } + } + pos += sizeof(buffer_term) >> 2; + } +} + +static grn_rc +buffer_split(grn_ctx *ctx, grn_ii *ii, uint32_t seg, grn_hash *h) +{ + grn_io_win sw, dw0, dw1; + buffer *sb, *db0 = NULL, *db1 = NULL; + uint8_t *sc = NULL, *dc0, *dc1; + uint32_t dps0 = 0, dps1 = 0, dls0 = 0, dls1 = 0, sps, scn, dcn0 = 0, dcn1 = 0; + if (ii->header->binfo[seg] == GRN_II_PSEG_NOT_ASSIGNED) { + DEFINE_NAME(ii); + CRIT(GRN_FILE_CORRUPT, + "[ii][buffer][split] invalid segment: " + "<%.*s> :" + "request:<%u>, max:<%u>", + name_size, name, + seg, ii->seg->header->max_segment); + return ctx->rc; + } + buffer_segment_reserve(ctx, ii, &dls0, &dps0, &dls1, &dps1); + if (ctx->rc != GRN_SUCCESS) { + DEFINE_NAME(ii); + ERR(ctx->rc, + "[ii][buffer][split] failed to reserve buffer segments: " + "<%.*s> :" + "request:<%u>, max:<%u>", + name_size, name, + seg, ii->seg->header->max_segment); + return ctx->rc; + } + sps = buffer_open(ctx, ii, SEG2POS(seg, 0), NULL, &sb); + if (sps == GRN_II_PSEG_NOT_ASSIGNED) { + DEFINE_NAME(ii); + MERR("[ii][buffer][split] failed to open buffer: " + "<%.*s> :" + "segment:<%u>, position:<%u>, max-segment:<%u>", + name_size, name, + seg, SEG2POS(seg, 0), ii->seg->header->max_segment); + } else { + GRN_IO_SEG_REF(ii->seg, dps0, db0); + if (db0) { + GRN_IO_SEG_REF(ii->seg, dps1, db1); + if (db1) { + uint32_t actual_db0_chunk_size = 0; + uint32_t actual_db1_chunk_size = 0; + uint32_t max_dest_chunk_size = sb->header.chunk_size + S_SEGMENT; + if ((dc0 = GRN_MALLOC(max_dest_chunk_size * 2))) { + if ((dc1 = GRN_MALLOC(max_dest_chunk_size * 2))) { + if ((scn = sb->header.chunk) == GRN_II_PSEG_NOT_ASSIGNED || + (sc = WIN_MAP(ii->chunk, ctx, &sw, scn, 0, + sb->header.chunk_size, grn_io_rdonly))) { + term_split(ctx, ii->lexicon, sb, db0, db1); + buffer_merge(ctx, ii, seg, h, sb, sc, db0, dc0); + if (ctx->rc == GRN_SUCCESS) { + actual_db0_chunk_size = db0->header.chunk_size; + if (actual_db0_chunk_size > 0) { + chunk_new(ctx, ii, &dcn0, actual_db0_chunk_size); + } + if (ctx->rc == GRN_SUCCESS) { + grn_rc rc; + db0->header.chunk = + actual_db0_chunk_size ? dcn0 : GRN_II_PSEG_NOT_ASSIGNED; + fake_map(ctx, ii->chunk, &dw0, dc0, dcn0, actual_db0_chunk_size); + rc = grn_io_win_unmap(&dw0); + if (rc == GRN_SUCCESS) { + buffer_merge(ctx, ii, seg, h, sb, sc, db1, dc1); + if (ctx->rc == GRN_SUCCESS) { + actual_db1_chunk_size = db1->header.chunk_size; + if (actual_db1_chunk_size > 0) { + chunk_new(ctx, ii, &dcn1, actual_db1_chunk_size); + } + if (ctx->rc == GRN_SUCCESS) { + fake_map(ctx, ii->chunk, &dw1, dc1, dcn1, + actual_db1_chunk_size); + rc = grn_io_win_unmap(&dw1); + if (rc == GRN_SUCCESS) { + db1->header.chunk = + actual_db1_chunk_size ? dcn1 : GRN_II_PSEG_NOT_ASSIGNED; + buffer_segment_update(ii, dls0, dps0); + buffer_segment_update(ii, dls1, dps1); + array_update(ctx, ii, dls0, db0); + array_update(ctx, ii, dls1, db1); + buffer_segment_clear(ii, seg); + ii->header->total_chunk_size += actual_db0_chunk_size; + ii->header->total_chunk_size += actual_db1_chunk_size; + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { + grn_io_win_unmap(&sw); + chunk_free(ctx, ii, scn, 0, sb->header.chunk_size); + ii->header->total_chunk_size -= sb->header.chunk_size; + } + } else { + if (actual_db1_chunk_size) { + chunk_free(ctx, ii, dcn1, 0, actual_db1_chunk_size); + } + if (actual_db0_chunk_size) { + chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size); + } + GRN_FREE(dc1); + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { + grn_io_win_unmap(&sw); + } + { + DEFINE_NAME(ii); + ERR(rc, + "[ii][buffer[merge] " + "failed to unmap a destination chunk2: " + "<%.*s> :" + "segment:<%u>, " + "destination-chunk1:<%u>, " + "destination-chunk2:<%u>, " + "actual-size1:<%u>, " + "actual-size2:<%u>", + name_size, name, + seg, + dcn0, + dcn1, + actual_db0_chunk_size, + actual_db1_chunk_size); + } + } + } else { + if (actual_db0_chunk_size) { + chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size); + } + GRN_FREE(dc1); + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { + grn_io_win_unmap(&sw); + } + } + } else { + if (actual_db0_chunk_size) { + chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size); + } + GRN_FREE(dc1); + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { + grn_io_win_unmap(&sw); + } + } + } else { + if (actual_db0_chunk_size) { + chunk_free(ctx, ii, dcn0, 0, actual_db0_chunk_size); + } + GRN_FREE(dc1); + GRN_FREE(dc0); + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { + grn_io_win_unmap(&sw); + } + { + DEFINE_NAME(ii); + ERR(rc, + "[ii][buffer[merge] " + "failed to unmap a destination chunk1: " + "<%.*s> :" + "segment:<%u>, " + "destination-chunk1:<%u>, " + "actual-size1:<%u>", + name_size, name, + seg, + dcn0, + actual_db0_chunk_size); + } + } + } else { + GRN_FREE(dc1); + GRN_FREE(dc0); + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { grn_io_win_unmap(&sw); } + } + } else { + GRN_FREE(dc1); + GRN_FREE(dc0); + if (scn != GRN_II_PSEG_NOT_ASSIGNED) { grn_io_win_unmap(&sw); } + } + } else { + GRN_FREE(dc1); + GRN_FREE(dc0); + { + DEFINE_NAME(ii); + MERR("[ii][buffer][split] failed to map a source chunk: " + "<%.*s> :" + "segment:<%u>, " + "source-segment:<%u>, " + "chunk-size:<%u>", + name_size, name, + seg, + scn, + sb->header.chunk_size); + } + } + } else { + GRN_FREE(dc0); + { + DEFINE_NAME(ii); + MERR("[ii][buffer][split] " + "failed to allocate a destination chunk2: " + "<%.*s> :" + "segment:<%u>, " + "destination-segment1:<%u>, " + "destination-segment2:<%u>", + name_size, name, + seg, + dps0, + dps1); + } + } + } else { + DEFINE_NAME(ii); + MERR("[ii][buffer][split] failed to allocate a destination chunk1: " + "<%.*s>: " + "segment:<%u>, " + "destination-segment1:<%u>, " + "destination-segment2:<%u>", + name_size, name, + seg, + dps0, + dps1); + } + GRN_IO_SEG_UNREF(ii->seg, dps1); + } else { + DEFINE_NAME(ii); + MERR("[ii][buffer][split] failed to allocate a destination segment2: " + "<%.*s>: " + "segment:<%u>, " + "destination-segment1:<%u>, " + "destination-segment2:<%u>", + name_size, name, + seg, + dps0, + dps1); + } + GRN_IO_SEG_UNREF(ii->seg, dps0); + } else { + DEFINE_NAME(ii); + MERR("[ii][buffer][split] failed to allocate a destination segment1: " + "<%.*s>: " + "segment:<%u>, " + "destination-segment1:<%u>, " + "destination-segment2:<%u>", + name_size, name, + seg, + dps0, + dps1); + } + buffer_close(ctx, ii, sps); + } + return ctx->rc; +} + +#define SCALE_FACTOR 2048 +#define MAX_NTERMS 8192 +#define SPLIT_COND(ii, buffer)\ + ((buffer)->header.nterms > 1024 ||\ + ((buffer)->header.nterms > 1 &&\ + (buffer)->header.chunk_size * 100 > (ii)->header->total_chunk_size)) + +inline static void +buffer_new_find_segment(grn_ctx *ctx, + grn_ii *ii, + int size, + grn_id tid, + grn_hash *h, + buffer **b, + uint32_t *lseg, + uint32_t *pseg) +{ + uint32_t *a; + + a = array_at(ctx, ii, tid); + if (!a) { + return; + } + + for (;;) { + uint32_t pos = a[0]; + if (!pos || (pos & 1)) { break; } + *pseg = buffer_open(ctx, ii, pos, NULL, b); + if (*pseg == GRN_II_PSEG_NOT_ASSIGNED) { break; } + if ((*b)->header.buffer_free >= size + sizeof(buffer_term)) { + *lseg = LSEG(pos); + break; + } + buffer_close(ctx, ii, *pseg); + if (SPLIT_COND(ii, (*b))) { + /* ((S_SEGMENT - sizeof(buffer_header) + ii->header->bmax - + (*b)->header.nterms * sizeof(buffer_term)) * 4 < + (*b)->header.chunk_size) */ + GRN_LOG(ctx, GRN_LOG_DEBUG, + "nterms=%d chunk=%d total=%" GRN_FMT_INT64U, + (*b)->header.nterms, + (*b)->header.chunk_size, + ii->header->total_chunk_size >> 10); + if (buffer_split(ctx, ii, LSEG(pos), h)) { break; } + } else { + if (S_SEGMENT - sizeof(buffer_header) + - (*b)->header.nterms * sizeof(buffer_term) + < size + sizeof(buffer_term)) { + break; + } + if (buffer_flush(ctx, ii, LSEG(pos), h)) { break; } + } + } + + array_unref(ii, tid); +} + +inline static void +buffer_new_lexicon_pat(grn_ctx *ctx, + grn_ii *ii, + int size, + grn_id id, + grn_hash *h, + buffer **b, + uint32_t *lseg, + uint32_t *pseg) +{ + grn_pat_cursor *cursor; + char key[GRN_TABLE_MAX_KEY_SIZE]; + int key_size; + + key_size = grn_table_get_key(ctx, ii->lexicon, id, key, + GRN_TABLE_MAX_KEY_SIZE); + if (ii->lexicon->header.flags & GRN_OBJ_KEY_VAR_SIZE) { + grn_obj *tokenizer = NULL; + + grn_table_get_info(ctx, ii->lexicon, NULL, NULL, &tokenizer, NULL, NULL); + if (tokenizer) { + /* For natural language */ + cursor = grn_pat_cursor_open(ctx, + (grn_pat *)(ii->lexicon), + key, + key_size, + NULL, + 0, + 0, + -1, + GRN_CURSOR_ASCENDING|GRN_CURSOR_GT); + if (cursor) { + grn_id tid; + while (ctx->rc == GRN_SUCCESS && + *lseg == GRN_II_PSEG_NOT_ASSIGNED && + (tid = grn_pat_cursor_next(ctx, cursor))) { + buffer_new_find_segment(ctx, ii, size, tid, h, b, lseg, pseg); + } + grn_pat_cursor_close(ctx, cursor); + } + } else { + /* For text data */ + int target_key_size = key_size; + int reduced_key_size = 0; + + while (*lseg == GRN_II_PSEG_NOT_ASSIGNED && target_key_size > 0) { + grn_id tid; + + cursor = grn_pat_cursor_open(ctx, + (grn_pat *)(ii->lexicon), + key, target_key_size, + NULL, 0, 0, -1, + GRN_CURSOR_PREFIX); + if (!cursor) { + break; + } + + if (reduced_key_size == 0) { + while (ctx->rc == GRN_SUCCESS && + *lseg == GRN_II_PSEG_NOT_ASSIGNED && + (tid = grn_pat_cursor_next(ctx, cursor))) { + buffer_new_find_segment(ctx, ii, size, tid, h, b, lseg, pseg); + } + } else { + while (ctx->rc == GRN_SUCCESS && + *lseg == GRN_II_PSEG_NOT_ASSIGNED && + (tid = grn_pat_cursor_next(ctx, cursor))) { + void *current_key; + int current_key_size; + + current_key_size = grn_pat_cursor_get_key(ctx, cursor, ¤t_key); + if (memcmp(((char *)current_key) + target_key_size, + key + target_key_size, + reduced_key_size) == 0) { + continue; + } + buffer_new_find_segment(ctx, ii, size, tid, h, b, lseg, pseg); + } + } + grn_pat_cursor_close(ctx, cursor); + + if (reduced_key_size == 0) { + reduced_key_size = 1; + } else { + reduced_key_size *= 2; + } + target_key_size -= reduced_key_size; + } + } + } else { + /* For other data */ + cursor = grn_pat_cursor_open(ctx, + (grn_pat *)(ii->lexicon), + NULL, 0, key, key_size, 0, -1, + GRN_CURSOR_PREFIX); + if (cursor) { + grn_id tid; + while (ctx->rc == GRN_SUCCESS && + *lseg == GRN_II_PSEG_NOT_ASSIGNED && + (tid = grn_pat_cursor_next(ctx, cursor))) { + buffer_new_find_segment(ctx, ii, size, tid, h, b, lseg, pseg); + } + grn_pat_cursor_close(ctx, cursor); + } + } +} + +inline static void +buffer_new_lexicon_other(grn_ctx *ctx, + grn_ii *ii, + int size, + grn_id id, + grn_hash *h, + buffer **b, + uint32_t *lseg, + uint32_t *pseg) +{ + GRN_TABLE_EACH_BEGIN(ctx, ii->lexicon, cursor, tid) { + if (ctx->rc != GRN_SUCCESS || *lseg != GRN_II_PSEG_NOT_ASSIGNED) { + break; + } + buffer_new_find_segment(ctx, ii, size, tid, h, b, lseg, pseg); + } GRN_TABLE_EACH_END(ctx, cursor); +} + + +inline static uint32_t +buffer_new(grn_ctx *ctx, grn_ii *ii, int size, uint32_t *pos, + buffer_term **bt, buffer_rec **br, buffer **bp, grn_id id, grn_hash *h) +{ + buffer *b = NULL; + uint16_t offset; + uint32_t lseg = GRN_II_PSEG_NOT_ASSIGNED, pseg = GRN_II_PSEG_NOT_ASSIGNED; + if (S_SEGMENT - sizeof(buffer_header) < size + sizeof(buffer_term)) { + DEFINE_NAME(ii); + MERR("[ii][buffer][new] requested size is too large: " + "<%.*s> :" + "requested:<%" GRN_FMT_SIZE ">, max:<%" GRN_FMT_SIZE ">", + name_size, name, + (size_t)(size + sizeof(buffer_term)), + (size_t)(S_SEGMENT - sizeof(buffer_header))); + return GRN_II_PSEG_NOT_ASSIGNED; + } + if (ii->lexicon->header.type == GRN_TABLE_PAT_KEY) { + buffer_new_lexicon_pat(ctx, ii, size, id, h, &b, &lseg, &pseg); + } else { + buffer_new_lexicon_other(ctx, ii, size, id, h, &b, &lseg, &pseg); + } + if (lseg == GRN_II_PSEG_NOT_ASSIGNED) { + if (buffer_segment_new(ctx, ii, &lseg) || + (pseg = buffer_open(ctx, ii, SEG2POS(lseg, 0), NULL, &b)) == GRN_II_PSEG_NOT_ASSIGNED) { + return GRN_II_PSEG_NOT_ASSIGNED; + } + memset(b, 0, S_SEGMENT); + b->header.buffer_free = S_SEGMENT - sizeof(buffer_header); + b->header.chunk = GRN_II_PSEG_NOT_ASSIGNED; + } + if (b->header.nterms_void) { + for (offset = 0; offset < b->header.nterms; offset++) { + if (!b->terms[offset].tid) { break; } + } + if (offset == b->header.nterms) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "inconsistent buffer(%d)", lseg); + b->header.nterms_void = 0; + b->header.nterms++; + b->header.buffer_free -= size + sizeof(buffer_term); + } else { + b->header.nterms_void--; + b->header.buffer_free -= size; + } + } else { + offset = b->header.nterms++; + b->header.buffer_free -= size + sizeof(buffer_term); + } + *pos = SEG2POS(lseg, (sizeof(buffer_header) + sizeof(buffer_term) * offset)); + *bt = &b->terms[offset]; + *br = (buffer_rec *)(((byte *)&b->terms[b->header.nterms]) + b->header.buffer_free); + *bp = b; + return pseg; +} + +/* ii */ + +static grn_ii * +_grn_ii_create(grn_ctx *ctx, grn_ii *ii, const char *path, grn_obj *lexicon, uint32_t flags) +{ + int i; + uint32_t max_n_segments; + uint32_t max_n_chunks; + grn_io *seg, *chunk; + char path2[PATH_MAX]; + struct grn_ii_header *header; + grn_table_flags lflags; + grn_encoding encoding; + grn_obj *tokenizer; + /* + for (i = 0; i < 32; i++) { + new_histogram[i] = 0; + free_histogram[i] = 0; + } + */ + if (grn_table_get_info(ctx, lexicon, &lflags, &encoding, &tokenizer, + NULL, NULL)) { + return NULL; + } + if (path && strlen(path) + 6 >= PATH_MAX) { return NULL; } + + if (flags & GRN_OBJ_INDEX_SMALL) { + max_n_segments = grn_ii_max_n_segments_small; + max_n_chunks = grn_ii_max_n_chunks_small; + } else if (flags & GRN_OBJ_INDEX_MEDIUM) { + max_n_segments = MAX_PSEG_MEDIUM; + max_n_chunks = GRN_II_MAX_CHUNK_MEDIUM; + } else { + max_n_segments = MAX_PSEG; + max_n_chunks = GRN_II_MAX_CHUNK; + } + + seg = grn_io_create(ctx, + path, + sizeof(struct grn_ii_header), + S_SEGMENT, + max_n_segments, + grn_io_auto, + GRN_IO_EXPIRE_SEGMENT); + if (!seg) { return NULL; } + if (path) { + grn_strcpy(path2, PATH_MAX, path); + grn_strcat(path2, PATH_MAX, ".c"); + chunk = grn_io_create(ctx, path2, 0, S_CHUNK, max_n_chunks, grn_io_auto, + GRN_IO_EXPIRE_SEGMENT); + } else { + chunk = grn_io_create(ctx, NULL, 0, S_CHUNK, max_n_chunks, grn_io_auto, 0); + } + if (!chunk) { + grn_io_close(ctx, seg); + grn_io_remove(ctx, path); + return NULL; + } + header = grn_io_header(seg); + grn_io_set_type(seg, GRN_COLUMN_INDEX); + for (i = 0; i < GRN_II_MAX_LSEG; i++) { + header->ainfo[i] = GRN_II_PSEG_NOT_ASSIGNED; + header->binfo[i] = GRN_II_PSEG_NOT_ASSIGNED; + } + for (i = 0; i <= GRN_II_N_CHUNK_VARIATION; i++) { + header->free_chunks[i] = GRN_II_PSEG_NOT_ASSIGNED; + header->garbages[i] = GRN_II_PSEG_NOT_ASSIGNED; + } + header->flags = flags; + ii->seg = seg; + ii->chunk = chunk; + ii->lexicon = lexicon; + ii->lflags = lflags; + ii->encoding = encoding; + ii->header = header; + ii->n_elements = 2; + if ((flags & GRN_OBJ_WITH_SECTION)) { ii->n_elements++; } + if ((flags & GRN_OBJ_WITH_WEIGHT)) { ii->n_elements++; } + if ((flags & GRN_OBJ_WITH_POSITION)) { ii->n_elements++; } + return ii; +} + +grn_ii * +grn_ii_create(grn_ctx *ctx, const char *path, grn_obj *lexicon, uint32_t flags) +{ + grn_ii *ii = NULL; + if (!(ii = GRN_MALLOCN(grn_ii, 1))) { + return NULL; + } + GRN_DB_OBJ_SET_TYPE(ii, GRN_COLUMN_INDEX); + if (!_grn_ii_create(ctx, ii, path, lexicon, flags)) { + GRN_FREE(ii); + return NULL; + } + return ii; +} + +grn_rc +grn_ii_remove(grn_ctx *ctx, const char *path) +{ + grn_rc rc; + char buffer[PATH_MAX]; + if (!path || strlen(path) > PATH_MAX - 4) { return GRN_INVALID_ARGUMENT; } + if ((rc = grn_io_remove(ctx, path))) { goto exit; } + grn_snprintf(buffer, PATH_MAX, PATH_MAX, + "%-.256s.c", path); + rc = grn_io_remove(ctx, buffer); +exit : + return rc; +} + +grn_rc +grn_ii_truncate(grn_ctx *ctx, grn_ii *ii) +{ + grn_rc rc; + const char *io_segpath, *io_chunkpath; + char *segpath, *chunkpath = NULL; + grn_obj *lexicon; + uint32_t flags; + if ((io_segpath = grn_io_path(ii->seg)) && *io_segpath != '\0') { + if (!(segpath = GRN_STRDUP(io_segpath))) { + ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%-.256s>", io_segpath); + return GRN_NO_MEMORY_AVAILABLE; + } + if ((io_chunkpath = grn_io_path(ii->chunk)) && *io_chunkpath != '\0') { + if (!(chunkpath = GRN_STRDUP(io_chunkpath))) { + ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%-.256s>", io_chunkpath); + return GRN_NO_MEMORY_AVAILABLE; + } + } else { + chunkpath = NULL; + } + } else { + segpath = NULL; + } + lexicon = ii->lexicon; + flags = ii->header->flags; + if ((rc = grn_io_close(ctx, ii->seg))) { goto exit; } + if ((rc = grn_io_close(ctx, ii->chunk))) { goto exit; } + ii->seg = NULL; + ii->chunk = NULL; + if (segpath && (rc = grn_io_remove(ctx, segpath))) { goto exit; } + if (chunkpath && (rc = grn_io_remove(ctx, chunkpath))) { goto exit; } + if (!_grn_ii_create(ctx, ii, segpath, lexicon, flags)) { + rc = GRN_UNKNOWN_ERROR; + } +exit: + if (segpath) { GRN_FREE(segpath); } + if (chunkpath) { GRN_FREE(chunkpath); } + return rc; +} + +grn_ii * +grn_ii_open(grn_ctx *ctx, const char *path, grn_obj *lexicon) +{ + grn_io *seg, *chunk; + grn_ii *ii; + char path2[PATH_MAX]; + struct grn_ii_header *header; + uint32_t io_type; + grn_table_flags lflags; + grn_encoding encoding; + grn_obj *tokenizer; + if (grn_table_get_info(ctx, lexicon, &lflags, &encoding, &tokenizer, + NULL, NULL)) { + return NULL; + } + if (strlen(path) + 6 >= PATH_MAX) { return NULL; } + grn_strcpy(path2, PATH_MAX, path); + grn_strcat(path2, PATH_MAX, ".c"); + seg = grn_io_open(ctx, path, grn_io_auto); + if (!seg) { return NULL; } + chunk = grn_io_open(ctx, path2, grn_io_auto); + if (!chunk) { + grn_io_close(ctx, seg); + return NULL; + } + header = grn_io_header(seg); + io_type = grn_io_get_type(seg); + if (io_type != GRN_COLUMN_INDEX) { + ERR(GRN_INVALID_FORMAT, + "[column][index] file type must be %#04x: <%#04x>", + GRN_COLUMN_INDEX, io_type); + grn_io_close(ctx, seg); + grn_io_close(ctx, chunk); + return NULL; + } + if (!(ii = GRN_MALLOCN(grn_ii, 1))) { + grn_io_close(ctx, seg); + grn_io_close(ctx, chunk); + return NULL; + } + GRN_DB_OBJ_SET_TYPE(ii, GRN_COLUMN_INDEX); + ii->seg = seg; + ii->chunk = chunk; + ii->lexicon = lexicon; + ii->lflags = lflags; + ii->encoding = encoding; + ii->header = header; + ii->n_elements = 2; + if ((header->flags & GRN_OBJ_WITH_SECTION)) { ii->n_elements++; } + if ((header->flags & GRN_OBJ_WITH_WEIGHT)) { ii->n_elements++; } + if ((header->flags & GRN_OBJ_WITH_POSITION)) { ii->n_elements++; } + return ii; +} + +grn_rc +grn_ii_close(grn_ctx *ctx, grn_ii *ii) +{ + grn_rc rc; + if (!ii) { return GRN_INVALID_ARGUMENT; } + if ((rc = grn_io_close(ctx, ii->seg))) { return rc; } + if ((rc = grn_io_close(ctx, ii->chunk))) { return rc; } + GRN_FREE(ii); + /* + { + int i; + for (i = 0; i < 32; i++) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "new[%d]=%d free[%d]=%d", + i, new_histogram[i], + i, free_histogram[i]); + } + } + */ + return rc; +} + +grn_rc +grn_ii_info(grn_ctx *ctx, grn_ii *ii, uint64_t *seg_size, uint64_t *chunk_size) +{ + grn_rc rc; + + if (seg_size) { + if ((rc = grn_io_size(ctx, ii->seg, seg_size))) { + return rc; + } + } + + if (chunk_size) { + if ((rc = grn_io_size(ctx, ii->chunk, chunk_size))) { + return rc; + } + } + + return GRN_SUCCESS; +} + +grn_column_flags +grn_ii_get_flags(grn_ctx *ctx, grn_ii *ii) +{ + if (!ii) { + return 0; + } + + return ii->header->flags; +} + +uint32_t +grn_ii_get_n_elements(grn_ctx *ctx, grn_ii *ii) +{ + if (!ii) { + return 0; + } + + return ii->n_elements; +} + +void +grn_ii_expire(grn_ctx *ctx, grn_ii *ii) +{ + /* + grn_io_expire(ctx, ii->seg, 128, 1000000); + */ + grn_io_expire(ctx, ii->chunk, 0, 1000000); +} + +grn_rc +grn_ii_flush(grn_ctx *ctx, grn_ii *ii) +{ + grn_rc rc; + + rc = grn_io_flush(ctx, ii->seg); + if (rc == GRN_SUCCESS) { + rc = grn_io_flush(ctx, ii->chunk); + } + + return rc; +} + +size_t +grn_ii_get_disk_usage(grn_ctx *ctx, grn_ii *ii) +{ + size_t usage; + + usage = grn_io_get_disk_usage(ctx, ii->seg); + usage += grn_io_get_disk_usage(ctx, ii->chunk); + + return usage; +} + +#define BIT11_01(x) ((x >> 1) & 0x7ff) +#define BIT31_12(x) (x >> 12) + +grn_rc +grn_ii_update_one(grn_ctx *ctx, grn_ii *ii, grn_id tid, grn_ii_updspec *u, grn_hash *h) +{ + buffer *b; + uint8_t *bs; + buffer_rec *br = NULL; + buffer_term *bt; + uint32_t pseg = 0, pos = 0, size, *a; + if (!tid) { return ctx->rc; } + if (!u->tf || !u->sid) { return grn_ii_delete_one(ctx, ii, tid, u, h); } + if (u->sid > ii->header->smax) { ii->header->smax = u->sid; } + if (!(a = array_get(ctx, ii, tid))) { + DEFINE_NAME(ii); + MERR("[ii][update][one] failed to allocate an array: " + "<%.*s>: " + "<%u>:<%u>:<%u>", + name_size, name, + u->rid, u->sid, tid); + return ctx->rc; + } + if (!(bs = encode_rec(ctx, ii, u, &size, 0))) { + DEFINE_NAME(ii); + MERR("[ii][update][one] failed to encode a record: " + "<%.*s>: " + "<%u>:<%u>:<%u>", + name_size, name, + u->rid, u->sid, tid); + goto exit; + } + for (;;) { + if (a[0]) { + if (!(a[0] & 1)) { + pos = a[0]; + if ((pseg = buffer_open(ctx, ii, pos, &bt, &b)) == GRN_II_PSEG_NOT_ASSIGNED) { + DEFINE_NAME(ii); + MERR("[ii][update][one] failed to allocate a buffer: " + "<%.*s>: " + "<%u>:<%u>:<%u>: " + "segment:<%u>", + name_size, name, + u->rid, u->sid, tid, + pos); + goto exit; + } + if (b->header.buffer_free < size) { + int bfb = b->header.buffer_free; + GRN_LOG(ctx, GRN_LOG_DEBUG, "flushing a[0]=%d seg=%d(%p) free=%d", + a[0], LSEG(a[0]), b, b->header.buffer_free); + buffer_close(ctx, ii, pseg); + if (SPLIT_COND(ii, b)) { + /*((S_SEGMENT - sizeof(buffer_header) + ii->header->bmax - + b->header.nterms * sizeof(buffer_term)) * 4 < + b->header.chunk_size)*/ + GRN_LOG(ctx, GRN_LOG_DEBUG, + "nterms=%d chunk=%d total=%" GRN_FMT_INT64U, + b->header.nterms, + b->header.chunk_size, + ii->header->total_chunk_size >> 10); + buffer_split(ctx, ii, LSEG(pos), h); + if (ctx->rc != GRN_SUCCESS) { + DEFINE_NAME(ii); + ERR(ctx->rc, + "[ii][update][one] failed to split a buffer: " + "<%.*s>: " + "<%u>:<%u><%u>: " + "segment:<%u>", + name_size, name, + u->rid, u->sid, tid, + pos); + goto exit; + } + continue; + } + buffer_flush(ctx, ii, LSEG(pos), h); + if (ctx->rc != GRN_SUCCESS) { + DEFINE_NAME(ii); + ERR(ctx->rc, + "[ii][update][one] failed to flush a buffer: " + "<%.*s>: " + "<%u>:<%u><%u>: " + "segment:<%u>", + name_size, name, + u->rid, u->sid, tid, + pos); + goto exit; + } + if (a[0] != pos) { + GRN_LOG(ctx, GRN_LOG_DEBUG, + "grn_ii_update_one: a[0] changed %d->%d", a[0], pos); + continue; + } + if ((pseg = buffer_open(ctx, ii, pos, &bt, &b)) == GRN_II_PSEG_NOT_ASSIGNED) { + GRN_LOG(ctx, GRN_LOG_CRIT, "buffer not found a[0]=%d", a[0]); + { + DEFINE_NAME(ii); + MERR("[ii][update][one] failed to reallocate a buffer: " + "<%.*s>: " + "<%u>:<%u>:<%u>: " + "segment:<%u>, new-segment:<%u>", + name_size, name, + u->rid, u->sid, tid, + pos, a[0]); + } + goto exit; + } + GRN_LOG(ctx, GRN_LOG_DEBUG, + "flushed a[0]=%d seg=%d(%p) free=%d->%d nterms=%d v=%d", + a[0], LSEG(a[0]), b, bfb, b->header.buffer_free, + b->header.nterms, b->header.nterms_void); + if (b->header.buffer_free < size) { + DEFINE_NAME(ii); + MERR("[ii][update][one] buffer is full: " + "<%.*s>: " + "<%u>:<%u><%u>: " + "segment:<%u>, new-segment:<%u>, free:<%u>, required:<%u>", + name_size, name, + u->rid, u->sid, tid, + pos, a[0], b->header.buffer_free, size); + buffer_close(ctx, ii, pseg); + /* todo: direct merge */ + goto exit; + } + } + b->header.buffer_free -= size; + br = (buffer_rec *)(((byte *)&b->terms[b->header.nterms]) + + b->header.buffer_free); + } else { + grn_ii_updspec u2; + uint32_t size2 = 0, v = a[0]; + struct _grn_ii_pos pos2; + pos2.pos = a[1]; + pos2.next = NULL; + u2.pos = &pos2; + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + u2.rid = BIT31_12(v); + u2.sid = BIT11_01(v); + } else { + u2.rid = v >> 1; + u2.sid = 1; + } + u2.tf = 1; + u2.weight = 0; + if (u2.rid != u->rid || u2.sid != u->sid) { + uint8_t *bs2 = encode_rec(ctx, ii, &u2, &size2, 0); + if (!bs2) { + DEFINE_NAME(ii); + MERR("[ii][update][one] failed to encode a record2: " + "<%.*s>: " + "<%u>:<%u>:<%u>", + name_size, name, + u2.rid, u2.sid, tid); + goto exit; + } + pseg = buffer_new(ctx, ii, size + size2, &pos, &bt, &br, &b, tid, h); + if (pseg == GRN_II_PSEG_NOT_ASSIGNED) { + GRN_FREE(bs2); + { + DEFINE_NAME(ii); + MERR("[ii][update][one] failed to create a buffer2: " + "<%.*s>: " + "<%u>:<%u>:<%u>: " + "size:<%u>", + name_size, name, + u2.rid, u2.sid, tid, + size + size2); + } + goto exit; + } + bt->tid = tid; + bt->size_in_chunk = 0; + bt->pos_in_chunk = 0; + bt->size_in_buffer = 0; + bt->pos_in_buffer = 0; + buffer_put(ctx, ii, b, bt, br, bs2, &u2, size2); + if (ctx->rc != GRN_SUCCESS) { + GRN_FREE(bs2); + buffer_close(ctx, ii, pseg); + { + DEFINE_NAME(ii); + MERR("[ii][update][one] failed to put to buffer: " + "<%.*s>: " + "<%u>:<%u>:<%u>", + name_size, name, + u2.rid, u2.sid, tid); + } + goto exit; + } + br = (buffer_rec *)(((byte *)br) + size2); + GRN_FREE(bs2); + } + } + } + break; + } + if (!br) { + if (u->tf == 1 && u->weight == 0) { + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + if (u->rid < 0x100000 && u->sid < 0x800) { + a[0] = (u->rid << 12) + (u->sid << 1) + 1; + a[1] = u->pos->pos; + goto exit; + } + } else { + a[0] = (u->rid << 1) + 1; + a[1] = u->pos->pos; + goto exit; + } + } + pseg = buffer_new(ctx, ii, size, &pos, &bt, &br, &b, tid, h); + if (pseg == GRN_II_PSEG_NOT_ASSIGNED) { + DEFINE_NAME(ii); + MERR("[ii][update][one] failed to create a buffer: " + "<%.*s>: " + "<%u>:<%u>:<%u>: " + "size:<%u>", + name_size, name, + u->rid, u->sid, tid, + size); + goto exit; + } + bt->tid = tid; + bt->size_in_chunk = 0; + bt->pos_in_chunk = 0; + bt->size_in_buffer = 0; + bt->pos_in_buffer = 0; + } + buffer_put(ctx, ii, b, bt, br, bs, u, size); + buffer_close(ctx, ii, pseg); + if (!a[0] || (a[0] & 1)) { a[0] = pos; } +exit : + array_unref(ii, tid); + if (bs) { GRN_FREE(bs); } + if (u->tf != u->atf) { + grn_obj *source_table; + char source_table_name[GRN_TABLE_MAX_KEY_SIZE]; + int source_table_name_size; + char term[GRN_TABLE_MAX_KEY_SIZE]; + int term_size; + + source_table = grn_ctx_at(ctx, DB_OBJ(ii)->range); + if (source_table) { + source_table_name_size = grn_obj_name(ctx, + source_table, + source_table_name, + GRN_TABLE_MAX_KEY_SIZE); + } else { + grn_strcpy(source_table_name, GRN_TABLE_MAX_KEY_SIZE, "(null)"); + source_table_name_size = strlen(source_table_name); + } + term_size = grn_table_get_key(ctx, ii->lexicon, tid, + term, GRN_TABLE_MAX_KEY_SIZE); + { + DEFINE_NAME(ii); + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][update][one] too many postings: " + "<%.*s>: " + "record:<%.*s>(%d), " + "n-postings:<%d>, " + "n-discarded-postings:<%d>, " + "term:<%d>(<%.*s>)", + name_size, name, + source_table_name_size, source_table_name, + u->rid, + u->atf, + u->atf - u->tf, + tid, term_size, term); + } + } + grn_ii_expire(ctx, ii); + return ctx->rc; +} + +grn_rc +grn_ii_delete_one(grn_ctx *ctx, grn_ii *ii, grn_id tid, grn_ii_updspec *u, grn_hash *h) +{ + buffer *b; + uint8_t *bs = NULL; + buffer_rec *br; + buffer_term *bt; + uint32_t pseg, size, *a; + if (!tid) { return ctx->rc; } + if (!(a = array_at(ctx, ii, tid))) { + return ctx->rc; + } + for (;;) { + if (!a[0]) { goto exit; } + if (a[0] & 1) { + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + uint32_t rid = BIT31_12(a[0]); + uint32_t sid = BIT11_01(a[0]); + if (u->rid == rid && (!u->sid || u->sid == sid)) { + a[0] = 0; + lexicon_delete(ctx, ii, tid, h); + } + } else { + uint32_t rid = a[0] >> 1; + if (u->rid == rid) { + a[0] = 0; + lexicon_delete(ctx, ii, tid, h); + } + } + goto exit; + } + if (!(bs = encode_rec(ctx, ii, u, &size, 1))) { + DEFINE_NAME(ii); + MERR("[ii][delete][one] failed to encode a record: " + "<%.*s>: " + "<%u>:<%u>:<%u>", + name_size, name, + u->rid, u->sid, tid); + goto exit; + } + if ((pseg = buffer_open(ctx, ii, a[0], &bt, &b)) == GRN_II_PSEG_NOT_ASSIGNED) { + DEFINE_NAME(ii); + MERR("[ii][delete][one] failed to allocate a buffer: " + "<%.*s>: " + "<%u>:<%u><%u>: " + "position:<%u>", + name_size, name, + u->rid, u->sid, tid, + a[0]); + goto exit; + } + if (b->header.buffer_free < size) { + uint32_t _a = a[0]; + GRN_LOG(ctx, GRN_LOG_DEBUG, "flushing! b=%p free=%d, seg(%d)", + b, b->header.buffer_free, LSEG(a[0])); + buffer_close(ctx, ii, pseg); + buffer_flush(ctx, ii, LSEG(a[0]), h); + if (ctx->rc != GRN_SUCCESS) { + DEFINE_NAME(ii); + ERR(ctx->rc, + "[ii][delete][one] failed to flush a buffer: " + "<%.*s>: " + "<%u>:<%u><%u>: " + "position:<%u>", + name_size, name, + u->rid, u->sid, tid, + a[0]); + goto exit; + } + if (a[0] != _a) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "grn_ii_delete_one: a[0] changed %d->%d)", + a[0], _a); + continue; + } + if ((pseg = buffer_open(ctx, ii, a[0], &bt, &b)) == GRN_II_PSEG_NOT_ASSIGNED) { + DEFINE_NAME(ii); + MERR("[ii][delete][one] failed to reallocate a buffer: " + "<%.*s>: " + "<%u>:<%u><%u>: " + "position:<%u>", + name_size, name, + u->rid, u->sid, tid, + a[0]); + goto exit; + } + GRN_LOG(ctx, GRN_LOG_DEBUG, "flushed! b=%p free=%d, seg(%d)", + b, b->header.buffer_free, LSEG(a[0])); + if (b->header.buffer_free < size) { + DEFINE_NAME(ii); + MERR("[ii][delete][one] buffer is full: " + "<%.*s>: " + "<%u>:<%u><%u>: " + "segment:<%u>, free:<%u>, required:<%u>", + name_size, name, + u->rid, u->sid, tid, + a[0], b->header.buffer_free, size); + buffer_close(ctx, ii, pseg); + goto exit; + } + } + + b->header.buffer_free -= size; + br = (buffer_rec *)(((byte *)&b->terms[b->header.nterms]) + b->header.buffer_free); + buffer_put(ctx, ii, b, bt, br, bs, u, size); + buffer_close(ctx, ii, pseg); + break; + } +exit : + array_unref(ii, tid); + if (bs) { GRN_FREE(bs); } + return ctx->rc; +} + +#define CHUNK_USED 1 +#define BUFFER_USED 2 +#define SOLE_DOC_USED 4 +#define SOLE_POS_USED 8 + +struct _grn_ii_cursor { + grn_db_obj obj; + grn_ctx *ctx; + grn_ii *ii; + grn_id id; + grn_posting *post; + + grn_id min; /* Minimum record ID */ + grn_id max; + grn_posting pc; + grn_posting pb; + + uint32_t cdf; /* Document frequency */ + uint32_t *cdp; + uint32_t *crp; /* Record ID */ + uint32_t *csp; /* Section ID */ + uint32_t *ctp; /* Term frequency */ + uint32_t *cwp; /* Weight */ + uint32_t *cpp; /* Position */ + + uint8_t *bp; + + int nelements; + uint32_t nchunks; + uint32_t curr_chunk; + chunk_info *cinfo; + grn_io_win iw; + uint8_t *cp; + uint8_t *cpe; + datavec rdv[MAX_N_ELEMENTS + 1]; + + struct grn_ii_buffer *buf; + uint16_t stat; + uint16_t nextb; + uint32_t buffer_pseg; + int flags; + uint32_t *ppseg; + + int weight; + + uint32_t prev_chunk_rid; +}; + +static grn_bool +buffer_is_reused(grn_ctx *ctx, grn_ii *ii, grn_ii_cursor *c) +{ + if (*c->ppseg != c->buffer_pseg) { + uint32_t i; + for (i = ii->header->bgqtail; i != ii->header->bgqhead; + i = (i + 1) & (GRN_II_BGQSIZE - 1)) { + if (ii->header->bgqbody[i] == c->buffer_pseg) { return GRN_FALSE; } + } + return GRN_TRUE; + } + return GRN_FALSE; +} + +static int +chunk_is_reused(grn_ctx *ctx, grn_ii *ii, grn_ii_cursor *c, uint32_t offset, uint32_t size) +{ + if (*c->ppseg != c->buffer_pseg) { + uint32_t i, m, gseg; + if (size > S_CHUNK) { return 1; } + if (size > (1 << GRN_II_W_LEAST_CHUNK)) { + int es = size - 1; + GRN_BIT_SCAN_REV(es, m); + m++; + } else { + m = GRN_II_W_LEAST_CHUNK; + } + gseg = ii->header->garbages[m - GRN_II_W_LEAST_CHUNK]; + while (gseg != GRN_II_PSEG_NOT_ASSIGNED) { + grn_io_win iw; + grn_ii_ginfo *ginfo = WIN_MAP(ii->chunk, ctx, &iw, gseg, 0, S_GARBAGE, + grn_io_rdwr); + if (!ginfo) { break; } + for (i = 0; i < ginfo->nrecs; i++) { + if (ginfo->recs[i] == offset) { + grn_io_win_unmap(&iw); + return 0; + } + } + gseg = ginfo->next; + grn_io_win_unmap(&iw); + } + return 1; + } + return 0; +} + +#define GRN_II_CURSOR_CMP(c1,c2) \ + (((c1)->post->rid > (c2)->post->rid) || \ + (((c1)->post->rid == (c2)->post->rid) && \ + (((c1)->post->sid > (c2)->post->sid) || \ + (((c1)->post->sid == (c2)->post->sid) && \ + ((c1)->post->pos > (c2)->post->pos))))) + +grn_ii_cursor * +grn_ii_cursor_open(grn_ctx *ctx, grn_ii *ii, grn_id tid, + grn_id min, grn_id max, int nelements, int flags) +{ + grn_ii_cursor *c = NULL; + uint32_t pos, *a; + if (!(a = array_at(ctx, ii, tid))) { return NULL; } + for (;;) { + c = NULL; + if (!(pos = a[0])) { goto exit; } + if (!(c = GRN_MALLOC(sizeof(grn_ii_cursor)))) { goto exit; } + memset(c, 0, sizeof(grn_ii_cursor)); + c->ctx = ctx; + c->ii = ii; + c->id = tid; + c->min = min; + c->max = max; + c->nelements = nelements; + c->flags = flags; + c->weight = 0; + if (pos & 1) { + c->stat = 0; + if ((ii->header->flags & GRN_OBJ_WITH_SECTION)) { + c->pb.rid = BIT31_12(pos); + c->pb.sid = BIT11_01(pos); + } else { + c->pb.rid = pos >> 1; + c->pb.sid = 1; + } + c->pb.tf = 1; + c->pb.weight = 0; + c->pb.pos = a[1]; + } else { + uint32_t chunk; + buffer_term *bt; + c->buffer_pseg = buffer_open(ctx, ii, pos, &bt, &c->buf); + if (c->buffer_pseg == GRN_II_PSEG_NOT_ASSIGNED) { + GRN_FREE(c); + c = NULL; + goto exit; + } + c->ppseg = &ii->header->binfo[LSEG(pos)]; + if (bt->size_in_chunk && (chunk = c->buf->header.chunk) != GRN_II_PSEG_NOT_ASSIGNED) { + if (!(c->cp = WIN_MAP(ii->chunk, ctx, &c->iw, chunk, bt->pos_in_chunk, + bt->size_in_chunk, grn_io_rdonly))) { + buffer_close(ctx, ii, c->buffer_pseg); + GRN_FREE(c); + c = NULL; + goto exit; + } + if (buffer_is_reused(ctx, ii, c)) { + grn_ii_cursor_close(ctx, c); + continue; + } + c->cpe = c->cp + bt->size_in_chunk; + if ((bt->tid & CHUNK_SPLIT)) { + int i; + grn_id crid; + GRN_B_DEC(c->nchunks, c->cp); + if (chunk_is_reused(ctx, ii, c, chunk, c->buf->header.chunk_size)) { + grn_ii_cursor_close(ctx, c); + continue; + } + if (!(c->cinfo = GRN_MALLOCN(chunk_info, c->nchunks))) { + buffer_close(ctx, ii, c->buffer_pseg); + grn_io_win_unmap(&c->iw); + GRN_FREE(c); + c = NULL; + goto exit; + } + for (i = 0, crid = GRN_ID_NIL; i < c->nchunks; i++) { + GRN_B_DEC(c->cinfo[i].segno, c->cp); + GRN_B_DEC(c->cinfo[i].size, c->cp); + GRN_B_DEC(c->cinfo[i].dgap, c->cp); + crid += c->cinfo[i].dgap; + if (crid < min) { + c->pc.rid = crid; + c->curr_chunk = i + 1; + } + } + if (chunk_is_reused(ctx, ii, c, chunk, c->buf->header.chunk_size)) { + grn_ii_cursor_close(ctx, c); + continue; + } + } + if ((ii->header->flags & GRN_OBJ_WITH_POSITION)) { + c->rdv[ii->n_elements - 1].flags = ODD; + } + } + c->nextb = bt->pos_in_buffer; + c->stat = CHUNK_USED|BUFFER_USED; + } + if (pos == a[0]) { break; } + grn_ii_cursor_close(ctx, c); + } +exit : + array_unref(ii, tid); + return c; +} + +static inline void +grn_ii_cursor_set_min(grn_ctx *ctx, grn_ii_cursor *c, grn_id min) +{ + if (c->min >= min) { + return; + } + + if (grn_ii_cursor_set_min_enable) { + grn_id old_min = c->min; + c->min = min; + if (c->buf && + c->pc.rid != GRN_ID_NIL && + c->pc.rid < c->min && + c->prev_chunk_rid < c->min && + c->curr_chunk < c->nchunks) { + uint32_t i; + uint32_t skip_chunk = 0; + grn_id rid = c->prev_chunk_rid; + + if (c->curr_chunk > 0) { + i = c->curr_chunk - 1; + } else { + i = 0; + } + for (; i < c->nchunks; i++) { + rid += c->cinfo[i].dgap; + if (rid < c->min) { + skip_chunk = i + 1; + } else { + rid -= c->cinfo[i].dgap; + break; + } + } + if (skip_chunk > c->curr_chunk) { + uint32_t old_chunk = c->curr_chunk; + grn_bool old_chunk_used = (c->stat & CHUNK_USED); + c->pc.rid = rid; + c->pc.rest = 0; + c->prev_chunk_rid = rid - c->cinfo[skip_chunk - 1].dgap; + c->curr_chunk = skip_chunk; + c->crp = c->cdp + c->cdf; + c->stat |= CHUNK_USED; + GRN_LOG(ctx, GRN_LOG_DEBUG, + "[ii][cursor][min] skip: %p: min(%u->%u): chunk(%u->%u): " + "chunk-used(%-.256s->%-.256s)", + c, + old_min, min, + old_chunk, c->curr_chunk, + old_chunk_used ? "true" : "false", + (c->stat & CHUNK_USED) ? "true" : "false"); + } + } + } +} + +typedef struct { + grn_bool include_garbage; +} grn_ii_cursor_next_options; + +static inline grn_posting * +grn_ii_cursor_next_internal(grn_ctx *ctx, grn_ii_cursor *c, + grn_ii_cursor_next_options *options) +{ + const grn_bool include_garbage = options->include_garbage; + if (c->buf) { + for (;;) { + if (c->stat & CHUNK_USED) { + for (;;) { + if (c->crp < c->cdp + c->cdf) { + uint32_t dgap = *c->crp++; + c->pc.rid += dgap; + if (dgap) { c->pc.sid = 0; } + if ((c->ii->header->flags & GRN_OBJ_WITH_SECTION)) { + c->pc.sid += 1 + *c->csp++; + } else { + c->pc.sid = 1; + } + c->cpp += c->pc.rest; + c->pc.rest = c->pc.tf = 1 + *c->ctp++; + if ((c->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { + c->pc.weight = *c->cwp++; + } else { + c->pc.weight = 0; + } + c->pc.pos = 0; + /* + { + static int count = 0; + int tf = c->pc.tf, pos = 0, *pp = (int *)c->cpp; + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + grn_text_itoa(ctx, &buf, c->pc.rid); + GRN_TEXT_PUTC(ctx, &buf, ':'); + grn_text_itoa(ctx, &buf, c->pc.sid); + GRN_TEXT_PUTC(ctx, &buf, ':'); + grn_text_itoa(ctx, &buf, c->pc.tf); + GRN_TEXT_PUTC(ctx, &buf, '('); + while (tf--) { + pos += *pp++; + count++; + grn_text_itoa(ctx, &buf, pos); + if (tf) { GRN_TEXT_PUTC(ctx, &buf, ':'); } + } + GRN_TEXT_PUTC(ctx, &buf, ')'); + GRN_TEXT_PUTC(ctx, &buf, '\0'); + GRN_LOG(ctx, GRN_LOG_DEBUG, "posting(%d):%-.256s", count, GRN_TEXT_VALUE(&buf)); + GRN_OBJ_FIN(ctx, &buf); + } + */ + } else { + if (c->curr_chunk <= c->nchunks) { + if (c->curr_chunk == c->nchunks) { + if (c->cp < c->cpe) { + int decoded_size; + decoded_size = + grn_p_decv(ctx, c->cp, c->cpe - c->cp, + c->rdv, c->ii->n_elements); + if (decoded_size == 0) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][cursor][next][chunk][last] " + "chunk(%d) is changed by another thread " + "while decoding: %p", + c->cinfo[c->curr_chunk].segno, + c); + c->pc.rid = GRN_ID_NIL; + break; + } + if (buffer_is_reused(ctx, c->ii, c)) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][cursor][next][chunk][last] " + "buffer is reused by another thread: %p", + c); + c->pc.rid = GRN_ID_NIL; + break; + } + if (chunk_is_reused(ctx, c->ii, c, + c->buf->header.chunk, + c->buf->header.chunk_size)) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][cursor][next][chunk][last] " + "chunk(%d) is reused by another thread: %p", + c->buf->header.chunk, + c); + c->pc.rid = GRN_ID_NIL; + break; + } + } else { + c->pc.rid = GRN_ID_NIL; + break; + } + } else { + uint8_t *cp; + grn_io_win iw; + uint32_t size = c->cinfo[c->curr_chunk].size; + if (size && (cp = WIN_MAP(c->ii->chunk, ctx, &iw, + c->cinfo[c->curr_chunk].segno, 0, + size, grn_io_rdonly))) { + int decoded_size; + decoded_size = + grn_p_decv(ctx, cp, size, c->rdv, c->ii->n_elements); + grn_io_win_unmap(&iw); + if (decoded_size == 0) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][cursor][next][chunk] " + "chunk(%d) is changed by another thread " + "while decoding: %p", + c->cinfo[c->curr_chunk].segno, + c); + c->pc.rid = GRN_ID_NIL; + break; + } + if (chunk_is_reused(ctx, c->ii, c, + c->cinfo[c->curr_chunk].segno, size)) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][cursor][next][chunk] " + "chunk(%d) is reused by another thread: %p", + c->cinfo[c->curr_chunk].segno, + c); + c->pc.rid = GRN_ID_NIL; + break; + } + } else { + c->pc.rid = GRN_ID_NIL; + break; + } + } + { + int j = 0; + c->cdf = c->rdv[j].data_size; + c->crp = c->cdp = c->rdv[j++].data; + if ((c->ii->header->flags & GRN_OBJ_WITH_SECTION)) { + c->csp = c->rdv[j++].data; + } + c->ctp = c->rdv[j++].data; + if ((c->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { + c->cwp = c->rdv[j++].data; + } + if ((c->ii->header->flags & GRN_OBJ_WITH_POSITION)) { + c->cpp = c->rdv[j].data; + } + } + c->prev_chunk_rid = c->pc.rid; + c->pc.rid = GRN_ID_NIL; + c->pc.sid = 0; + c->pc.rest = 0; + c->curr_chunk++; + continue; + } else { + c->pc.rid = GRN_ID_NIL; + } + } + break; + } + } + if (c->stat & BUFFER_USED) { + for (;;) { + if (c->nextb) { + uint32_t lrid = c->pb.rid, lsid = c->pb.sid; /* for check */ + buffer_rec *br = BUFFER_REC_AT(c->buf, c->nextb); + if (buffer_is_reused(ctx, c->ii, c)) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][cursor][next][buffer] " + "buffer(%d,%d) is reused by another thread: %p", + c->buffer_pseg, *c->ppseg, + c); + c->pb.rid = GRN_ID_NIL; + break; + } + c->bp = GRN_NEXT_ADDR(br); + GRN_B_DEC(c->pb.rid, c->bp); + if ((c->ii->header->flags & GRN_OBJ_WITH_SECTION)) { + GRN_B_DEC(c->pb.sid, c->bp); + } else { + c->pb.sid = 1; + } + if (lrid > c->pb.rid || (lrid == c->pb.rid && lsid >= c->pb.sid)) { + DEFINE_NAME(c->ii); + ERR(GRN_FILE_CORRUPT, + "[ii][broken][cursor][next][buffer] " + "posting in list in buffer isn't sorted: " + "<%.*s>: (%d:%d) -> (%d:%d) (%d->%d)", + name_size, name, + lrid, lsid, + c->pb.rid, c->pb.sid, + c->buffer_pseg, *c->ppseg); + c->pb.rid = GRN_ID_NIL; + break; + } + if (c->pb.rid < c->min) { + c->pb.rid = 0; + if (br->jump > 0 && !BUFFER_REC_DELETED(br)) { + buffer_rec *jump_br = BUFFER_REC_AT(c->buf, br->jump); + if (BUFFER_REC_DELETED(jump_br)) { + c->nextb = br->step; + } else { + uint8_t *jump_bp; + uint32_t jump_rid; + jump_bp = GRN_NEXT_ADDR(jump_br); + GRN_B_DEC(jump_rid, jump_bp); + if (jump_rid < c->min) { + c->nextb = br->jump; + } else { + c->nextb = br->step; + } + } + } else { + c->nextb = br->step; + } + continue; + } + c->nextb = br->step; + GRN_B_DEC(c->pb.tf, c->bp); + if ((c->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { + GRN_B_DEC(c->pb.weight, c->bp); + } else { + c->pb.weight = 0; + } + c->pb.rest = c->pb.tf; + c->pb.pos = 0; + } else { + c->pb.rid = 0; + } + break; + } + } + if (c->pb.rid) { + if (c->pc.rid) { + if (c->pc.rid < c->pb.rid) { + c->stat = CHUNK_USED; + if (include_garbage || (c->pc.tf && c->pc.sid)) { + c->post = &c->pc; + break; + } + } else { + if (c->pb.rid < c->pc.rid) { + c->stat = BUFFER_USED; + if (include_garbage || (c->pb.tf && c->pb.sid)) { + c->post = &c->pb; + break; + } + } else { + if (c->pb.sid) { + if (c->pc.sid < c->pb.sid) { + c->stat = CHUNK_USED; + if (include_garbage || (c->pc.tf && c->pc.sid)) { + c->post = &c->pc; + break; + } + } else { + c->stat = BUFFER_USED; + if (c->pb.sid == c->pc.sid) { c->stat |= CHUNK_USED; } + if (include_garbage || (c->pb.tf)) { + c->post = &c->pb; + break; + } + } + } else { + c->stat = CHUNK_USED; + } + } + } + } else { + c->stat = BUFFER_USED; + if (include_garbage || (c->pb.tf && c->pb.sid)) { + c->post = &c->pb; + break; + } + } + } else { + if (c->pc.rid) { + c->stat = CHUNK_USED; + if (include_garbage || (c->pc.tf && c->pc.sid)) { + c->post = &c->pc; + break; + } + } else { + c->post = NULL; + return NULL; + } + } + } + } else { + if (c->stat & SOLE_DOC_USED) { + c->post = NULL; + return NULL; + } else { + c->post = &c->pb; + c->stat |= SOLE_DOC_USED; + if (c->post->rid < c->min) { + c->post = NULL; + return NULL; + } + } + } + return c->post; +} + +grn_posting * +grn_ii_cursor_next(grn_ctx *ctx, grn_ii_cursor *c) +{ + grn_ii_cursor_next_options options = { + .include_garbage = GRN_FALSE + }; + return grn_ii_cursor_next_internal(ctx, c, &options); +} + +grn_posting * +grn_ii_cursor_next_pos(grn_ctx *ctx, grn_ii_cursor *c) +{ + uint32_t gap; + if ((c->ii->header->flags & GRN_OBJ_WITH_POSITION)) { + if (c->nelements == c->ii->n_elements) { + if (c->buf) { + if (c->post == &c->pc) { + if (c->pc.rest) { + c->pc.rest--; + c->pc.pos += *c->cpp++; + } else { + return NULL; + } + } else if (c->post == &c->pb) { + if (buffer_is_reused(ctx, c->ii, c)) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][cursor][next][pos][buffer] " + "buffer(%d,%d) is reused by another thread: %p", + c->buffer_pseg, *c->ppseg, + c); + return NULL; + } + if (c->pb.rest) { + c->pb.rest--; + GRN_B_DEC(gap, c->bp); + c->pb.pos += gap; + } else { + return NULL; + } + } else { + return NULL; + } + } else { + if (c->stat & SOLE_POS_USED) { + return NULL; + } else { + c->stat |= SOLE_POS_USED; + } + } + } + } else { + if (c->stat & SOLE_POS_USED) { + return NULL; + } else { + c->stat |= SOLE_POS_USED; + } + } + return c->post; +} + +grn_rc +grn_ii_cursor_close(grn_ctx *ctx, grn_ii_cursor *c) +{ + if (!c) { return GRN_INVALID_ARGUMENT; } + datavec_fin(ctx, c->rdv); + if (c->cinfo) { GRN_FREE(c->cinfo); } + if (c->buf) { buffer_close(ctx, c->ii, c->buffer_pseg); } + if (c->cp) { grn_io_win_unmap(&c->iw); } + GRN_FREE(c); + return GRN_SUCCESS; +} + +uint32_t +grn_ii_get_chunksize(grn_ctx *ctx, grn_ii *ii, grn_id tid) +{ + uint32_t res, pos, *a; + a = array_at(ctx, ii, tid); + if (!a) { return 0; } + if ((pos = a[0])) { + if (pos & 1) { + res = 0; + } else { + buffer *buf; + uint32_t pseg; + buffer_term *bt; + if ((pseg = buffer_open(ctx, ii, pos, &bt, &buf)) == GRN_II_PSEG_NOT_ASSIGNED) { + res = 0; + } else { + res = bt->size_in_chunk; + buffer_close(ctx, ii, pseg); + } + } + } else { + res = 0; + } + array_unref(ii, tid); + return res; +} + +uint32_t +grn_ii_estimate_size(grn_ctx *ctx, grn_ii *ii, grn_id tid) +{ + uint32_t res, pos, *a; + a = array_at(ctx, ii, tid); + if (!a) { return 0; } + if ((pos = a[0])) { + if (pos & 1) { + res = 1; + } else { + buffer *buf; + uint32_t pseg; + buffer_term *bt; + if ((pseg = buffer_open(ctx, ii, pos, &bt, &buf)) == GRN_II_PSEG_NOT_ASSIGNED) { + res = 0; + } else { + res = a[1] + bt->size_in_buffer + 2; + buffer_close(ctx, ii, pseg); + } + } + } else { + res = 0; + } + array_unref(ii, tid); + return res; +} + +int +grn_ii_entry_info(grn_ctx *ctx, grn_ii *ii, grn_id tid, unsigned int *a, + unsigned int *chunk, unsigned int *chunk_size, + unsigned int *buffer_free, + unsigned int *nterms, unsigned int *nterms_void, + unsigned int *bt_tid, + unsigned int *size_in_chunk, unsigned int *pos_in_chunk, + unsigned int *size_in_buffer, unsigned int *pos_in_buffer) +{ + buffer *b; + buffer_term *bt; + uint32_t pseg, *ap; + ERRCLR(NULL); + ap = array_at(ctx, ii, tid); + if (!ap) { return 0; } + a[0] = *ap; + array_unref(ii, tid); + if (!a[0]) { return 1; } + if (a[0] & 1) { return 2; } + if ((pseg = buffer_open(ctx, ii, a[0], &bt, &b)) == GRN_II_PSEG_NOT_ASSIGNED) { return 3; } + *chunk = b->header.chunk; + *chunk_size = b->header.chunk_size; + *buffer_free = b->header.buffer_free; + *nterms = b->header.nterms; + *bt_tid = bt->tid; + *size_in_chunk = bt->size_in_chunk; + *pos_in_chunk = bt->pos_in_chunk; + *size_in_buffer = bt->size_in_buffer; + *pos_in_buffer = bt->pos_in_buffer; + buffer_close(ctx, ii, pseg); + return 4; +} + +const char * +grn_ii_path(grn_ii *ii) +{ + return grn_io_path(ii->seg); +} + +uint32_t +grn_ii_max_section(grn_ii *ii) +{ + return ii->header->smax; +} + +grn_obj * +grn_ii_lexicon(grn_ii *ii) +{ + return ii->lexicon; +} + +/* private classes */ + +/* b-heap */ + +typedef struct { + int n_entries; + int n_bins; + grn_ii_cursor **bins; +} cursor_heap; + +static inline cursor_heap * +cursor_heap_open(grn_ctx *ctx, int max) +{ + cursor_heap *h = GRN_MALLOC(sizeof(cursor_heap)); + if (!h) { return NULL; } + h->bins = GRN_MALLOC(sizeof(grn_ii_cursor *) * max); + if (!h->bins) { + GRN_FREE(h); + return NULL; + } + h->n_entries = 0; + h->n_bins = max; + return h; +} + +static inline grn_rc +cursor_heap_push(grn_ctx *ctx, cursor_heap *h, grn_ii *ii, grn_id tid, uint32_t offset2, + int weight, grn_id min) +{ + int n, n2; + grn_ii_cursor *c, *c2; + if (h->n_entries >= h->n_bins) { + int max = h->n_bins * 2; + grn_ii_cursor **bins = GRN_REALLOC(h->bins, sizeof(grn_ii_cursor *) * max); + GRN_LOG(ctx, GRN_LOG_DEBUG, "expanded cursor_heap to %d,%p", max, bins); + if (!bins) { return GRN_NO_MEMORY_AVAILABLE; } + h->n_bins = max; + h->bins = bins; + } + { + if (!(c = grn_ii_cursor_open(ctx, ii, tid, min, GRN_ID_MAX, + ii->n_elements, 0))) { + GRN_LOG(ctx, GRN_LOG_ERROR, "cursor open failed"); + return ctx->rc; + } + if (!grn_ii_cursor_next(ctx, c)) { + grn_ii_cursor_close(ctx, c); + return GRN_END_OF_DATA; + } + if (!grn_ii_cursor_next_pos(ctx, c)) { + if (grn_logger_pass(ctx, GRN_LOG_ERROR)) { + char token[GRN_TABLE_MAX_KEY_SIZE]; + int token_size; + token_size = grn_table_get_key(ctx, + c->ii->lexicon, + c->id, + &token, + GRN_TABLE_MAX_KEY_SIZE); + GRN_LOG(ctx, GRN_LOG_ERROR, + "[ii][cursor][heap][push] invalid cursor: " + "%p: token:<%.*s>(%u)", + c, token_size, token, c->id); + } + grn_ii_cursor_close(ctx, c); + return GRN_END_OF_DATA; + } + if (weight) { + c->weight = weight; + } + n = h->n_entries++; + while (n) { + n2 = (n - 1) >> 1; + c2 = h->bins[n2]; + if (GRN_II_CURSOR_CMP(c, c2)) { break; } + h->bins[n] = c2; + n = n2; + } + h->bins[n] = c; + } + return GRN_SUCCESS; +} + +static inline grn_rc +cursor_heap_push2(cursor_heap *h) +{ + grn_rc rc = GRN_SUCCESS; + return rc; +} + +static inline grn_ii_cursor * +cursor_heap_min(cursor_heap *h) +{ + return h->n_entries ? h->bins[0] : NULL; +} + +static inline void +cursor_heap_recalc_min(cursor_heap *h) +{ + int n = 0, n1, n2, m; + if ((m = h->n_entries) > 1) { + grn_ii_cursor *c = h->bins[0], *c1, *c2; + for (;;) { + n1 = n * 2 + 1; + n2 = n1 + 1; + c1 = n1 < m ? h->bins[n1] : NULL; + c2 = n2 < m ? h->bins[n2] : NULL; + if (c1 && GRN_II_CURSOR_CMP(c, c1)) { + if (c2 && GRN_II_CURSOR_CMP(c, c2) && GRN_II_CURSOR_CMP(c1, c2)) { + h->bins[n] = c2; + n = n2; + } else { + h->bins[n] = c1; + n = n1; + } + } else { + if (c2 && GRN_II_CURSOR_CMP(c, c2)) { + h->bins[n] = c2; + n = n2; + } else { + h->bins[n] = c; + break; + } + } + } + } +} + +static inline void +cursor_heap_pop(grn_ctx *ctx, cursor_heap *h, grn_id min) +{ + if (h->n_entries) { + grn_ii_cursor *c = h->bins[0]; + grn_ii_cursor_set_min(ctx, c, min); + if (!grn_ii_cursor_next(ctx, c)) { + grn_ii_cursor_close(ctx, c); + h->bins[0] = h->bins[--h->n_entries]; + } else if (!grn_ii_cursor_next_pos(ctx, c)) { + if (grn_logger_pass(ctx, GRN_LOG_ERROR)) { + char token[GRN_TABLE_MAX_KEY_SIZE]; + int token_size; + token_size = grn_table_get_key(ctx, + c->ii->lexicon, + c->id, + &token, + GRN_TABLE_MAX_KEY_SIZE); + GRN_LOG(ctx, GRN_LOG_ERROR, + "[ii][cursor][heap][pop] invalid cursor: " + "%p: token:<%.*s>(%u)", + c, token_size, token, c->id); + } + grn_ii_cursor_close(ctx, c); + h->bins[0] = h->bins[--h->n_entries]; + } + if (h->n_entries > 1) { cursor_heap_recalc_min(h); } + } +} + +static inline void +cursor_heap_pop_pos(grn_ctx *ctx, cursor_heap *h) +{ + if (h->n_entries) { + grn_ii_cursor *c = h->bins[0]; + if (!grn_ii_cursor_next_pos(ctx, c)) { + if (!grn_ii_cursor_next(ctx, c)) { + grn_ii_cursor_close(ctx, c); + h->bins[0] = h->bins[--h->n_entries]; + } else if (!grn_ii_cursor_next_pos(ctx, c)) { + if (grn_logger_pass(ctx, GRN_LOG_ERROR)) { + char token[GRN_TABLE_MAX_KEY_SIZE]; + int token_size; + token_size = grn_table_get_key(ctx, + c->ii->lexicon, + c->id, + &token, + GRN_TABLE_MAX_KEY_SIZE); + GRN_LOG(ctx, GRN_LOG_ERROR, + "[ii][cursor][heap][pop][position] invalid cursor: " + "%p: token:<%.*s>(%u)", + c, token_size, token, c->id); + } + grn_ii_cursor_close(ctx, c); + h->bins[0] = h->bins[--h->n_entries]; + } + } + if (h->n_entries > 1) { cursor_heap_recalc_min(h); } + } +} + +static inline void +cursor_heap_close(grn_ctx *ctx, cursor_heap *h) +{ + int i; + if (!h) { return; } + for (i = h->n_entries; i--;) { grn_ii_cursor_close(ctx, h->bins[i]); } + GRN_FREE(h->bins); + GRN_FREE(h); +} + +/* update */ +#ifdef USE_VGRAM + +inline static grn_rc +index_add(grn_ctx *ctx, grn_id rid, grn_obj *lexicon, grn_ii *ii, grn_vgram *vgram, + const char *value, size_t value_len) +{ + grn_hash *h; + unsigned int token_flags = 0; + grn_token_cursor *token_cursor; + grn_ii_updspec **u; + grn_id tid, *tp; + grn_rc r, rc = GRN_SUCCESS; + grn_vgram_buf *sbuf = NULL; + if (!rid) { return GRN_INVALID_ARGUMENT; } + if (!(token_cursor = grn_token_cursor_open(ctx, lexicon, value, value_len, + GRN_TOKEN_ADD, token_flags))) { + return GRN_NO_MEMORY_AVAILABLE; + } + if (vgram) { sbuf = grn_vgram_buf_open(value_len); } + h = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_ii_updspec *), + GRN_HASH_TINY); + if (!h) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create on index_add failed !"); + grn_token_cursor_close(ctx, token_cursor); + if (sbuf) { grn_vgram_buf_close(sbuf); } + return GRN_NO_MEMORY_AVAILABLE; + } + while (!token_cursor->status) { + (tid = grn_token_cursor_next(ctx, token_cursor)); + if (tid) { + if (!grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **) &u, NULL)) { + break; + } + if (!*u) { + if (!(*u = grn_ii_updspec_open(ctx, rid, 1))) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "grn_ii_updspec_open on index_add failed!"); + goto exit; + } + } + if (grn_ii_updspec_add(ctx, *u, token_cursor->pos, 0)) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "grn_ii_updspec_add on index_add failed!"); + goto exit; + } + if (sbuf) { grn_vgram_buf_add(sbuf, tid); } + } + } + grn_token_cursor_close(ctx, token_cursor); + // todo : support vgram + // if (sbuf) { grn_vgram_update(vgram, rid, sbuf, (grn_set *)h); } + GRN_HASH_EACH(ctx, h, id, &tp, NULL, &u, { + if ((r = grn_ii_update_one(ctx, ii, *tp, *u, h))) { rc = r; } + grn_ii_updspec_close(ctx, *u); + }); + grn_hash_close(ctx, h); + if (sbuf) { grn_vgram_buf_close(sbuf); } + return rc; +exit: + grn_hash_close(ctx, h); + grn_token_cursor_close(ctx, token_cursor); + if (sbuf) { grn_vgram_buf_close(sbuf); } + return GRN_NO_MEMORY_AVAILABLE; +} + +inline static grn_rc +index_del(grn_ctx *ctx, grn_id rid, grn_obj *lexicon, grn_ii *ii, grn_vgram *vgram, + const char *value, size_t value_len) +{ + grn_rc rc = GRN_SUCCESS; + grn_hash *h; + unsigned int token_flags = 0; + grn_token_cursor *token_cursor; + grn_ii_updspec **u; + grn_id tid, *tp; + if (!rid) { return GRN_INVALID_ARGUMENT; } + if (!(token_cursor = grn_token_cursor_open(ctx, lexicon, value, value_len, + GRN_TOKEN_DEL, token_flags))) { + return GRN_NO_MEMORY_AVAILABLE; + } + h = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_ii_updspec *), + GRN_HASH_TINY); + if (!h) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create on index_del failed !"); + grn_token_cursor_close(ctx, token_cursor); + return GRN_NO_MEMORY_AVAILABLE; + } + while (!token_cursor->status) { + if ((tid = grn_token_cursor_next(ctx, token_cursor))) { + if (!grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **) &u, NULL)) { + break; + } + if (!*u) { + if (!(*u = grn_ii_updspec_open(ctx, rid, 0))) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_open on index_del failed !"); + grn_hash_close(ctx, h); + grn_token_cursor_close(ctx, token_cursor); + return GRN_NO_MEMORY_AVAILABLE; + } + } + } + } + grn_token_cursor_close(ctx, token_cursor); + GRN_HASH_EACH(ctx, h, id, &tp, NULL, &u, { + if (*tp) { + grn_rc r; + r = grn_ii_delete_one(ctx, ii, *tp, *u, NULL); + if (r) { + rc = r; + } + } + grn_ii_updspec_close(ctx, *u); + }); + grn_hash_close(ctx, h); + return rc; +} + +grn_rc +grn_ii_upd(grn_ctx *ctx, grn_ii *ii, grn_id rid, grn_vgram *vgram, + const char *oldvalue, unsigned int oldvalue_len, + const char *newvalue, unsigned int newvalue_len) +{ + grn_rc rc; + grn_obj *lexicon = ii->lexicon; + if (!rid) { return GRN_INVALID_ARGUMENT; } + if (oldvalue && *oldvalue) { + if ((rc = index_del(ctx, rid, lexicon, ii, vgram, oldvalue, oldvalue_len))) { + GRN_LOG(ctx, GRN_LOG_ERROR, "index_del on grn_ii_upd failed !"); + goto exit; + } + } + if (newvalue && *newvalue) { + rc = index_add(ctx, rid, lexicon, ii, vgram, newvalue, newvalue_len); + } +exit : + return rc; +} + +grn_rc +grn_ii_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, grn_vgram *vgram, unsigned int section, + grn_values *oldvalues, grn_values *newvalues) +{ + int j; + grn_value *v; + unsigned int token_flags = 0; + grn_token_cursor *token_cursor; + grn_rc rc = GRN_SUCCESS; + grn_hash *old, *new; + grn_id tid, *tp; + grn_ii_updspec **u, **un; + grn_obj *lexicon = ii->lexicon; + if (!lexicon || !ii || !rid) { + GRN_LOG(ctx, GRN_LOG_WARNING, "grn_ii_update: invalid argument"); + return GRN_INVALID_ARGUMENT; + } + if (newvalues) { + new = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_ii_updspec *), + GRN_HASH_TINY); + if (!new) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_hash_create on grn_ii_update failed !"); + rc = GRN_NO_MEMORY_AVAILABLE; + goto exit; + } + for (j = newvalues->n_values, v = newvalues->values; j; j--, v++) { + if ((token_cursor = grn_token_cursor_open(ctx, lexicon, v->str, + v->str_len, GRN_TOKEN_ADD, + token_flags))) { + while (!token_cursor->status) { + if ((tid = grn_token_cursor_next(ctx, token_cursor))) { + if (!grn_hash_add(ctx, new, &tid, sizeof(grn_id), (void **) &u, + NULL)) { + break; + } + if (!*u) { + if (!(*u = grn_ii_updspec_open(ctx, rid, section))) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_open on grn_ii_update failed!"); + grn_token_cursor_close(ctx, token_cursor); + grn_hash_close(ctx, new); + rc = GRN_NO_MEMORY_AVAILABLE; + goto exit; + } + } + if (grn_ii_updspec_add(ctx, *u, token_cursor->pos, v->weight)) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_add on grn_ii_update failed!"); + grn_token_cursor_close(ctx, token_cursor); + grn_hash_close(ctx, new); + rc = GRN_NO_MEMORY_AVAILABLE; + goto exit; + } + } + } + grn_token_cursor_close(ctx, token_cursor); + } + } + if (!GRN_HASH_SIZE(new)) { + grn_hash_close(ctx, new); + new = NULL; + } + } else { + new = NULL; + } + if (oldvalues) { + old = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(grn_ii_updspec *), + GRN_HASH_TINY); + if (!old) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_hash_create(ctx, NULL, old) on grn_ii_update failed!"); + if (new) { grn_hash_close(ctx, new); } + rc = GRN_NO_MEMORY_AVAILABLE; + goto exit; + } + for (j = oldvalues->n_values, v = oldvalues->values; j; j--, v++) { + if ((token_cursor = grn_token_cursor_open(ctx, lexicon, v->str, + v->str_len, GRN_TOKEN_DEL, + token_flags))) { + while (!token_cursor->status) { + if ((tid = grn_token_cursor_next(ctx, token_cursor))) { + if (!grn_hash_add(ctx, old, &tid, sizeof(grn_id), (void **) &u, + NULL)) { + break; + } + if (!*u) { + if (!(*u = grn_ii_updspec_open(ctx, rid, section))) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_open on grn_ii_update failed!"); + grn_token_cursor_close(ctx, token_cursor); + if (new) { grn_hash_close(ctx, new); }; + grn_hash_close(ctx, old); + rc = GRN_NO_MEMORY_AVAILABLE; + goto exit; + } + } + if (grn_ii_updspec_add(ctx, *u, token_cursor->pos, v->weight)) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_add on grn_ii_update failed!"); + grn_token_cursor_close(ctx, token_cursor); + if (new) { grn_hash_close(ctx, new); }; + grn_hash_close(ctx, old); + rc = GRN_NO_MEMORY_AVAILABLE; + goto exit; + } + } + } + grn_token_cursor_close(ctx, token_cursor); + } + } + } else { + old = NULL; + } + if (old) { + grn_id eid; + GRN_HASH_EACH(ctx, old, id, &tp, NULL, &u, { + if (new && (eid = grn_hash_get(ctx, new, tp, sizeof(grn_id), + (void **) &un))) { + if (!grn_ii_updspec_cmp(*u, *un)) { + grn_ii_updspec_close(ctx, *un); + grn_hash_delete_by_id(ctx, new, eid, NULL); + } + } else { + grn_rc r; + r = grn_ii_delete_one(ctx, ii, *tp, *u, new); + if (r) { + rc = r; + } + } + grn_ii_updspec_close(ctx, *u); + }); + grn_hash_close(ctx, old); + } + if (new) { + GRN_HASH_EACH(ctx, new, id, &tp, NULL, &u, { + grn_rc r; + if ((r = grn_ii_update_one(ctx, ii, *tp, *u, new))) { rc = r; } + grn_ii_updspec_close(ctx, *u); + }); + grn_hash_close(ctx, new); + } else { + if (!section) { + /* todo: delete key when all sections deleted */ + } + } +exit : + return rc; +} +#endif /* USE_VGRAM */ + +static grn_rc +grn_vector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, + grn_obj *in, grn_obj *out, grn_tokenize_mode mode, + grn_obj *posting) +{ + int j; + grn_id tid; + grn_section *v; + grn_token_cursor *token_cursor; + grn_ii_updspec **u; + grn_hash *h = (grn_hash *)out; + grn_obj *lexicon = ii->lexicon; + if (in->u.v.body) { + const char *head = GRN_BULK_HEAD(in->u.v.body); + for (j = in->u.v.n_sections, v = in->u.v.sections; j; j--, v++) { + unsigned int token_flags = 0; + if (v->length && + (token_cursor = grn_token_cursor_open(ctx, lexicon, head + v->offset, + v->length, mode, + token_flags))) { + while (!token_cursor->status) { + if ((tid = grn_token_cursor_next(ctx, token_cursor))) { + if (posting) { GRN_RECORD_PUT(ctx, posting, tid); } + if (!grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **) &u, + NULL)) { + break; + } + if (!*u) { + if (!(*u = grn_ii_updspec_open(ctx, rid, section))) { + DEFINE_NAME(ii); + MERR("[ii][update][spec] failed to create an update spec: " + "<%.*s>: " + "record:<%u>:<%u>, token:<%u>:<%d>:<%u>", + name_size, name, + rid, section, + tid, token_cursor->pos, v->weight); + grn_token_cursor_close(ctx, token_cursor); + return ctx->rc; + } + } + if (grn_ii_updspec_add(ctx, *u, token_cursor->pos, v->weight)) { + DEFINE_NAME(ii); + MERR("[ii][update][spec] failed to add to update spec: " + "<%.*s>: " + "record:<%u>:<%u>, token:<%u>:<%d>:<%u>", + name_size, name, + rid, section, + tid, token_cursor->pos, v->weight); + grn_token_cursor_close(ctx, token_cursor); + return ctx->rc; + } + } + } + grn_token_cursor_close(ctx, token_cursor); + } + } + } + return ctx->rc; +} + +static grn_rc +grn_uvector2updspecs_data(grn_ctx *ctx, grn_ii *ii, grn_id rid, + unsigned int section, grn_obj *in, grn_obj *out, + grn_tokenize_mode mode, grn_obj *posting) +{ + int i, n; + grn_hash *h = (grn_hash *)out; + grn_obj *lexicon = ii->lexicon; + unsigned int element_size; + + n = grn_uvector_size(ctx, in); + element_size = grn_uvector_element_size(ctx, in); + for (i = 0; i < n; i++) { + grn_obj *tokenizer; + grn_token_cursor *token_cursor; + unsigned int token_flags = 0; + const char *element; + + tokenizer = grn_obj_get_info(ctx, lexicon, GRN_INFO_DEFAULT_TOKENIZER, + NULL); + + element = GRN_BULK_HEAD(in) + (element_size * i); + token_cursor = grn_token_cursor_open(ctx, lexicon, + element, element_size, + mode, token_flags); + if (!token_cursor) { + continue; + } + + while (!token_cursor->status) { + grn_id tid; + if ((tid = grn_token_cursor_next(ctx, token_cursor))) { + grn_ii_updspec **u; + int pos; + + if (posting) { GRN_RECORD_PUT(ctx, posting, tid); } + if (!grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **)&u, NULL)) { + break; + } + if (!*u) { + if (!(*u = grn_ii_updspec_open(ctx, rid, section))) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_open on grn_uvector2updspecs_data failed!"); + grn_token_cursor_close(ctx, token_cursor); + return GRN_NO_MEMORY_AVAILABLE; + } + } + if (tokenizer) { + pos = token_cursor->pos; + } else { + pos = i; + } + if (grn_ii_updspec_add(ctx, *u, pos, 0)) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_add on grn_uvector2updspecs failed!"); + grn_token_cursor_close(ctx, token_cursor); + return GRN_NO_MEMORY_AVAILABLE; + } + } + } + + grn_token_cursor_close(ctx, token_cursor); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_uvector2updspecs_id(grn_ctx *ctx, grn_ii *ii, grn_id rid, + unsigned int section, grn_obj *in, grn_obj *out) +{ + int i, n; + grn_ii_updspec **u; + grn_hash *h = (grn_hash *)out; + + n = grn_vector_size(ctx, in); + for (i = 0; i < n; i++) { + grn_id id; + unsigned int weight; + + id = grn_uvector_get_element(ctx, in, i, &weight); + if (!grn_hash_add(ctx, h, &id, sizeof(grn_id), (void **)&u, NULL)) { + break; + } + if (!*u) { + if (!(*u = grn_ii_updspec_open(ctx, rid, section))) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_open on grn_ii_update failed!"); + return GRN_NO_MEMORY_AVAILABLE; + } + } + if (grn_ii_updspec_add(ctx, *u, i, weight)) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_ii_updspec_add on grn_ii_update failed!"); + return GRN_NO_MEMORY_AVAILABLE; + } + } + return GRN_SUCCESS; +} + +static grn_rc +grn_uvector2updspecs(grn_ctx *ctx, grn_ii *ii, grn_id rid, + unsigned int section, grn_obj *in, grn_obj *out, + grn_tokenize_mode mode, grn_obj *posting) +{ + if (in->header.domain < GRN_N_RESERVED_TYPES) { + return grn_uvector2updspecs_data(ctx, ii, rid, section, in, out, + mode, posting); + } else { + return grn_uvector2updspecs_id(ctx, ii, rid, section, in, out); + } +} + +grn_rc +grn_ii_column_update(grn_ctx *ctx, grn_ii *ii, grn_id rid, unsigned int section, + grn_obj *oldvalue, grn_obj *newvalue, grn_obj *posting) +{ + grn_id *tp; + grn_bool do_grn_ii_updspec_cmp = GRN_TRUE; + grn_ii_updspec **u, **un; + grn_obj *old_, *old = oldvalue, *new_, *new = newvalue, oldv, newv; + grn_obj buf, *post = NULL; + + if (!ii) { + ERR(GRN_INVALID_ARGUMENT, "[ii][column][update] ii is NULL"); + return ctx->rc; + } + if (!ii->lexicon) { + ERR(GRN_INVALID_ARGUMENT, "[ii][column][update] lexicon is NULL"); + return ctx->rc; + } + if (rid == GRN_ID_NIL) { + ERR(GRN_INVALID_ARGUMENT, "[ii][column][update] record ID is nil"); + return ctx->rc; + } + if (old || new) { + unsigned char type = GRN_VOID; + if (old) { + type = (ii->obj.header.domain == old->header.domain) + ? GRN_UVECTOR + : old->header.type; + } + if (new) { + type = (ii->obj.header.domain == new->header.domain) + ? GRN_UVECTOR + : new->header.type; + } + if (type == GRN_VECTOR) { + grn_obj *tokenizer; + grn_table_get_info(ctx, ii->lexicon, NULL, NULL, &tokenizer, NULL, NULL); + if (tokenizer) { + grn_obj old_elem, new_elem; + unsigned int i, max_n; + unsigned int old_n = 0, new_n = 0; + if (old) { + old_n = grn_vector_size(ctx, old); + } + if (new) { + new_n = grn_vector_size(ctx, new); + } + max_n = (old_n > new_n) ? old_n : new_n; + GRN_OBJ_INIT(&old_elem, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, old->header.domain); + GRN_OBJ_INIT(&new_elem, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, new->header.domain); + for (i = 0; i < max_n; i++) { + grn_rc rc; + grn_obj *old_p = NULL, *new_p = NULL; + if (i < old_n) { + const char *str; + unsigned int size = grn_vector_get_element(ctx, old, i, &str, NULL, NULL); + GRN_TEXT_SET_REF(&old_elem, str, size); + old_p = &old_elem; + } + if (i < new_n) { + const char *str; + unsigned int size = grn_vector_get_element(ctx, new, i, &str, NULL, NULL); + GRN_TEXT_SET_REF(&new_elem, str, size); + new_p = &new_elem; + } + rc = grn_ii_column_update(ctx, ii, rid, section + i, old_p, new_p, posting); + if (rc != GRN_SUCCESS) { + break; + } + } + GRN_OBJ_FIN(ctx, &old_elem); + GRN_OBJ_FIN(ctx, &new_elem); + return ctx->rc; + } + } + } + if (posting) { + GRN_RECORD_INIT(&buf, GRN_OBJ_VECTOR, grn_obj_id(ctx, ii->lexicon)); + post = &buf; + } + if (grn_io_lock(ctx, ii->seg, grn_lock_timeout)) { return ctx->rc; } + if (new) { + unsigned char type = (ii->obj.header.domain == new->header.domain) + ? GRN_UVECTOR + : new->header.type; + switch (type) { + case GRN_BULK : + { + if (grn_bulk_is_zero(ctx, new)) { + do_grn_ii_updspec_cmp = GRN_FALSE; + } + new_ = new; + GRN_OBJ_INIT(&newv, GRN_VECTOR, GRN_OBJ_DO_SHALLOW_COPY, GRN_DB_TEXT); + newv.u.v.body = new; + new = &newv; + grn_vector_delimit(ctx, new, 0, GRN_ID_NIL); + if (new_ != newvalue) { grn_obj_close(ctx, new_); } + } + /* fallthru */ + case GRN_VECTOR : + new_ = new; + new = (grn_obj *)grn_hash_create(ctx, NULL, sizeof(grn_id), + sizeof(grn_ii_updspec *), + GRN_HASH_TINY); + if (!new) { + DEFINE_NAME(ii); + MERR("[ii][column][update][new][vector] failed to create a hash table: " + "<%.*s>: ", + name_size, name); + } else { + grn_vector2updspecs(ctx, ii, rid, section, new_, new, + GRN_TOKEN_ADD, post); + } + if (new_ != newvalue) { grn_obj_close(ctx, new_); } + if (ctx->rc != GRN_SUCCESS) { goto exit; } + break; + case GRN_UVECTOR : + new_ = new; + new = (grn_obj *)grn_hash_create(ctx, NULL, sizeof(grn_id), + sizeof(grn_ii_updspec *), + GRN_HASH_TINY); + if (!new) { + DEFINE_NAME(ii); + MERR("[ii][column][update][new][uvector] failed to create a hash table: " + "<%.*s>: ", + name_size, name); + } else { + if (new_->header.type == GRN_UVECTOR) { + grn_uvector2updspecs(ctx, ii, rid, section, new_, new, + GRN_TOKEN_ADD, post); + } else { + grn_obj uvector; + unsigned int weight = 0; + GRN_VALUE_FIX_SIZE_INIT(&uvector, GRN_OBJ_VECTOR, + new_->header.domain); + if (new_->header.impl_flags & GRN_OBJ_WITH_WEIGHT) { + uvector.header.impl_flags |= GRN_OBJ_WITH_WEIGHT; + } + grn_uvector_add_element(ctx, &uvector, GRN_RECORD_VALUE(new_), + weight); + grn_uvector2updspecs(ctx, ii, rid, section, &uvector, new, + GRN_TOKEN_ADD, post); + GRN_OBJ_FIN(ctx, &uvector); + } + } + if (new_ != newvalue) { grn_obj_close(ctx, new_); } + if (ctx->rc != GRN_SUCCESS) { goto exit; } + break; + case GRN_TABLE_HASH_KEY : + break; + default : + { + DEFINE_NAME(ii); + ERR(GRN_INVALID_ARGUMENT, + "[ii][column][update][new] invalid object: " + "<%.*s>: " + "<%-.256s>(%#x)", + name_size, name, + grn_obj_type_to_string(type), + type); + } + goto exit; + } + } + if (posting) { + grn_ii_updspec *u_; + uint32_t offset = 0; + grn_id tid_ = 0, gap, tid, *tpe; + grn_table_sort_optarg arg = {GRN_TABLE_SORT_ASC| + GRN_TABLE_SORT_AS_NUMBER| + GRN_TABLE_SORT_AS_UNSIGNED, NULL, NULL,0 }; + grn_array *sorted = grn_array_create(ctx, NULL, sizeof(grn_id), 0); + grn_hash_sort(ctx, (grn_hash *)new, -1, sorted, &arg); + GRN_TEXT_PUT(ctx, posting, ((grn_hash *)new)->n_entries, sizeof(uint32_t)); + GRN_ARRAY_EACH(ctx, sorted, 0, 0, id, &tp, { + grn_hash_get_key(ctx, (grn_hash *)new, *tp, &tid, sizeof(grn_id)); + gap = tid - tid_; + GRN_TEXT_PUT(ctx, posting, &gap, sizeof(grn_id)); + tid_ = tid; + }); + GRN_ARRAY_EACH(ctx, sorted, 0, 0, id, &tp, { + grn_hash_get_value(ctx, (grn_hash *)new, *tp, &u_); + u_->offset = offset++; + GRN_TEXT_PUT(ctx, posting, &u_->tf, sizeof(int32_t)); + }); + tpe = (grn_id *)GRN_BULK_CURR(post); + for (tp = (grn_id *)GRN_BULK_HEAD(post); tp < tpe; tp++) { + grn_hash_get(ctx, (grn_hash *)new, (void *)tp, sizeof(grn_id), + (void **)&u); + GRN_TEXT_PUT(ctx, posting, &(*u)->offset, sizeof(int32_t)); + } + GRN_OBJ_FIN(ctx, post); + grn_array_close(ctx, sorted); + } + + if (old) { + unsigned char type = (ii->obj.header.domain == old->header.domain) + ? GRN_UVECTOR + : old->header.type; + switch (type) { + case GRN_BULK : + { + // const char *str = GRN_BULK_HEAD(old); + // unsigned int str_len = GRN_BULK_VSIZE(old); + old_ = old; + GRN_OBJ_INIT(&oldv, GRN_VECTOR, GRN_OBJ_DO_SHALLOW_COPY, GRN_DB_TEXT); + oldv.u.v.body = old; + old = &oldv; + grn_vector_delimit(ctx, old, 0, GRN_ID_NIL); + if (old_ != oldvalue) { grn_obj_close(ctx, old_); } + } + /* fallthru */ + case GRN_VECTOR : + old_ = old; + old = (grn_obj *)grn_hash_create(ctx, NULL, sizeof(grn_id), + sizeof(grn_ii_updspec *), + GRN_HASH_TINY); + if (!old) { + DEFINE_NAME(ii); + MERR("[ii][column][update][old][vector] failed to create a hash table: " + "<%.*s>: ", + name_size, name); + } else { + grn_vector2updspecs(ctx, ii, rid, section, old_, old, + GRN_TOKEN_DEL, NULL); + } + if (old_ != oldvalue) { grn_obj_close(ctx, old_); } + if (ctx->rc != GRN_SUCCESS) { goto exit; } + break; + case GRN_UVECTOR : + old_ = old; + old = (grn_obj *)grn_hash_create(ctx, NULL, sizeof(grn_id), + sizeof(grn_ii_updspec *), + GRN_HASH_TINY); + if (!old) { + DEFINE_NAME(ii); + MERR("[ii][column][update][old][uvector] failed to create a hash table: " + "<%.*s>: ", + name_size, name); + } else { + if (old_->header.type == GRN_UVECTOR) { + grn_uvector2updspecs(ctx, ii, rid, section, old_, old, + GRN_TOKEN_DEL, NULL); + } else { + grn_obj uvector; + unsigned int weight = 0; + GRN_VALUE_FIX_SIZE_INIT(&uvector, GRN_OBJ_VECTOR, + old_->header.domain); + if (old_->header.impl_flags & GRN_OBJ_WITH_WEIGHT) { + uvector.header.impl_flags |= GRN_OBJ_WITH_WEIGHT; + } + grn_uvector_add_element(ctx, &uvector, GRN_RECORD_VALUE(old_), + weight); + grn_uvector2updspecs(ctx, ii, rid, section, &uvector, old, + GRN_TOKEN_DEL, NULL); + GRN_OBJ_FIN(ctx, &uvector); + } + } + if (old_ != oldvalue) { grn_obj_close(ctx, old_); } + if (ctx->rc != GRN_SUCCESS) { goto exit; } + break; + case GRN_TABLE_HASH_KEY : + break; + default : + { + DEFINE_NAME(ii); + ERR(GRN_INVALID_ARGUMENT, + "[ii][column][update][old] invalid object: " + "<%.*s>: " + "<%-.256s>(%#x)", + name_size, name, + grn_obj_type_to_string(type), + type); + } + goto exit; + } + } + + if (old) { + grn_id eid; + grn_hash *o = (grn_hash *)old; + grn_hash *n = (grn_hash *)new; + GRN_HASH_EACH(ctx, o, id, &tp, NULL, &u, { + if (n && (eid = grn_hash_get(ctx, n, tp, sizeof(grn_id), + (void **) &un))) { + if (do_grn_ii_updspec_cmp && !grn_ii_updspec_cmp(*u, *un)) { + grn_ii_updspec_close(ctx, *un); + grn_hash_delete_by_id(ctx, n, eid, NULL); + } + } else { + grn_ii_delete_one(ctx, ii, *tp, *u, n); + } + grn_ii_updspec_close(ctx, *u); + if (ctx->rc != GRN_SUCCESS) { + break; + } + }); + } + if (new) { + grn_hash *n = (grn_hash *)new; + GRN_HASH_EACH(ctx, n, id, &tp, NULL, &u, { + grn_ii_update_one(ctx, ii, *tp, *u, n); + grn_ii_updspec_close(ctx, *u); + if (ctx->rc != GRN_SUCCESS) { + break; + } + }); + } else { + if (!section) { + /* todo: delete key when all sections deleted */ + } + } +exit : + grn_io_unlock(ii->seg); + if (old && old != oldvalue) { grn_obj_close(ctx, old); } + if (new && new != newvalue) { grn_obj_close(ctx, new); } + return ctx->rc; +} + +/* token_info */ + +typedef struct { + cursor_heap *cursors; + int offset; + int pos; + int size; + int ntoken; + grn_posting *p; +} token_info; + +#define EX_NONE 0 +#define EX_PREFIX 1 +#define EX_SUFFIX 2 +#define EX_BOTH 3 +#define EX_FUZZY 4 + +inline static void +token_info_expand_both(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, + const char *key, unsigned int key_size, token_info *ti) +{ + int s = 0; + grn_hash *h, *g; + uint32_t *offset2; + grn_hash_cursor *c; + grn_id *tp, *tq; + if ((h = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, 0))) { + grn_table_search(ctx, lexicon, key, key_size, + GRN_OP_PREFIX, (grn_obj *)h, GRN_OP_OR); + if (GRN_HASH_SIZE(h)) { + if ((ti->cursors = cursor_heap_open(ctx, GRN_HASH_SIZE(h) + 256))) { + if ((c = grn_hash_cursor_open(ctx, h, NULL, 0, NULL, 0, 0, -1, 0))) { + uint32_t key2_size; + const char *key2; + while (grn_hash_cursor_next(ctx, c)) { + grn_hash_cursor_get_key(ctx, c, (void **) &tp); + key2 = _grn_table_key(ctx, lexicon, *tp, &key2_size); + if (!key2) { break; } + if ((lexicon->header.type != GRN_TABLE_PAT_KEY) || + !(lexicon->header.flags & GRN_OBJ_KEY_WITH_SIS) || + key2_size <= 2) { // todo: refine + if ((s = grn_ii_estimate_size(ctx, ii, *tp))) { + cursor_heap_push(ctx, ti->cursors, ii, *tp, 0, 0, GRN_ID_NIL); + ti->ntoken++; + ti->size += s; + } + } else { + if ((g = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_HASH_TINY))) { + grn_pat_suffix_search(ctx, (grn_pat *)lexicon, key2, key2_size, + g); + GRN_HASH_EACH(ctx, g, id, &tq, NULL, &offset2, { + if ((s = grn_ii_estimate_size(ctx, ii, *tq))) { + cursor_heap_push(ctx, ti->cursors, ii, *tq, + /* *offset2 */ 0, 0, GRN_ID_NIL); + ti->ntoken++; + ti->size += s; + } + }); + grn_hash_close(ctx, g); + } + } + } + grn_hash_cursor_close(ctx, c); + } + } + } + grn_hash_close(ctx, h); + } +} + +inline static grn_rc +token_info_close(grn_ctx *ctx, token_info *ti) +{ + cursor_heap_close(ctx, ti->cursors); + GRN_FREE(ti); + return GRN_SUCCESS; +} + +inline static token_info * +token_info_open(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, + const char *key, unsigned int key_size, uint32_t offset, + int mode, grn_fuzzy_search_optarg *args, grn_id min) +{ + int s = 0; + grn_hash *h; + token_info *ti; + grn_id tid; + grn_id *tp; + if (!key) { return NULL; } + if (!(ti = GRN_MALLOC(sizeof(token_info)))) { return NULL; } + ti->cursors = NULL; + ti->size = 0; + ti->ntoken = 0; + ti->offset = offset; + switch (mode) { + case EX_BOTH : + token_info_expand_both(ctx, lexicon, ii, key, key_size, ti); + break; + case EX_NONE : + if ((tid = grn_table_get(ctx, lexicon, key, key_size)) && + (s = grn_ii_estimate_size(ctx, ii, tid)) && + (ti->cursors = cursor_heap_open(ctx, 1))) { + cursor_heap_push(ctx, ti->cursors, ii, tid, 0, 0, min); + ti->ntoken++; + ti->size = s; + } + break; + case EX_PREFIX : + if ((h = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, 0))) { + grn_table_search(ctx, lexicon, key, key_size, + GRN_OP_PREFIX, (grn_obj *)h, GRN_OP_OR); + if (GRN_HASH_SIZE(h)) { + if ((ti->cursors = cursor_heap_open(ctx, GRN_HASH_SIZE(h)))) { + GRN_HASH_EACH(ctx, h, id, &tp, NULL, NULL, { + if ((s = grn_ii_estimate_size(ctx, ii, *tp))) { + cursor_heap_push(ctx, ti->cursors, ii, *tp, 0, 0, min); + ti->ntoken++; + ti->size += s; + } + }); + } + } + grn_hash_close(ctx, h); + } + break; + case EX_SUFFIX : + if ((h = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, 0))) { + grn_table_search(ctx, lexicon, key, key_size, + GRN_OP_SUFFIX, (grn_obj *)h, GRN_OP_OR); + if (GRN_HASH_SIZE(h)) { + if ((ti->cursors = cursor_heap_open(ctx, GRN_HASH_SIZE(h)))) { + uint32_t *offset2; + GRN_HASH_EACH(ctx, h, id, &tp, NULL, &offset2, { + if ((s = grn_ii_estimate_size(ctx, ii, *tp))) { + cursor_heap_push(ctx, ti->cursors, ii, *tp, /* *offset2 */ 0, 0, min); + ti->ntoken++; + ti->size += s; + } + }); + } + } + grn_hash_close(ctx, h); + } + break; + case EX_FUZZY : + if ((h = (grn_hash *)grn_table_create(ctx, NULL, 0, NULL, + GRN_OBJ_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + grn_ctx_at(ctx, GRN_DB_UINT32), NULL))) { + grn_table_fuzzy_search(ctx, lexicon, key, key_size, + args, (grn_obj *)h, GRN_OP_OR); + if (GRN_HASH_SIZE(h)) { + if ((ti->cursors = cursor_heap_open(ctx, GRN_HASH_SIZE(h)))) { + grn_rset_recinfo *ri; + GRN_HASH_EACH(ctx, h, id, &tp, NULL, (void **)&ri, { + if ((s = grn_ii_estimate_size(ctx, ii, *tp))) { + cursor_heap_push(ctx, ti->cursors, ii, *tp, 0, ri->score - 1, min); + ti->ntoken++; + ti->size += s; + } + }); + } + } + grn_obj_close(ctx, (grn_obj *)h); + } + break; + } + if (cursor_heap_push2(ti->cursors)) { + token_info_close(ctx, ti); + return NULL; + } + { + grn_ii_cursor *ic; + if (ti->cursors && (ic = cursor_heap_min(ti->cursors))) { + grn_posting *p = ic->post; + ti->pos = p->pos - ti->offset; + ti->p = p; + } else { + token_info_close(ctx, ti); + ti = NULL; + } + } + return ti; +} + +static inline grn_rc +token_info_skip(grn_ctx *ctx, token_info *ti, uint32_t rid, uint32_t sid) +{ + grn_ii_cursor *c; + grn_posting *p; + for (;;) { + if (!(c = cursor_heap_min(ti->cursors))) { return GRN_END_OF_DATA; } + p = c->post; + if (p->rid > rid || (p->rid == rid && p->sid >= sid)) { break; } + cursor_heap_pop(ctx, ti->cursors, rid); + } + ti->pos = p->pos - ti->offset; + ti->p = p; + return GRN_SUCCESS; +} + +static inline grn_rc +token_info_skip_pos(grn_ctx *ctx, token_info *ti, uint32_t rid, uint32_t sid, uint32_t pos) +{ + grn_ii_cursor *c; + grn_posting *p; + pos += ti->offset; + for (;;) { + if (!(c = cursor_heap_min(ti->cursors))) { return GRN_END_OF_DATA; } + p = c->post; + if (p->rid != rid || p->sid != sid || p->pos >= pos) { break; } + cursor_heap_pop_pos(ctx, ti->cursors); + } + ti->pos = p->pos - ti->offset; + ti->p = p; + return GRN_SUCCESS; +} + +inline static int +token_compare(const void *a, const void *b) +{ + const token_info *t1 = *((token_info **)a), *t2 = *((token_info **)b); + return t1->size - t2->size; +} + +#define TOKEN_CANDIDATE_NODE_SIZE 32 +#define TOKEN_CANDIDATE_ADJACENT_MAX_SIZE 16 +#define TOKEN_CANDIDATE_QUEUE_SIZE 64 +#define TOKEN_CANDIDATE_SIZE 16 + +typedef struct { + grn_id tid; + const unsigned char *token; + uint32_t token_size; + int32_t pos; + grn_token_cursor_status status; + int ef; + uint32_t estimated_size; + uint8_t adjacent[TOKEN_CANDIDATE_ADJACENT_MAX_SIZE]; /* Index of adjacent node from top */ + uint8_t n_adjacent; +} token_candidate_node; + +typedef struct { + uint32_t *candidates; /* Standing bits indicate index of token_candidate_node */ + int top; + int rear; + int size; +} token_candidate_queue; + +inline static void +token_candidate_adjacent_set(grn_ctx *ctx, grn_token_cursor *token_cursor, + token_candidate_node *top, token_candidate_node *curr) +{ + grn_bool exists_adjacent = GRN_FALSE; + token_candidate_node *adj; + for (adj = top; adj < curr; adj++) { + if (token_cursor->curr <= adj->token + adj->token_size) { + if (adj->n_adjacent < TOKEN_CANDIDATE_ADJACENT_MAX_SIZE) { + adj->adjacent[adj->n_adjacent] = curr - top; + adj->n_adjacent++; + exists_adjacent = GRN_TRUE; + } + } + } + if (!exists_adjacent) { + adj = curr - 1; + if (adj->n_adjacent < TOKEN_CANDIDATE_ADJACENT_MAX_SIZE) { + adj->adjacent[adj->n_adjacent] = curr - top; + adj->n_adjacent++; + } + } +} + +inline static grn_rc +token_candidate_init(grn_ctx *ctx, grn_ii *ii, grn_token_cursor *token_cursor, + grn_id tid, int ef, token_candidate_node **nodes, int *n_nodes, + uint32_t *max_estimated_size) +{ + grn_rc rc; + token_candidate_node *top, *curr; + int size = TOKEN_CANDIDATE_NODE_SIZE; + + *nodes = GRN_MALLOC(TOKEN_CANDIDATE_NODE_SIZE * sizeof(token_candidate_node)); + if (!*nodes) { + return GRN_NO_MEMORY_AVAILABLE; + } + top = *nodes; + curr = top; + +#define TOKEN_CANDIDATE_NODE_SET() { \ + curr->tid = tid; \ + curr->token = token_cursor->curr; \ + curr->token_size = token_cursor->curr_size; \ + curr->pos = token_cursor->pos; \ + curr->status = token_cursor->status; \ + curr->ef = ef; \ + curr->estimated_size = grn_ii_estimate_size(ctx, ii, tid); \ + curr->n_adjacent = 0; \ +} + TOKEN_CANDIDATE_NODE_SET(); + GRN_LOG(ctx, GRN_LOG_DEBUG, "[ii][overlap_token_skip] tid=%u pos=%d estimated_size=%u", + curr->tid, curr->pos, curr->estimated_size); + *max_estimated_size = curr->estimated_size; + curr++; + + while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) { + if (curr - top >= size) { + if (!(*nodes = GRN_REALLOC(*nodes, + (curr - top + TOKEN_CANDIDATE_NODE_SIZE) * sizeof(token_candidate_node)))) { + return GRN_NO_MEMORY_AVAILABLE; + } + top = *nodes; + curr = top + size; + size += TOKEN_CANDIDATE_NODE_SIZE; + } + tid = grn_token_cursor_next(ctx, token_cursor); + if (token_cursor->status != GRN_TOKEN_CURSOR_DONE_SKIP) { + if (token_cursor->force_prefix) { ef |= EX_PREFIX; } + TOKEN_CANDIDATE_NODE_SET(); + token_candidate_adjacent_set(ctx, token_cursor, top, curr); + if (curr->estimated_size > *max_estimated_size) { + *max_estimated_size = curr->estimated_size; + } + curr++; + } + } + *n_nodes = curr - top; + rc = GRN_SUCCESS; + return rc; +#undef TOKEN_CANDIDATE_NODE_SET +} + +inline static grn_rc +token_candidate_queue_init(grn_ctx *ctx, token_candidate_queue *q) +{ + q->top = 0; + q->rear = 0; + q->size = TOKEN_CANDIDATE_QUEUE_SIZE; + + q->candidates = GRN_MALLOC(TOKEN_CANDIDATE_QUEUE_SIZE * sizeof(uint32_t)); + if (!q->candidates) { + q->size = 0; + return GRN_NO_MEMORY_AVAILABLE; + } + return GRN_SUCCESS; +} + +inline static grn_rc +token_candidate_enqueue(grn_ctx *ctx, token_candidate_queue *q, uint32_t candidate) +{ + if (q->rear >= q->size) { + if (!(q->candidates = + GRN_REALLOC(q->candidates, + (q->rear + TOKEN_CANDIDATE_QUEUE_SIZE) * sizeof(uint32_t)))) { + q->size = 0; + return GRN_NO_MEMORY_AVAILABLE; + } + q->size += TOKEN_CANDIDATE_QUEUE_SIZE; + } + *(q->candidates + q->rear) = candidate; + q->rear++; + return GRN_SUCCESS; +} + +inline static grn_rc +token_candidate_dequeue(grn_ctx *ctx, token_candidate_queue *q, uint32_t *candidate) +{ + if (q->top == q->rear) { + return GRN_END_OF_DATA; + } + *candidate = *(q->candidates + q->top); + q->top++; + return GRN_SUCCESS; +} + +inline static void +token_candidate_queue_fin(grn_ctx *ctx, token_candidate_queue *q) +{ + GRN_FREE(q->candidates); +} + +inline static token_candidate_node* +token_candidate_last_node(grn_ctx *ctx, token_candidate_node *nodes, uint32_t candidate, int offset) +{ + int i; + GRN_BIT_SCAN_REV(candidate, i); + return nodes + i + offset; +} + +inline static uint64_t +token_candidate_score(grn_ctx *ctx, token_candidate_node *nodes, uint32_t candidate, + int offset, uint32_t max_estimated_size) +{ + int i, last; + uint64_t score = 0; + GRN_BIT_SCAN_REV(candidate, last); + for (i = 0; i <= last; i++) { + if (candidate & (1 << i)) { + token_candidate_node *node = nodes + i + offset; + if (node->estimated_size > 0) { + score += max_estimated_size / node->estimated_size; + } + } + } + return score; +} + +inline static grn_rc +token_candidate_select(grn_ctx *ctx, token_candidate_node *nodes, + int offset, int limit, int end, + uint32_t *selected_candidate, uint32_t max_estimated_size) +{ + grn_rc rc; + token_candidate_queue q; + uint32_t candidate; + uint64_t max_score = 0; + int i, min_n_nodes = 0; + + if (offset + limit > end) { + limit = end - offset; + } + rc = token_candidate_queue_init(ctx, &q); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = token_candidate_enqueue(ctx, &q, 1); + if (rc != GRN_SUCCESS) { + goto exit; + } + while (token_candidate_dequeue(ctx, &q, &candidate) != GRN_END_OF_DATA) { + token_candidate_node *candidate_last_node = + token_candidate_last_node(ctx, nodes, candidate, offset); + for (i = 0; i < candidate_last_node->n_adjacent; i++) { + int adjacent, n_nodes = 0; + uint32_t new_candidate; + adjacent = candidate_last_node->adjacent[i] - offset; + if (adjacent > limit) { + break; + } + new_candidate = candidate | (1 << adjacent); + GET_NUM_BITS(new_candidate, n_nodes); + if (min_n_nodes > 0 && n_nodes > min_n_nodes + 1) { + goto exit; + } + rc = token_candidate_enqueue(ctx, &q, new_candidate); + if (rc != GRN_SUCCESS) { + goto exit; + } + if (adjacent == limit) { + if (min_n_nodes == 0) { + min_n_nodes = n_nodes; + } + if (n_nodes >= min_n_nodes && n_nodes <= min_n_nodes + 1) { + uint64_t score; + score = token_candidate_score(ctx, nodes, new_candidate, offset, max_estimated_size); + if (score > max_score) { + max_score = score; + *selected_candidate = new_candidate; + } + } + } + } + } + rc = GRN_SUCCESS; +exit : + token_candidate_queue_fin(ctx, &q); + return rc; +} + +inline static grn_rc +token_candidate_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, + token_info **tis, uint32_t *n, + token_candidate_node *nodes, uint32_t selected_candidate, + int offset, grn_id min) +{ + grn_rc rc = GRN_END_OF_DATA; + token_info *ti; + const char *key; + uint32_t size; + int i, last = 0; + GRN_BIT_SCAN_REV(selected_candidate, last); + for (i = 1; i <= last; i++) { + if (selected_candidate & (1 << i)) { + token_candidate_node *node = nodes + i + offset; + switch (node->status) { + case GRN_TOKEN_CURSOR_DOING : + key = _grn_table_key(ctx, lexicon, node->tid, &size); + ti = token_info_open(ctx, lexicon, ii, key, size, node->pos, + EX_NONE, NULL, min); + break; + case GRN_TOKEN_CURSOR_DONE : + if (node->tid) { + key = _grn_table_key(ctx, lexicon, node->tid, &size); + ti = token_info_open(ctx, lexicon, ii, key, size, node->pos, + node->ef & EX_PREFIX, NULL, min); + break; + } /* else fallthru */ + default : + ti = token_info_open(ctx, lexicon, ii, (char *)node->token, + node->token_size, node->pos, + node->ef & EX_PREFIX, NULL, min); + break; + } + if (!ti) { + goto exit; + } + tis[(*n)++] = ti; + GRN_LOG(ctx, GRN_LOG_DEBUG, "[ii][overlap_token_skip] tid=%u pos=%d estimated_size=%u", + node->tid, node->pos, node->estimated_size); + } + } + rc = GRN_SUCCESS; +exit : + return rc; +} + +inline static grn_rc +token_info_build_skipping_overlap(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, + token_info **tis, uint32_t *n, + grn_token_cursor *token_cursor, + grn_id tid, int ef, grn_id min) +{ + grn_rc rc; + token_candidate_node *nodes = NULL; + int n_nodes = 0, offset = 0, limit = TOKEN_CANDIDATE_SIZE - 1; + uint32_t max_estimated_size; + + rc = token_candidate_init(ctx, ii, token_cursor, tid, ef, &nodes, &n_nodes, &max_estimated_size); + if (rc != GRN_SUCCESS) { + return rc; + } + while (offset < n_nodes - 1) { + uint32_t selected_candidate = 0; + rc = token_candidate_select(ctx, nodes, offset, limit, n_nodes - 1, + &selected_candidate, max_estimated_size); + if (rc != GRN_SUCCESS) { + goto exit; + } + rc = token_candidate_build(ctx, lexicon, ii, tis, n, nodes, selected_candidate, offset, min); + if (rc != GRN_SUCCESS) { + goto exit; + } + offset += limit; + } + rc = GRN_SUCCESS; +exit : + if (nodes) { + GRN_FREE(nodes); + } + return rc; +} + +inline static grn_rc +token_info_build(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, const char *string, unsigned int string_len, + token_info **tis, uint32_t *n, grn_bool *only_skip_token, grn_id min, + grn_operator mode) +{ + token_info *ti; + const char *key; + uint32_t size; + grn_rc rc = GRN_END_OF_DATA; + unsigned int token_flags = GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER; + grn_token_cursor *token_cursor = grn_token_cursor_open(ctx, lexicon, + string, string_len, + GRN_TOKEN_GET, + token_flags); + *only_skip_token = GRN_FALSE; + if (!token_cursor) { return GRN_NO_MEMORY_AVAILABLE; } + if (mode == GRN_OP_UNSPLIT) { + if ((ti = token_info_open(ctx, lexicon, ii, (char *)token_cursor->orig, + token_cursor->orig_blen, 0, EX_BOTH, NULL, min))) { + tis[(*n)++] = ti; + rc = GRN_SUCCESS; + } + } else { + grn_id tid; + int ef; + switch (mode) { + case GRN_OP_PREFIX : + ef = EX_PREFIX; + break; + case GRN_OP_SUFFIX : + ef = EX_SUFFIX; + break; + case GRN_OP_PARTIAL : + ef = EX_BOTH; + break; + default : + ef = EX_NONE; + break; + } + tid = grn_token_cursor_next(ctx, token_cursor); + if (token_cursor->force_prefix) { ef |= EX_PREFIX; } + switch (token_cursor->status) { + case GRN_TOKEN_CURSOR_DOING : + key = _grn_table_key(ctx, lexicon, tid, &size); + ti = token_info_open(ctx, lexicon, ii, key, size, token_cursor->pos, + ef & EX_SUFFIX, NULL, min); + break; + case GRN_TOKEN_CURSOR_DONE : + ti = token_info_open(ctx, lexicon, ii, (const char *)token_cursor->curr, + token_cursor->curr_size, 0, ef, NULL, min); + /* + key = _grn_table_key(ctx, lexicon, tid, &size); + ti = token_info_open(ctx, lexicon, ii, token_cursor->curr, token_cursor->curr_size, token_cursor->pos, ef, NULL, GRN_ID_NIL); + ti = token_info_open(ctx, lexicon, ii, (char *)token_cursor->orig, + token_cursor->orig_blen, token_cursor->pos, ef, NULL, GRN_ID_NIL); + */ + break; + case GRN_TOKEN_CURSOR_NOT_FOUND : + ti = token_info_open(ctx, lexicon, ii, (char *)token_cursor->orig, + token_cursor->orig_blen, 0, ef, NULL, min); + break; + case GRN_TOKEN_CURSOR_DONE_SKIP : + *only_skip_token = GRN_TRUE; + goto exit; + default : + goto exit; + } + if (!ti) { goto exit ; } + tis[(*n)++] = ti; + + if (grn_ii_overlap_token_skip_enable) { + rc = token_info_build_skipping_overlap(ctx, lexicon, ii, tis, n, token_cursor, tid, ef, min); + goto exit; + } + + while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) { + tid = grn_token_cursor_next(ctx, token_cursor); + if (token_cursor->force_prefix) { ef |= EX_PREFIX; } + switch (token_cursor->status) { + case GRN_TOKEN_CURSOR_DONE_SKIP : + continue; + case GRN_TOKEN_CURSOR_DOING : + key = _grn_table_key(ctx, lexicon, tid, &size); + ti = token_info_open(ctx, lexicon, ii, key, size, token_cursor->pos, + EX_NONE, NULL, min); + break; + case GRN_TOKEN_CURSOR_DONE : + if (tid) { + key = _grn_table_key(ctx, lexicon, tid, &size); + ti = token_info_open(ctx, lexicon, ii, key, size, token_cursor->pos, + ef & EX_PREFIX, NULL, min); + break; + } /* else fallthru */ + default : + ti = token_info_open(ctx, lexicon, ii, (char *)token_cursor->curr, + token_cursor->curr_size, token_cursor->pos, + ef & EX_PREFIX, NULL, min); + break; + } + if (!ti) { + goto exit; + } + tis[(*n)++] = ti; + } + rc = GRN_SUCCESS; + } +exit : + grn_token_cursor_close(ctx, token_cursor); + return rc; +} + +inline static grn_rc +token_info_build_fuzzy(grn_ctx *ctx, grn_obj *lexicon, grn_ii *ii, + const char *string, unsigned int string_len, + token_info **tis, uint32_t *n, grn_bool *only_skip_token, + grn_id min, grn_operator mode, grn_fuzzy_search_optarg *args) +{ + token_info *ti; + grn_rc rc = GRN_END_OF_DATA; + unsigned int token_flags = GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER; + grn_token_cursor *token_cursor = grn_token_cursor_open(ctx, lexicon, + string, string_len, + GRN_TOKENIZE_ONLY, + token_flags); + *only_skip_token = GRN_FALSE; + if (!token_cursor) { return GRN_NO_MEMORY_AVAILABLE; } + grn_token_cursor_next(ctx, token_cursor); + switch (token_cursor->status) { + case GRN_TOKEN_CURSOR_DONE_SKIP : + *only_skip_token = GRN_TRUE; + goto exit; + case GRN_TOKEN_CURSOR_DOING : + case GRN_TOKEN_CURSOR_DONE : + ti = token_info_open(ctx, lexicon, ii, (const char *)token_cursor->curr, + token_cursor->curr_size, token_cursor->pos, EX_FUZZY, + args, min); + break; + default : + ti = NULL; + break; + } + if (!ti) { + goto exit ; + } + tis[(*n)++] = ti; + while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) { + grn_token_cursor_next(ctx, token_cursor); + switch (token_cursor->status) { + case GRN_TOKEN_CURSOR_DONE_SKIP : + continue; + case GRN_TOKEN_CURSOR_DOING : + case GRN_TOKEN_CURSOR_DONE : + ti = token_info_open(ctx, lexicon, ii, (const char *)token_cursor->curr, + token_cursor->curr_size, token_cursor->pos, EX_FUZZY, + args, min); + break; + default : + break; + } + if (!ti) { + goto exit; + } + tis[(*n)++] = ti; + } + rc = GRN_SUCCESS; +exit : + grn_token_cursor_close(ctx, token_cursor); + return rc; +} + +static void +token_info_clear_offset(token_info **tis, uint32_t n) +{ + token_info **tie; + for (tie = tis + n; tis < tie; tis++) { (*tis)->offset = 0; } +} + +/* select */ + +inline static void +res_add(grn_ctx *ctx, grn_hash *s, grn_rset_posinfo *pi, double score, + grn_operator op) +{ + grn_rset_recinfo *ri; + switch (op) { + case GRN_OP_OR : + if (grn_hash_add(ctx, s, pi, s->key_size, (void **)&ri, NULL)) { + if (s->obj.header.flags & GRN_OBJ_WITH_SUBREC) { + grn_table_add_subrec((grn_obj *)s, ri, score, pi, 1); + } + } + break; + case GRN_OP_AND : + if (grn_hash_get(ctx, s, pi, s->key_size, (void **)&ri)) { + if (s->obj.header.flags & GRN_OBJ_WITH_SUBREC) { + ri->n_subrecs |= GRN_RSET_UTIL_BIT; + grn_table_add_subrec((grn_obj *)s, ri, score, pi, 1); + } + } + break; + case GRN_OP_AND_NOT : + { + grn_id id; + if ((id = grn_hash_get(ctx, s, pi, s->key_size, (void **)&ri))) { + grn_hash_delete_by_id(ctx, s, id, NULL); + } + } + break; + case GRN_OP_ADJUST : + if (grn_hash_get(ctx, s, pi, s->key_size, (void **)&ri)) { + if (s->obj.header.flags & GRN_OBJ_WITH_SUBREC) { + ri->score += score; + } + } + break; + default : + break; + } +} + +grn_rc +grn_ii_posting_add(grn_ctx *ctx, grn_posting *pos, grn_hash *s, grn_operator op) +{ + res_add(ctx, s, (grn_rset_posinfo *)(pos), (1 + pos->weight), op); + return ctx->rc; +} + +#ifdef USE_BHEAP + +/* todo */ + +#else /* USE_BHEAP */ + +struct _btr_node { + struct _btr_node *car; + struct _btr_node *cdr; + token_info *ti; +}; + +typedef struct _btr_node btr_node; + +typedef struct { + int n; + token_info *min; + token_info *max; + btr_node *root; + btr_node *nodes; +} btr; + +inline static void +bt_zap(btr *bt) +{ + bt->n = 0; + bt->min = NULL; + bt->max = NULL; + bt->root = NULL; +} + +inline static btr * +bt_open(grn_ctx *ctx, int size) +{ + btr *bt = GRN_MALLOC(sizeof(btr)); + if (bt) { + bt_zap(bt); + if (!(bt->nodes = GRN_MALLOC(sizeof(btr_node) * size))) { + GRN_FREE(bt); + bt = NULL; + } + } + return bt; +} + +inline static void +bt_close(grn_ctx *ctx, btr *bt) +{ + if (!bt) { return; } + GRN_FREE(bt->nodes); + GRN_FREE(bt); +} + +inline static void +bt_push(btr *bt, token_info *ti) +{ + int pos = ti->pos, minp = 1, maxp = 1; + btr_node *node, *new, **last; + new = bt->nodes + bt->n++; + new->ti = ti; + new->car = NULL; + new->cdr = NULL; + for (last = &bt->root; (node = *last);) { + if (pos < node->ti->pos) { + last = &node->car; + maxp = 0; + } else { + last = &node->cdr; + minp = 0; + } + } + *last = new; + if (minp) { bt->min = ti; } + if (maxp) { bt->max = ti; } +} + +inline static void +bt_pop(btr *bt) +{ + btr_node *node, *min, *newmin, **last; + for (last = &bt->root; (min = *last) && min->car; last = &min->car) ; + if (min) { + int pos = min->ti->pos, minp = 1, maxp = 1; + *last = min->cdr; + min->cdr = NULL; + for (last = &bt->root; (node = *last);) { + if (pos < node->ti->pos) { + last = &node->car; + maxp = 0; + } else { + last = &node->cdr; + minp = 0; + } + } + *last = min; + if (maxp) { bt->max = min->ti; } + if (!minp) { + for (newmin = bt->root; newmin->car; newmin = newmin->car) ; + bt->min = newmin->ti; + } + } +} + +#endif /* USE_BHEAP */ + +typedef enum { + grn_wv_none = 0, + grn_wv_static, + grn_wv_dynamic, + grn_wv_constant +} grn_wv_mode; + +inline static double +get_weight(grn_ctx *ctx, grn_hash *s, grn_id rid, int sid, + grn_wv_mode wvm, grn_select_optarg *optarg) +{ + switch (wvm) { + case grn_wv_none : + return 1; + case grn_wv_static : + return sid <= optarg->vector_size ? optarg->weight_vector[sid - 1] : 0; + case grn_wv_dynamic : + /* todo : support hash with keys + if (s->keys) { + uint32_t key_size; + const char *key = _grn_table_key(ctx, s->keys, rid, &key_size); + // todo : change grn_select_optarg + return key ? optarg->func(s, key, key_size, sid, optarg->func_arg) : 0; + } + */ + /* todo : cast */ + return optarg->func(ctx, (void *)s, (void *)(intptr_t)rid, sid, + optarg->func_arg); + case grn_wv_constant : + return optarg->vector_size; + default : + return 1; + } +} + +grn_rc +grn_ii_similar_search(grn_ctx *ctx, grn_ii *ii, + const char *string, unsigned int string_len, + grn_hash *s, grn_operator op, grn_select_optarg *optarg) +{ + int *w1, limit; + grn_id tid, *tp, max_size; + grn_rc rc = GRN_SUCCESS; + grn_hash *h; + grn_token_cursor *token_cursor; + unsigned int token_flags = GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER; + grn_obj *lexicon = ii->lexicon; + if (!lexicon || !ii || !string || !string_len || !s || !optarg) { + return GRN_INVALID_ARGUMENT; + } + if (!(h = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(int), 0))) { + return GRN_NO_MEMORY_AVAILABLE; + } + if (!(token_cursor = grn_token_cursor_open(ctx, lexicon, string, string_len, + GRN_TOKEN_GET, token_flags))) { + grn_hash_close(ctx, h); + return GRN_NO_MEMORY_AVAILABLE; + } + if (!(max_size = optarg->max_size)) { max_size = 1048576; } + while (token_cursor->status != GRN_TOKEN_CURSOR_DONE && + token_cursor->status != GRN_TOKEN_CURSOR_DONE_SKIP) { + if ((tid = grn_token_cursor_next(ctx, token_cursor))) { + if (grn_hash_add(ctx, h, &tid, sizeof(grn_id), (void **)&w1, NULL)) { + (*w1)++; + } + } + if (tid && token_cursor->curr_size) { + if (optarg->mode == GRN_OP_UNSPLIT) { + grn_table_search(ctx, lexicon, token_cursor->curr, + token_cursor->curr_size, + GRN_OP_PREFIX, (grn_obj *)h, GRN_OP_OR); + } + if (optarg->mode == GRN_OP_PARTIAL) { + grn_table_search(ctx, lexicon, token_cursor->curr, + token_cursor->curr_size, + GRN_OP_SUFFIX, (grn_obj *)h, GRN_OP_OR); + } + } + } + grn_token_cursor_close(ctx, token_cursor); + { + grn_hash_cursor *c = grn_hash_cursor_open(ctx, h, NULL, 0, NULL, 0, + 0, -1, 0); + if (!c) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_hash_cursor_open on grn_ii_similar_search failed !"); + grn_hash_close(ctx, h); + return GRN_NO_MEMORY_AVAILABLE; + } + while (grn_hash_cursor_next(ctx, c)) { + uint32_t es; + grn_hash_cursor_get_key_value(ctx, c, (void **) &tp, NULL, (void **) &w1); + if ((es = grn_ii_estimate_size(ctx, ii, *tp))) { + *w1 += max_size / es; + } else { + grn_hash_cursor_delete(ctx, c, NULL); + } + } + grn_hash_cursor_close(ctx, c); + } + limit = optarg->similarity_threshold + ? (optarg->similarity_threshold > GRN_HASH_SIZE(h) + ? GRN_HASH_SIZE(h) + : optarg->similarity_threshold) + : (GRN_HASH_SIZE(h) >> 3) + 1; + if (GRN_HASH_SIZE(h)) { + grn_id j, id; + int w2, rep; + grn_ii_cursor *c; + grn_posting *pos; + grn_wv_mode wvm = grn_wv_none; + grn_table_sort_optarg arg = { + GRN_TABLE_SORT_DESC|GRN_TABLE_SORT_BY_VALUE|GRN_TABLE_SORT_AS_NUMBER, + NULL, + NULL, + 0 + }; + grn_array *sorted = grn_array_create(ctx, NULL, sizeof(grn_id), 0); + if (!sorted) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_hash_sort on grn_ii_similar_search failed !"); + grn_hash_close(ctx, h); + return GRN_NO_MEMORY_AVAILABLE; + } + grn_hash_sort(ctx, h, limit, sorted, &arg); + /* todo support subrec + rep = (s->record_unit == grn_rec_position || s->subrec_unit == grn_rec_position); + */ + rep = 0; + if (optarg->func) { + wvm = grn_wv_dynamic; + } else if (optarg->vector_size) { + wvm = optarg->weight_vector ? grn_wv_static : grn_wv_constant; + } + for (j = 1; j <= limit; j++) { + grn_array_get_value(ctx, sorted, j, &id); + _grn_hash_get_key_value(ctx, h, id, (void **) &tp, (void **) &w1); + if (!*tp || !(c = grn_ii_cursor_open(ctx, ii, *tp, GRN_ID_NIL, GRN_ID_MAX, + rep + ? ii->n_elements + : ii->n_elements - 1, 0))) { + GRN_LOG(ctx, GRN_LOG_ERROR, "cursor open failed (%d)", *tp); + continue; + } + if (rep) { + while (grn_ii_cursor_next(ctx, c)) { + pos = c->post; + if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg)) > 0) { + while (grn_ii_cursor_next_pos(ctx, c)) { + res_add(ctx, s, (grn_rset_posinfo *) pos, + *w1 * w2 * (1 + pos->weight), op); + } + } + } + } else { + while (grn_ii_cursor_next(ctx, c)) { + pos = c->post; + if ((w2 = get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg)) > 0) { + res_add(ctx, s, (grn_rset_posinfo *) pos, + *w1 * w2 * (pos->tf + pos->weight), op); + } + } + } + grn_ii_cursor_close(ctx, c); + } + grn_array_close(ctx, sorted); + } + grn_hash_close(ctx, h); + grn_ii_resolve_sel_and(ctx, s, op); + // grn_hash_cursor_clear(r); + return rc; +} + +#define TERM_EXTRACT_EACH_POST 0 +#define TERM_EXTRACT_EACH_TERM 1 + +grn_rc +grn_ii_term_extract(grn_ctx *ctx, grn_ii *ii, const char *string, + unsigned int string_len, grn_hash *s, + grn_operator op, grn_select_optarg *optarg) +{ + grn_rset_posinfo pi; + grn_id tid; + const char *p, *pe; + grn_obj *nstr; + const char *normalized; + unsigned int normalized_length_in_bytes; + grn_ii_cursor *c; + grn_posting *pos; + int skip, rep, policy; + grn_rc rc = GRN_SUCCESS; + grn_wv_mode wvm = grn_wv_none; + if (!ii || !string || !string_len || !s || !optarg) { + return GRN_INVALID_ARGUMENT; + } + if (!(nstr = grn_string_open(ctx, string, string_len, NULL, 0))) { + return GRN_INVALID_ARGUMENT; + } + policy = optarg->max_interval; + if (optarg->func) { + wvm = grn_wv_dynamic; + } else if (optarg->vector_size) { + wvm = optarg->weight_vector ? grn_wv_static : grn_wv_constant; + } + /* todo support subrec + if (policy == TERM_EXTRACT_EACH_POST) { + if ((rc = grn_records_reopen(s, grn_rec_section, grn_rec_none, 0))) { goto exit; } + } + rep = (s->record_unit == grn_rec_position || s->subrec_unit == grn_rec_position); + */ + rep = 0; + grn_string_get_normalized(ctx, nstr, &normalized, &normalized_length_in_bytes, + NULL); + for (p = normalized, pe = p + normalized_length_in_bytes; p < pe; p += skip) { + if ((tid = grn_table_lcp_search(ctx, ii->lexicon, p, pe - p))) { + if (policy == TERM_EXTRACT_EACH_POST) { + if (!(skip = grn_table_get_key(ctx, ii->lexicon, tid, NULL, 0))) { break; } + } else { + if (!(skip = (int)grn_charlen(ctx, p, pe))) { break; } + } + if (!(c = grn_ii_cursor_open(ctx, ii, tid, GRN_ID_NIL, GRN_ID_MAX, + rep + ? ii->n_elements + : ii->n_elements - 1, 0))) { + GRN_LOG(ctx, GRN_LOG_ERROR, "cursor open failed (%d)", tid); + continue; + } + if (rep) { + while (grn_ii_cursor_next(ctx, c)) { + pos = c->post; + while (grn_ii_cursor_next_pos(ctx, c)) { + res_add(ctx, s, (grn_rset_posinfo *) pos, + get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg), op); + } + } + } else { + while (grn_ii_cursor_next(ctx, c)) { + if (policy == TERM_EXTRACT_EACH_POST) { + pi.rid = c->post->rid; + pi.sid = p - normalized; + res_add(ctx, s, &pi, pi.sid + 1, op); + } else { + pos = c->post; + res_add(ctx, s, (grn_rset_posinfo *) pos, + get_weight(ctx, s, pos->rid, pos->sid, wvm, optarg), op); + } + } + } + grn_ii_cursor_close(ctx, c); + } else { + if (!(skip = (int)grn_charlen(ctx, p, pe))) { + break; + } + } + } + grn_obj_close(ctx, nstr); + return rc; +} + +typedef struct { + grn_id rid; + uint32_t sid; + uint32_t start_pos; + uint32_t end_pos; + uint32_t tf; + uint32_t weight; +} grn_ii_select_cursor_posting; + +typedef struct { + btr *bt; + grn_ii *ii; + token_info **tis; + uint32_t n_tis; + int max_interval; + grn_operator mode; + grn_ii_select_cursor_posting posting; + const char *string; + unsigned int string_len; + grn_bool done; + grn_ii_select_cursor_posting unshifted_posting; + grn_bool have_unshifted_posting; +} grn_ii_select_cursor; + +static grn_rc +grn_ii_select_cursor_close(grn_ctx *ctx, + grn_ii_select_cursor *cursor) +{ + token_info **tip; + + if (!cursor) { + return GRN_SUCCESS; + } + + for (tip = cursor->tis; tip < cursor->tis + cursor->n_tis; tip++) { + if (*tip) { + token_info_close(ctx, *tip); + } + } + if (cursor->tis) { + GRN_FREE(cursor->tis); + } + bt_close(ctx, cursor->bt); + GRN_FREE(cursor); + + return GRN_SUCCESS; +} + +static grn_ii_select_cursor * +grn_ii_select_cursor_open(grn_ctx *ctx, + grn_ii *ii, + const char *string, + unsigned int string_len, + grn_select_optarg *optarg) +{ + grn_operator mode = GRN_OP_EXACT; + grn_ii_select_cursor *cursor; + + if (string_len == 0) { + ERR(GRN_INVALID_ARGUMENT, + "[ii][select][cursor][open] empty string"); + return NULL; + } + + if (optarg) { + mode = optarg->mode; + } + switch (mode) { + case GRN_OP_EXACT : + case GRN_OP_FUZZY : + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + break; + default : + ERR(GRN_INVALID_ARGUMENT, + "[ii][select][cursor][open] " + "EXACT, FUZZY, NEAR and NEAR2 are only supported mode: %-.256s", + grn_operator_to_string(mode)); + break; + } + + cursor = GRN_CALLOC(sizeof(grn_ii_select_cursor)); + if (!cursor) { + ERR(ctx->rc, + "[ii][select][cursor][open] failed to allocate cursor: %-.256s", + ctx->errbuf); + return NULL; + } + + cursor->ii = ii; + cursor->mode = mode; + + if (!(cursor->tis = GRN_MALLOC(sizeof(token_info *) * string_len * 2))) { + ERR(ctx->rc, + "[ii][select][cursor][open] failed to allocate token info container: %-.256s", + ctx->errbuf); + GRN_FREE(cursor); + return NULL; + } + cursor->n_tis = 0; + if (cursor->mode == GRN_OP_FUZZY) { + grn_bool only_skip_token = GRN_FALSE; + grn_id previous_min = GRN_ID_NIL; + if (token_info_build_fuzzy(ctx, ii->lexicon, ii, string, string_len, + cursor->tis, &(cursor->n_tis), + &only_skip_token, previous_min, + cursor->mode, &(optarg->fuzzy)) != GRN_SUCCESS) { + grn_ii_select_cursor_close(ctx, cursor); + return NULL; + } + } else { + grn_bool only_skip_token = GRN_FALSE; + grn_id previous_min = GRN_ID_NIL; + if (token_info_build(ctx, ii->lexicon, ii, string, string_len, + cursor->tis, &(cursor->n_tis), + &only_skip_token, previous_min, + cursor->mode) != GRN_SUCCESS) { + grn_ii_select_cursor_close(ctx, cursor); + return NULL; + } + } + if (cursor->n_tis == 0) { + grn_ii_select_cursor_close(ctx, cursor); + return NULL; + } + + switch (cursor->mode) { + case GRN_OP_NEAR2 : + token_info_clear_offset(cursor->tis, cursor->n_tis); + cursor->mode = GRN_OP_NEAR; + /* fallthru */ + case GRN_OP_NEAR : + if (!(cursor->bt = bt_open(ctx, cursor->n_tis))) { + ERR(ctx->rc, + "[ii][select][cursor][open] failed to allocate btree: %-.256s", + ctx->errbuf); + grn_ii_select_cursor_close(ctx, cursor); + return NULL; + } + cursor->max_interval = optarg->max_interval; + break; + default : + break; + } + qsort(cursor->tis, cursor->n_tis, sizeof(token_info *), token_compare); + GRN_LOG(ctx, GRN_LOG_INFO, + "[ii][select][cursor][open] n=%d <%.*s>", + cursor->n_tis, + string_len, string); + + cursor->string = string; + cursor->string_len = string_len; + + cursor->done = GRN_FALSE; + + cursor->have_unshifted_posting = GRN_FALSE; + + return cursor; +} + +static grn_ii_select_cursor_posting * +grn_ii_select_cursor_next(grn_ctx *ctx, + grn_ii_select_cursor *cursor) +{ + btr *bt = cursor->bt; + token_info **tis = cursor->tis; + token_info **tie = tis + cursor->n_tis; + uint32_t n_tis = cursor->n_tis; + int max_interval = cursor->max_interval; + grn_operator mode = cursor->mode; + + if (cursor->have_unshifted_posting) { + cursor->have_unshifted_posting = GRN_FALSE; + return &(cursor->unshifted_posting); + } + + if (cursor->done) { + return NULL; + } + + for (;;) { + grn_id rid; + grn_id sid; + grn_id next_rid; + grn_id next_sid; + token_info **tip; + + rid = (*tis)->p->rid; + sid = (*tis)->p->sid; + for (tip = tis + 1, next_rid = rid, next_sid = sid + 1; + tip < tie; + tip++) { + token_info *ti = *tip; + if (token_info_skip(ctx, ti, rid, sid)) { return NULL; } + if (ti->p->rid != rid || ti->p->sid != sid) { + next_rid = ti->p->rid; + next_sid = ti->p->sid; + break; + } + } + + if (tip == tie) { + int start_pos = 0; + int pos = 0; + int end_pos = 0; + int score = 0; + int tf = 0; + int tscore = 0; + +#define SKIP_OR_BREAK(pos) {\ + if (token_info_skip_pos(ctx, ti, rid, sid, pos)) { break; } \ + if (ti->p->rid != rid || ti->p->sid != sid) { \ + next_rid = ti->p->rid; \ + next_sid = ti->p->sid; \ + break; \ + } \ +} + +#define RETURN_POSTING() do { \ + cursor->posting.rid = rid; \ + cursor->posting.sid = sid; \ + cursor->posting.start_pos = start_pos; \ + cursor->posting.end_pos = end_pos; \ + cursor->posting.tf = tf; \ + cursor->posting.weight = tscore; \ + if (token_info_skip_pos(ctx, *tis, rid, sid, pos) != GRN_SUCCESS) { \ + if (token_info_skip(ctx, *tis, next_rid, next_sid) != GRN_SUCCESS) { \ + cursor->done = GRN_TRUE; \ + } \ + } \ + return &(cursor->posting); \ +} while (GRN_FALSE) + + if (n_tis == 1) { + start_pos = pos = end_pos = (*tis)->p->pos; + pos++; + tf = (*tis)->p->tf; + tscore = (*tis)->p->weight + (*tis)->cursors->bins[0]->weight; + RETURN_POSTING(); + } else if (mode == GRN_OP_NEAR) { + bt_zap(bt); + for (tip = tis; tip < tie; tip++) { + token_info *ti = *tip; + SKIP_OR_BREAK(pos); + bt_push(bt, ti); + } + if (tip == tie) { + for (;;) { + token_info *ti; + int min; + int max; + + ti = bt->min; + min = ti->pos; + max = bt->max->pos; + if (min > max) { + char ii_name[GRN_TABLE_MAX_KEY_SIZE]; + int ii_name_size; + ii_name_size = grn_obj_name(ctx, + (grn_obj *)(cursor->ii), + ii_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_FILE_CORRUPT, + "[ii][select][cursor][near] " + "max position must be larger than min position: " + "min:<%d> max:<%d> ii:<%.*s> string:<%.*s>", + min, max, + ii_name_size, ii_name, + cursor->string_len, + cursor->string); + return NULL; + } + if ((max_interval < 0) || (max - min <= max_interval)) { + /* TODO: Set start_pos, pos, end_pos, tf and tscore */ + RETURN_POSTING(); + if (ti->pos == max + 1) { + break; + } + SKIP_OR_BREAK(max + 1); + } else { + if (ti->pos == max - max_interval) { + break; + } + SKIP_OR_BREAK(max - max_interval); + } + bt_pop(bt); + } + } + } else { + int count = 0; + for (tip = tis; ; tip++) { + token_info *ti; + + if (tip == tie) { tip = tis; } + ti = *tip; + SKIP_OR_BREAK(pos); + if (ti->pos == pos) { + score += ti->p->weight + ti->cursors->bins[0]->weight; + count++; + if (ti->p->pos > end_pos) { + end_pos = ti->p->pos; + } + } else { + score = ti->p->weight + ti->cursors->bins[0]->weight; + count = 1; + start_pos = pos = ti->pos; + end_pos = ti->p->pos; + } + if (count == n_tis) { + pos++; + if (ti->p->pos > end_pos) { + end_pos = ti->p->pos; + } + tf = 1; + tscore += score; + RETURN_POSTING(); + } + } + } +#undef SKIP_OR_BREAK + } + if (token_info_skip(ctx, *tis, next_rid, next_sid)) { + return NULL; + } + } +} + +static void +grn_ii_select_cursor_unshift(grn_ctx *ctx, + grn_ii_select_cursor *cursor, + grn_ii_select_cursor_posting *posting) +{ + cursor->unshifted_posting = *posting; + cursor->have_unshifted_posting = GRN_TRUE; +} + +static grn_rc +grn_ii_parse_regexp_query(grn_ctx *ctx, + const char *log_tag, + const char *string, unsigned int string_len, + grn_obj *parsed_strings) +{ + grn_bool escaping = GRN_FALSE; + int nth_char = 0; + const char *current = string; + const char *string_end = string + string_len; + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + while (current < string_end) { + const char *target; + int char_len; + + char_len = grn_charlen(ctx, current, string_end); + if (char_len == 0) { + GRN_OBJ_FIN(ctx, &buffer); + ERR(GRN_INVALID_ARGUMENT, + "%-.256s invalid encoding character: <%.*s|%#x|>", + log_tag, + (int)(current - string), string, + *current); + return ctx->rc; + } + target = current; + current += char_len; + + if (escaping) { + escaping = GRN_FALSE; + if (char_len == 1) { + switch (*target) { + case 'A' : + if (nth_char == 0) { + target = GRN_TOKENIZER_BEGIN_MARK_UTF8; + char_len = GRN_TOKENIZER_BEGIN_MARK_UTF8_LEN; + } + break; + case 'z' : + if (current == string_end) { + target = GRN_TOKENIZER_END_MARK_UTF8; + char_len = GRN_TOKENIZER_END_MARK_UTF8_LEN; + } + break; + default : + break; + } + } + } else { + if (char_len == 1) { + if (*target == '\\') { + escaping = GRN_TRUE; + continue; + } else if (*target == '.' && + grn_charlen(ctx, current, string_end) == 1 && + *current == '*') { + if (GRN_TEXT_LEN(&buffer) > 0) { + grn_vector_add_element(ctx, + parsed_strings, + GRN_TEXT_VALUE(&buffer), + GRN_TEXT_LEN(&buffer), + 0, + GRN_DB_TEXT); + GRN_BULK_REWIND(&buffer); + } + current++; + nth_char++; + continue; + } + } + } + + GRN_TEXT_PUT(ctx, &buffer, target, char_len); + nth_char++; + } + if (GRN_TEXT_LEN(&buffer) > 0) { + grn_vector_add_element(ctx, + parsed_strings, + GRN_TEXT_VALUE(&buffer), + GRN_TEXT_LEN(&buffer), + 0, + GRN_DB_TEXT); + } + GRN_OBJ_FIN(ctx, &buffer); + + return GRN_SUCCESS; +} + +static grn_rc +grn_ii_select_regexp(grn_ctx *ctx, grn_ii *ii, + const char *string, unsigned int string_len, + grn_hash *s, grn_operator op, grn_select_optarg *optarg) +{ + grn_rc rc; + grn_obj parsed_strings; + unsigned int n_parsed_strings; + + GRN_TEXT_INIT(&parsed_strings, GRN_OBJ_VECTOR); + rc = grn_ii_parse_regexp_query(ctx, "[ii][select][regexp]", + string, string_len, &parsed_strings); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FIN(ctx, &parsed_strings); + return rc; + } + + if (optarg) { + optarg->mode = GRN_OP_EXACT; + } + + n_parsed_strings = grn_vector_size(ctx, &parsed_strings); + if (n_parsed_strings == 1) { + const char *parsed_string; + unsigned int parsed_string_len; + parsed_string_len = grn_vector_get_element(ctx, + &parsed_strings, + 0, + &parsed_string, + NULL, + NULL); + rc = grn_ii_select(ctx, ii, + parsed_string, + parsed_string_len, + s, op, optarg); + } else { + int i; + grn_ii_select_cursor **cursors; + grn_bool have_error = GRN_FALSE; + + cursors = GRN_CALLOC(sizeof(grn_ii_select_cursor *) * n_parsed_strings); + for (i = 0; i < n_parsed_strings; i++) { + const char *parsed_string; + unsigned int parsed_string_len; + parsed_string_len = grn_vector_get_element(ctx, + &parsed_strings, + i, + &parsed_string, + NULL, + NULL); + cursors[i] = grn_ii_select_cursor_open(ctx, + ii, + parsed_string, + parsed_string_len, + optarg); + if (!cursors[i]) { + have_error = GRN_TRUE; + break; + } + } + + while (!have_error) { + grn_ii_select_cursor_posting *posting; + uint32_t pos; + + posting = grn_ii_select_cursor_next(ctx, cursors[0]); + if (!posting) { + break; + } + + pos = posting->end_pos; + for (i = 1; i < n_parsed_strings; i++) { + grn_ii_select_cursor_posting *posting_i; + + for (;;) { + posting_i = grn_ii_select_cursor_next(ctx, cursors[i]); + if (!posting_i) { + break; + } + + if (posting_i->rid == posting->rid && + posting_i->sid == posting->sid && + posting_i->start_pos > pos) { + grn_ii_select_cursor_unshift(ctx, cursors[i], posting_i); + break; + } + if (posting_i->rid > posting->rid) { + grn_ii_select_cursor_unshift(ctx, cursors[i], posting_i); + break; + } + } + + if (!posting_i) { + break; + } + + if (posting_i->rid != posting->rid || posting_i->sid != posting->sid) { + break; + } + + pos = posting_i->end_pos; + } + + if (i == n_parsed_strings) { + grn_rset_posinfo pi = {posting->rid, posting->sid, pos}; + double record_score = 1.0; + res_add(ctx, s, &pi, record_score, op); + } + } + + for (i = 0; i < n_parsed_strings; i++) { + if (cursors[i]) { + grn_ii_select_cursor_close(ctx, cursors[i]); + } + } + GRN_FREE(cursors); + } + GRN_OBJ_FIN(ctx, &parsed_strings); + + if (optarg) { + optarg->mode = GRN_OP_REGEXP; + } + + return rc; +} + +#ifdef GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH +static grn_bool +grn_ii_select_sequential_search_should_use(grn_ctx *ctx, + grn_ii *ii, + const char *raw_query, + unsigned int raw_query_len, + grn_hash *result, + grn_operator op, + grn_wv_mode wvm, + grn_select_optarg *optarg, + token_info **token_infos, + uint32_t n_token_infos, + double too_many_index_match_ratio) +{ + int n_sources; + + if (too_many_index_match_ratio < 0.0) { + return GRN_FALSE; + } + + if (op != GRN_OP_AND) { + return GRN_FALSE; + } + + if (optarg->mode != GRN_OP_EXACT) { + return GRN_FALSE; + } + + n_sources = ii->obj.source_size / sizeof(grn_id); + if (n_sources == 0) { + return GRN_FALSE; + } + + { + uint32_t i; + int n_existing_records; + + n_existing_records = GRN_HASH_SIZE(result); + for (i = 0; i < n_token_infos; i++) { + token_info *info = token_infos[i]; + if (n_existing_records <= (info->size * too_many_index_match_ratio)) { + return GRN_TRUE; + } + } + return GRN_FALSE; + } +} + +static void +grn_ii_select_sequential_search_body(grn_ctx *ctx, + grn_ii *ii, + grn_obj *normalizer, + grn_encoding encoding, + OnigRegex regex, + grn_hash *result, + grn_operator op, + grn_wv_mode wvm, + grn_select_optarg *optarg) +{ + int i, n_sources; + grn_id *source_ids = ii->obj.source; + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + n_sources = ii->obj.source_size / sizeof(grn_id); + for (i = 0; i < n_sources; i++) { + grn_id source_id = source_ids[i]; + grn_obj *source; + grn_obj *accessor; + + source = grn_ctx_at(ctx, source_id); + switch (source->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + accessor = grn_obj_column(ctx, + (grn_obj *)result, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + break; + default : + { + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + column_name_size = grn_column_name(ctx, source, + column_name, + GRN_TABLE_MAX_KEY_SIZE); + accessor = grn_obj_column(ctx, (grn_obj *)result, column_name, + column_name_size); + } + break; + } + + { + grn_hash_cursor *cursor; + grn_id id; + cursor = grn_hash_cursor_open(ctx, result, NULL, 0, NULL, 0, 0, -1, 0); + while ((id = grn_hash_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + OnigPosition position; + grn_obj *value; + const char *normalized_value; + unsigned int normalized_value_length; + + GRN_BULK_REWIND(&buffer); + grn_obj_get_value(ctx, accessor, id, &buffer); + value = grn_string_open_(ctx, + GRN_TEXT_VALUE(&buffer), + GRN_TEXT_LEN(&buffer), + normalizer, 0, encoding); + grn_string_get_normalized(ctx, value, + &normalized_value, &normalized_value_length, + NULL); + position = onig_search(regex, + normalized_value, + normalized_value + normalized_value_length, + normalized_value, + normalized_value + normalized_value_length, + NULL, + 0); + if (position != ONIG_MISMATCH) { + grn_id *record_id; + grn_rset_posinfo info; + double score; + + grn_hash_cursor_get_key(ctx, cursor, (void **)&record_id); + + info.rid = *record_id; + info.sid = i + 1; + info.pos = 0; + score = get_weight(ctx, result, info.rid, info.sid, wvm, optarg); + res_add(ctx, result, &info, score, op); + } + grn_obj_unlink(ctx, value); + } + grn_hash_cursor_close(ctx, cursor); + } + grn_obj_unlink(ctx, accessor); + } + grn_obj_unlink(ctx, &buffer); +} + +static grn_bool +grn_ii_select_sequential_search(grn_ctx *ctx, + grn_ii *ii, + const char *raw_query, + unsigned int raw_query_len, + grn_hash *result, + grn_operator op, + grn_wv_mode wvm, + grn_select_optarg *optarg, + token_info **token_infos, + uint32_t n_token_infos) +{ + grn_bool processed = GRN_TRUE; + + { + if (!grn_ii_select_sequential_search_should_use(ctx, + ii, + raw_query, + raw_query_len, + result, + op, + wvm, + optarg, + token_infos, + n_token_infos, + grn_ii_select_too_many_index_match_ratio)) { + return GRN_FALSE; + } + } + + { + grn_encoding encoding; + grn_obj *normalizer; + int nflags = 0; + grn_obj *query; + const char *normalized_query; + unsigned int normalized_query_length; + + grn_table_get_info(ctx, ii->lexicon, + NULL, &encoding, NULL, &normalizer, NULL); + query = grn_string_open_(ctx, raw_query, raw_query_len, + normalizer, nflags, encoding); + grn_string_get_normalized(ctx, query, + &normalized_query, &normalized_query_length, + NULL); + { + OnigRegex regex; + int onig_result; + OnigErrorInfo error_info; + onig_result = onig_new(®ex, + normalized_query, + normalized_query + normalized_query_length, + ONIG_OPTION_NONE, + ONIG_ENCODING_UTF8, + ONIG_SYNTAX_ASIS, + &error_info); + if (onig_result == ONIG_NORMAL) { + grn_ii_select_sequential_search_body(ctx, ii, normalizer, encoding, + regex, result, op, wvm, optarg); + onig_free(regex); + } else { + char message[ONIG_MAX_ERROR_MESSAGE_LEN]; + onig_error_code_to_str(message, onig_result, error_info); + GRN_LOG(ctx, GRN_LOG_WARNING, + "[ii][select][sequential] " + "failed to create regular expression object: %-.256s", + message); + processed = GRN_FALSE; + } + } + grn_obj_unlink(ctx, query); + } + + return processed; +} +#endif + +grn_rc +grn_ii_select(grn_ctx *ctx, grn_ii *ii, + const char *string, unsigned int string_len, + grn_hash *s, grn_operator op, grn_select_optarg *optarg) +{ + btr *bt = NULL; + grn_rc rc = GRN_SUCCESS; + int rep, orp, weight, max_interval = 0; + token_info *ti, **tis = NULL, **tip, **tie; + uint32_t n = 0, rid, sid, nrid, nsid; + grn_bool only_skip_token = GRN_FALSE; + grn_operator mode = GRN_OP_EXACT; + grn_wv_mode wvm = grn_wv_none; + grn_obj *lexicon = ii->lexicon; + grn_scorer_score_func *score_func = NULL; + grn_scorer_matched_record record; + grn_id previous_min = GRN_ID_NIL; + grn_id current_min = GRN_ID_NIL; + grn_bool set_min_enable_for_and_query = GRN_FALSE; + + if (!lexicon || !ii || !s) { return GRN_INVALID_ARGUMENT; } + if (optarg) { + mode = optarg->mode; + if (optarg->func) { + wvm = grn_wv_dynamic; + } else if (optarg->vector_size) { + wvm = optarg->weight_vector ? grn_wv_static : grn_wv_constant; + } + if (optarg->match_info) { + if (optarg->match_info->flags & GRN_MATCH_INFO_GET_MIN_RECORD_ID) { + previous_min = optarg->match_info->min; + set_min_enable_for_and_query = GRN_TRUE; + } + } + } + if (mode == GRN_OP_SIMILAR) { + return grn_ii_similar_search(ctx, ii, string, string_len, s, op, optarg); + } + if (mode == GRN_OP_TERM_EXTRACT) { + return grn_ii_term_extract(ctx, ii, string, string_len, s, op, optarg); + } + if (mode == GRN_OP_REGEXP) { + return grn_ii_select_regexp(ctx, ii, string, string_len, s, op, optarg); + } + /* todo : support subrec + rep = (s->record_unit == grn_rec_position || s->subrec_unit == grn_rec_position); + orp = (s->record_unit == grn_rec_position || op == GRN_OP_OR); + */ + rep = 0; + orp = op == GRN_OP_OR; + if (!string_len) { goto exit; } + if (!(tis = GRN_MALLOC(sizeof(token_info *) * string_len * 2))) { + return GRN_NO_MEMORY_AVAILABLE; + } + if (mode == GRN_OP_FUZZY) { + if (token_info_build_fuzzy(ctx, lexicon, ii, string, string_len, + tis, &n, &only_skip_token, previous_min, + mode, &(optarg->fuzzy)) || + !n) { + goto exit; + } + } else { + if (token_info_build(ctx, lexicon, ii, string, string_len, + tis, &n, &only_skip_token, previous_min, mode) || + !n) { + goto exit; + } + } + switch (mode) { + case GRN_OP_NEAR2 : + token_info_clear_offset(tis, n); + mode = GRN_OP_NEAR; + /* fallthru */ + case GRN_OP_NEAR : + if (!(bt = bt_open(ctx, n))) { rc = GRN_NO_MEMORY_AVAILABLE; goto exit; } + max_interval = optarg->max_interval; + break; + default : + break; + } + qsort(tis, n, sizeof(token_info *), token_compare); + tie = tis + n; + /* + for (tip = tis; tip < tie; tip++) { + ti = *tip; + grn_log("o=%d n=%d s=%d r=%d", ti->offset, ti->ntoken, ti->size, ti->rid); + } + */ + GRN_LOG(ctx, GRN_LOG_INFO, "n=%d (%.*s)", n, string_len, string); + /* todo : array as result + if (n == 1 && (*tis)->cursors->n_entries == 1 && op == GRN_OP_OR + && !GRN_HASH_SIZE(s) && !s->garbages + && s->record_unit == grn_rec_document && !s->max_n_subrecs + && grn_ii_max_section(ii) == 1) { + grn_ii_cursor *c = (*tis)->cursors->bins[0]; + if ((rc = grn_hash_array_init(s, (*tis)->size + 32768))) { goto exit; } + do { + grn_rset_recinfo *ri; + grn_posting *p = c->post; + if ((weight = get_weight(ctx, s, p->rid, p->sid, wvm, optarg))) { + GRN_HASH_INT_ADD(s, p, ri); + ri->score = (p->tf + p->score) * weight; + ri->n_subrecs = 1; + } + } while (grn_ii_cursor_next(ctx, c)); + goto exit; + } + */ +#ifdef GRN_II_SELECT_ENABLE_SEQUENTIAL_SEARCH + if (grn_ii_select_sequential_search(ctx, ii, string, string_len, + s, op, wvm, optarg, tis, n)) { + goto exit; + } +#endif + + if (optarg && optarg->scorer) { + grn_proc *scorer = (grn_proc *)(optarg->scorer); + score_func = scorer->callbacks.scorer.score; + record.table = grn_ctx_at(ctx, s->obj.header.domain); + record.lexicon = lexicon; + record.id = GRN_ID_NIL; + GRN_RECORD_INIT(&(record.terms), GRN_OBJ_VECTOR, lexicon->header.domain); + GRN_UINT32_INIT(&(record.term_weights), GRN_OBJ_VECTOR); + record.total_term_weights = 0; + record.n_documents = grn_table_size(ctx, record.table); + record.n_occurrences = 0; + record.n_candidates = 0; + record.n_tokens = 0; + record.weight = 0; + record.args_expr = optarg->scorer_args_expr; + record.args_expr_offset = optarg->scorer_args_expr_offset; + } + + for (;;) { + rid = (*tis)->p->rid; + sid = (*tis)->p->sid; + for (tip = tis + 1, nrid = rid, nsid = sid + 1; tip < tie; tip++) { + ti = *tip; + if (token_info_skip(ctx, ti, rid, sid)) { goto exit; } + if (ti->p->rid != rid || ti->p->sid != sid) { + nrid = ti->p->rid; + nsid = ti->p->sid; + break; + } + } + weight = get_weight(ctx, s, rid, sid, wvm, optarg); + if (tip == tie && weight != 0) { + grn_rset_posinfo pi = {rid, sid, 0}; + if (orp || grn_hash_get(ctx, s, &pi, s->key_size, NULL)) { + int count = 0, noccur = 0, pos = 0, score = 0, tscore = 0, min, max; + + if (score_func) { + GRN_BULK_REWIND(&(record.terms)); + GRN_BULK_REWIND(&(record.term_weights)); + record.n_candidates = 0; + record.n_tokens = 0; + } + +#define SKIP_OR_BREAK(pos) {\ + if (token_info_skip_pos(ctx, ti, rid, sid, pos)) { break; } \ + if (ti->p->rid != rid || ti->p->sid != sid) { \ + nrid = ti->p->rid; \ + nsid = ti->p->sid; \ + break; \ + } \ +} + if (n == 1 && !rep) { + noccur = (*tis)->p->tf; + tscore = (*tis)->p->weight + (*tis)->cursors->bins[0]->weight; + if (score_func) { + GRN_RECORD_PUT(ctx, &(record.terms), (*tis)->cursors->bins[0]->id); + GRN_UINT32_PUT(ctx, &(record.term_weights), tscore); + record.n_occurrences = noccur; + record.n_candidates = (*tis)->size; + record.n_tokens = (*tis)->ntoken; + } + } else if (mode == GRN_OP_NEAR) { + bt_zap(bt); + for (tip = tis; tip < tie; tip++) { + ti = *tip; + SKIP_OR_BREAK(pos); + bt_push(bt, ti); + } + if (tip == tie) { + for (;;) { + ti = bt->min; min = ti->pos; max = bt->max->pos; + if (min > max) { + char ii_name[GRN_TABLE_MAX_KEY_SIZE]; + int ii_name_size; + ii_name_size = grn_obj_name(ctx, (grn_obj *)ii, ii_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_FILE_CORRUPT, + "[ii][select][near] " + "max position must be larger than min position: " + "min:<%d> max:<%d> ii:<%.*s> string:<%.*s>", + min, max, + ii_name_size, ii_name, + string_len, string); + rc = ctx->rc; + goto exit; + } + if ((max_interval < 0) || (max - min <= max_interval)) { + if (rep) { pi.pos = min; res_add(ctx, s, &pi, weight, op); } + noccur++; + if (ti->pos == max + 1) { + break; + } + SKIP_OR_BREAK(max + 1); + } else { + if (ti->pos == max - max_interval) { + break; + } + SKIP_OR_BREAK(max - max_interval); + } + bt_pop(bt); + } + } + } else { + for (tip = tis; ; tip++) { + if (tip == tie) { tip = tis; } + ti = *tip; + SKIP_OR_BREAK(pos); + if (ti->pos == pos) { + score += ti->p->weight + ti->cursors->bins[0]->weight; count++; + } else { + score = ti->p->weight + ti->cursors->bins[0]->weight; count = 1; + pos = ti->pos; + if (noccur == 0 && score_func) { + GRN_BULK_REWIND(&(record.terms)); + GRN_BULK_REWIND(&(record.term_weights)); + record.n_candidates = 0; + record.n_tokens = 0; + } + } + if (noccur == 0 && score_func) { + GRN_RECORD_PUT(ctx, &(record.terms), ti->cursors->bins[0]->id); + GRN_UINT32_PUT(ctx, &(record.term_weights), + ti->p->weight + ti->cursors->bins[0]->weight); + record.n_candidates += ti->size; + record.n_tokens += ti->ntoken; + } + if (count == n) { + if (rep) { + pi.pos = pos; res_add(ctx, s, &pi, (score + 1) * weight, op); + } + tscore += score; + score = 0; count = 0; pos++; + noccur++; + } + } + } + if (noccur && !rep) { + double record_score; + if (score_func) { + record.id = rid; + record.weight = weight; + record.n_occurrences = noccur; + record.total_term_weights = tscore; + record_score = score_func(ctx, &record) * weight; + } else { + record_score = (noccur + tscore) * weight; + } + if (set_min_enable_for_and_query) { + if (current_min == GRN_ID_NIL) { + current_min = rid; + } + } + res_add(ctx, s, &pi, record_score, op); + } +#undef SKIP_OR_BREAK + } + } + if (token_info_skip(ctx, *tis, nrid, nsid)) { goto exit; } + } +exit : + if (score_func) { + GRN_OBJ_FIN(ctx, &(record.terms)); + GRN_OBJ_FIN(ctx, &(record.term_weights)); + } + + if (set_min_enable_for_and_query) { + if (current_min > previous_min) { + optarg->match_info->min = current_min; + } + } + + for (tip = tis; tip < tis + n; tip++) { + if (*tip) { token_info_close(ctx, *tip); } + } + if (tis) { GRN_FREE(tis); } + if (!only_skip_token) { + grn_ii_resolve_sel_and(ctx, s, op); + } + // grn_hash_cursor_clear(r); + bt_close(ctx, bt); +#ifdef DEBUG + { + uint32_t segno = GRN_II_MAX_LSEG, nnref = 0; + grn_io_mapinfo *info = ii->seg->maps; + for (; segno; segno--, info++) { if (info->nref) { nnref++; } } + GRN_LOG(ctx, GRN_LOG_INFO, "nnref=%d", nnref); + } +#endif /* DEBUG */ + return rc; +} + +static uint32_t +grn_ii_estimate_size_for_query_regexp(grn_ctx *ctx, grn_ii *ii, + const char *query, unsigned int query_len, + grn_search_optarg *optarg) +{ + grn_rc rc; + grn_obj parsed_query; + uint32_t size; + + GRN_TEXT_INIT(&parsed_query, 0); + rc = grn_ii_parse_regexp_query(ctx, "[ii][estimate-size][query][regexp]", + query, query_len, &parsed_query); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FIN(ctx, &parsed_query); + return 0; + } + + if (optarg) { + optarg->mode = GRN_OP_EXACT; + } + + size = grn_ii_estimate_size_for_query(ctx, ii, + GRN_TEXT_VALUE(&parsed_query), + GRN_TEXT_LEN(&parsed_query), + optarg); + GRN_OBJ_FIN(ctx, &parsed_query); + + if (optarg) { + optarg->mode = GRN_OP_REGEXP; + } + + return size; +} + +uint32_t +grn_ii_estimate_size_for_query(grn_ctx *ctx, grn_ii *ii, + const char *query, unsigned int query_len, + grn_search_optarg *optarg) +{ + grn_rc rc; + grn_obj *lexicon = ii->lexicon; + token_info **tis = NULL; + uint32_t i; + uint32_t n_tis = 0; + grn_bool only_skip_token = GRN_FALSE; + grn_operator mode = GRN_OP_EXACT; + double estimated_size = 0; + double normalized_ratio = 1.0; + grn_id min = GRN_ID_NIL; + + if (query_len == 0) { + return 0; + } + + if (optarg) { + switch (optarg->mode) { + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + mode = optarg->mode; + break; + case GRN_OP_SIMILAR : + mode = optarg->mode; + break; + case GRN_OP_REGEXP : + mode = optarg->mode; + break; + case GRN_OP_FUZZY : + mode = optarg->mode; + default : + break; + } + if (optarg->match_info.flags & GRN_MATCH_INFO_GET_MIN_RECORD_ID) { + min = optarg->match_info.min; + } + } + + if (mode == GRN_OP_REGEXP) { + return grn_ii_estimate_size_for_query_regexp(ctx, ii, query, query_len, + optarg); + } + + tis = GRN_MALLOC(sizeof(token_info *) * query_len * 2); + if (!tis) { + return 0; + } + + switch (mode) { + case GRN_OP_FUZZY : + rc = token_info_build_fuzzy(ctx, lexicon, ii, query, query_len, + tis, &n_tis, &only_skip_token, min, + mode, &(optarg->fuzzy)); + break; + default : + rc = token_info_build(ctx, lexicon, ii, query, query_len, + tis, &n_tis, &only_skip_token, min, mode); + break; + } + + if (rc != GRN_SUCCESS) { + goto exit; + } + + for (i = 0; i < n_tis; i++) { + token_info *ti = tis[i]; + double term_estimated_size; + term_estimated_size = ((double)ti->size / ti->ntoken); + if (i == 0) { + estimated_size = term_estimated_size; + } else { + if (term_estimated_size < estimated_size) { + estimated_size = term_estimated_size; + } + normalized_ratio *= grn_ii_estimate_size_for_query_reduce_ratio; + } + } + + estimated_size *= normalized_ratio; + if (estimated_size > 0.0 && estimated_size < 1.0) { + estimated_size = 1.0; + } + +exit : + for (i = 0; i < n_tis; i++) { + token_info *ti = tis[i]; + if (ti) { + token_info_close(ctx, ti); + } + } + if (tis) { + GRN_FREE(tis); + } + + return estimated_size; +} + +uint32_t +grn_ii_estimate_size_for_lexicon_cursor(grn_ctx *ctx, grn_ii *ii, + grn_table_cursor *lexicon_cursor) +{ + grn_id term_id; + uint32_t estimated_size = 0; + + while ((term_id = grn_table_cursor_next(ctx, lexicon_cursor)) != GRN_ID_NIL) { + uint32_t term_estimated_size; + term_estimated_size = grn_ii_estimate_size(ctx, ii, term_id); + estimated_size += term_estimated_size; + } + + return estimated_size; +} + +grn_rc +grn_ii_sel(grn_ctx *ctx, grn_ii *ii, const char *string, unsigned int string_len, + grn_hash *s, grn_operator op, grn_search_optarg *optarg) +{ + ERRCLR(ctx); + GRN_LOG(ctx, GRN_LOG_INFO, "grn_ii_sel > (%.*s)", string_len, string); + { + grn_select_optarg arg; + if (!s) { return GRN_INVALID_ARGUMENT; } + memset(&arg, 0, sizeof(grn_select_optarg)); + arg.mode = GRN_OP_EXACT; + if (optarg) { + switch (optarg->mode) { + case GRN_OP_NEAR : + case GRN_OP_NEAR2 : + arg.mode = optarg->mode; + arg.max_interval = optarg->max_interval; + break; + case GRN_OP_SIMILAR : + arg.mode = optarg->mode; + arg.similarity_threshold = optarg->similarity_threshold; + break; + case GRN_OP_REGEXP : + arg.mode = optarg->mode; + break; + case GRN_OP_FUZZY : + arg.mode = optarg->mode; + arg.fuzzy = optarg->fuzzy; + break; + default : + break; + } + if (optarg->vector_size != 0) { + arg.weight_vector = optarg->weight_vector; + arg.vector_size = optarg->vector_size; + } + arg.scorer = optarg->scorer; + arg.scorer_args_expr = optarg->scorer_args_expr; + arg.scorer_args_expr_offset = optarg->scorer_args_expr_offset; + arg.match_info = &(optarg->match_info); + } + /* todo : support subrec + grn_rset_init(ctx, s, grn_rec_document, 0, grn_rec_none, 0, 0); + */ + if (grn_ii_select(ctx, ii, string, string_len, s, op, &arg)) { + GRN_LOG(ctx, GRN_LOG_ERROR, "grn_ii_select on grn_ii_sel(1) failed !"); + return ctx->rc; + } + GRN_LOG(ctx, GRN_LOG_INFO, "exact: %d", GRN_HASH_SIZE(s)); + if (op == GRN_OP_OR) { + grn_id min = GRN_ID_NIL; + if ((int64_t)GRN_HASH_SIZE(s) <= ctx->impl->match_escalation_threshold) { + arg.mode = GRN_OP_UNSPLIT; + if (arg.match_info) { + if (arg.match_info->flags & GRN_MATCH_INFO_GET_MIN_RECORD_ID) { + min = arg.match_info->min; + arg.match_info->min = GRN_ID_NIL; + } + } + if (grn_ii_select(ctx, ii, string, string_len, s, op, &arg)) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "grn_ii_select on grn_ii_sel(2) failed !"); + return ctx->rc; + } + GRN_LOG(ctx, GRN_LOG_INFO, "unsplit: %d", GRN_HASH_SIZE(s)); + if (arg.match_info) { + if (arg.match_info->flags & GRN_MATCH_INFO_GET_MIN_RECORD_ID) { + if (min > GRN_ID_NIL && min < arg.match_info->min) { + arg.match_info->min = min; + } + } + } + } + if ((int64_t)GRN_HASH_SIZE(s) <= ctx->impl->match_escalation_threshold) { + arg.mode = GRN_OP_PARTIAL; + if (arg.match_info) { + if (arg.match_info->flags & GRN_MATCH_INFO_GET_MIN_RECORD_ID) { + min = arg.match_info->min; + arg.match_info->min = GRN_ID_NIL; + } + } + if (grn_ii_select(ctx, ii, string, string_len, s, op, &arg)) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "grn_ii_select on grn_ii_sel(3) failed !"); + return ctx->rc; + } + GRN_LOG(ctx, GRN_LOG_INFO, "partial: %d", GRN_HASH_SIZE(s)); + if (arg.match_info) { + if (arg.match_info->flags & GRN_MATCH_INFO_GET_MIN_RECORD_ID) { + if (min > GRN_ID_NIL && min < arg.match_info->min) { + arg.match_info->min = min; + } + } + } + } + } + GRN_LOG(ctx, GRN_LOG_INFO, "hits=%d", GRN_HASH_SIZE(s)); + return GRN_SUCCESS; + } +} + +grn_rc +grn_ii_at(grn_ctx *ctx, grn_ii *ii, grn_id id, grn_hash *s, grn_operator op) +{ + int rep = 0; + grn_ii_cursor *c; + grn_posting *pos; + if ((c = grn_ii_cursor_open(ctx, ii, id, GRN_ID_NIL, GRN_ID_MAX, + rep ? ii->n_elements : ii->n_elements - 1, 0))) { + while ((pos = grn_ii_cursor_next(ctx, c))) { + res_add(ctx, s, (grn_rset_posinfo *) pos, (1 + pos->weight), op); + } + grn_ii_cursor_close(ctx, c); + } + return ctx->rc; +} + +void +grn_ii_resolve_sel_and(grn_ctx *ctx, grn_hash *s, grn_operator op) +{ + if (op == GRN_OP_AND + && !(ctx->flags & GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND)) { + grn_id eid; + grn_rset_recinfo *ri; + grn_hash_cursor *c = grn_hash_cursor_open(ctx, s, NULL, 0, NULL, 0, + 0, -1, 0); + if (c) { + while ((eid = grn_hash_cursor_next(ctx, c))) { + grn_hash_cursor_get_value(ctx, c, (void **) &ri); + if ((ri->n_subrecs & GRN_RSET_UTIL_BIT)) { + ri->n_subrecs &= ~GRN_RSET_UTIL_BIT; + } else { + grn_hash_delete_by_id(ctx, s, eid, NULL); + } + } + grn_hash_cursor_close(ctx, c); + } + } +} + +void +grn_ii_cursor_inspect(grn_ctx *ctx, grn_ii_cursor *c, grn_obj *buf) +{ + grn_obj key_buf; + char key[GRN_TABLE_MAX_KEY_SIZE]; + int key_size; + int i = 0; + grn_ii_cursor_next_options options = { + .include_garbage = GRN_TRUE + }; + + GRN_TEXT_PUTS(ctx, buf, " #<"); + key_size = grn_table_get_key(ctx, c->ii->lexicon, c->id, + key, GRN_TABLE_MAX_KEY_SIZE); + GRN_OBJ_INIT(&key_buf, GRN_BULK, 0, c->ii->lexicon->header.domain); + GRN_TEXT_SET(ctx, &key_buf, key, key_size); + grn_inspect(ctx, buf, &key_buf); + GRN_OBJ_FIN(ctx, &key_buf); + + GRN_TEXT_PUTS(ctx, buf, "\n elements:[\n "); + while (grn_ii_cursor_next_internal(ctx, c, &options)) { + grn_posting *pos = c->post; + if (i > 0) { + GRN_TEXT_PUTS(ctx, buf, ",\n "); + } + i++; + GRN_TEXT_PUTS(ctx, buf, "{status:"); + if (pos->tf && pos->sid) { + GRN_TEXT_PUTS(ctx, buf, "available"); + } else { + GRN_TEXT_PUTS(ctx, buf, "garbage"); + } + GRN_TEXT_PUTS(ctx, buf, ", rid:"); + grn_text_lltoa(ctx, buf, pos->rid); + GRN_TEXT_PUTS(ctx, buf, ", sid:"); + grn_text_lltoa(ctx, buf, pos->sid); + GRN_TEXT_PUTS(ctx, buf, ", pos:"); + grn_text_lltoa(ctx, buf, pos->pos); + GRN_TEXT_PUTS(ctx, buf, ", tf:"); + grn_text_lltoa(ctx, buf, pos->tf); + GRN_TEXT_PUTS(ctx, buf, ", weight:"); + grn_text_lltoa(ctx, buf, pos->weight); + GRN_TEXT_PUTS(ctx, buf, ", rest:"); + grn_text_lltoa(ctx, buf, pos->rest); + GRN_TEXT_PUTS(ctx, buf, "}"); + } + GRN_TEXT_PUTS(ctx, buf, "\n ]\n >"); +} + +void +grn_ii_inspect_values(grn_ctx *ctx, grn_ii *ii, grn_obj *buf) +{ + grn_table_cursor *tc; + GRN_TEXT_PUTS(ctx, buf, "["); + if ((tc = grn_table_cursor_open(ctx, ii->lexicon, NULL, 0, NULL, 0, 0, -1, + GRN_CURSOR_ASCENDING))) { + int i = 0; + grn_id tid; + grn_ii_cursor *c; + while ((tid = grn_table_cursor_next(ctx, tc))) { + if (i > 0) { + GRN_TEXT_PUTS(ctx, buf, ","); + } + i++; + GRN_TEXT_PUTS(ctx, buf, "\n"); + if ((c = grn_ii_cursor_open(ctx, ii, tid, GRN_ID_NIL, GRN_ID_MAX, + ii->n_elements, + GRN_OBJ_WITH_POSITION|GRN_OBJ_WITH_SECTION))) { + grn_ii_cursor_inspect(ctx, c, buf); + grn_ii_cursor_close(ctx, c); + } + } + grn_table_cursor_close(ctx, tc); + } + GRN_TEXT_PUTS(ctx, buf, "]"); +} + +/********************** buffered index builder ***********************/ + +const grn_id II_BUFFER_TYPE_MASK = 0xc0000000; +#define II_BUFFER_TYPE_RID 0x80000000 +#define II_BUFFER_TYPE_WEIGHT 0x40000000 +#define II_BUFFER_TYPE(id) (((id) & II_BUFFER_TYPE_MASK)) +#define II_BUFFER_PACK(value, type) ((value) | (type)) +#define II_BUFFER_UNPACK(id, type) ((id) & ~(type)) +#define II_BUFFER_ORDER GRN_CURSOR_BY_KEY +const uint16_t II_BUFFER_NTERMS_PER_BUFFER = 16380; +const uint32_t II_BUFFER_PACKED_BUF_SIZE = 0x4000000; +const char *TMPFILE_PATH = "grn_ii_buffer_tmp"; +const uint32_t II_BUFFER_NCOUNTERS_MARGIN = 0x100000; +const size_t II_BUFFER_BLOCK_SIZE = 0x1000000; +const uint32_t II_BUFFER_BLOCK_READ_UNIT_SIZE = 0x200000; + +typedef struct { + unsigned int sid; /* Section ID */ + unsigned int weight; /* Weight */ + const char *p; /* Value address */ + uint32_t len; /* Value length */ + char *buf; /* Buffer address */ + uint32_t cap; /* Buffer size */ +} ii_buffer_value; + +/* ii_buffer_counter is associated with a combination of a block an a term. */ +typedef struct { + uint32_t nrecs; /* Number of records or sections */ + uint32_t nposts; /* Number of occurrences */ + + /* Information of the last value */ + grn_id last_rid; /* Record ID */ + uint32_t last_sid; /* Section ID */ + uint32_t last_tf; /* Term frequency */ + uint32_t last_weight; /* Total weight */ + uint32_t last_pos; /* Token position */ + + /* Meaning of offset_* is different before/after encoding. */ + /* Before encoding: size in encoded sequence */ + /* After encoding: Offset in encoded sequence */ + uint32_t offset_rid; /* Record ID */ + uint32_t offset_sid; /* Section ID */ + uint32_t offset_tf; /* Term frequency */ + uint32_t offset_weight; /* Weight */ + uint32_t offset_pos; /* Token position */ +} ii_buffer_counter; + +typedef struct { + off64_t head; + off64_t tail; + uint32_t nextsize; + uint8_t *buffer; + uint32_t buffersize; + uint8_t *bufcur; + uint32_t rest; + grn_id tid; + uint32_t nrecs; + uint32_t nposts; + grn_id *recs; + uint32_t *tfs; + uint32_t *posts; +} ii_buffer_block; + +struct _grn_ii_buffer { + grn_obj *lexicon; /* Global lexicon */ + grn_obj *tmp_lexicon; /* Temporary lexicon for each block */ + ii_buffer_block *blocks; /* Blocks */ + uint32_t nblocks; /* Number of blocks */ + int tmpfd; /* Descriptor of temporary file */ + char tmpfpath[PATH_MAX]; /* Path of temporary file */ + uint64_t update_buffer_size; + + // stuff for parsing + off64_t filepos; /* Write position of temporary file */ + grn_id *block_buf; /* Buffer for the current block */ + size_t block_buf_size; /* Size of block_buf */ + size_t block_pos; /* Write position of block_buf */ + ii_buffer_counter *counters; /* Status of terms */ + uint32_t ncounters; /* Number of counters */ + size_t total_size; + size_t curr_size; + ii_buffer_value *values; /* Values in block */ + unsigned int nvalues; /* Number of values in block */ + unsigned int max_nvalues; /* Size of values */ + grn_id last_rid; + + // stuff for merging + grn_ii *ii; + uint32_t lseg; + uint32_t dseg; + buffer *term_buffer; + datavec data_vectors[MAX_N_ELEMENTS + 1]; + uint8_t *packed_buf; + size_t packed_buf_size; + size_t packed_len; + size_t total_chunk_size; +}; + +/* block_new returns a new ii_buffer_block to store block information. */ +static ii_buffer_block * +block_new(grn_ctx *ctx, grn_ii_buffer *ii_buffer) +{ + ii_buffer_block *block; + if (!(ii_buffer->nblocks & 0x3ff)) { + ii_buffer_block *blocks; + if (!(blocks = GRN_REALLOC(ii_buffer->blocks, + (ii_buffer->nblocks + 0x400) * + sizeof(ii_buffer_block)))) { + return NULL; + } + ii_buffer->blocks = blocks; + } + block = &ii_buffer->blocks[ii_buffer->nblocks]; + block->head = ii_buffer->filepos; + block->rest = 0; + block->buffer = NULL; + block->buffersize = 0; + return block; +} + +/* allocate_outbuf allocates memory to flush a block. */ +static uint8_t * +allocate_outbuf(grn_ctx *ctx, grn_ii_buffer *ii_buffer) +{ + size_t bufsize = 0, bufsize_ = 0; + uint32_t flags = ii_buffer->ii->header->flags; + ii_buffer_counter *counter = ii_buffer->counters; + grn_id tid, tid_max = grn_table_size(ctx, ii_buffer->tmp_lexicon); + for (tid = 1; tid <= tid_max; counter++, tid++) { + counter->offset_tf += GRN_B_ENC_SIZE(counter->last_tf - 1); + counter->last_rid = 0; + counter->last_tf = 0; + bufsize += 5; + bufsize += GRN_B_ENC_SIZE(counter->nrecs); + bufsize += GRN_B_ENC_SIZE(counter->nposts); + bufsize += counter->offset_rid; + if ((flags & GRN_OBJ_WITH_SECTION)) { + bufsize += counter->offset_sid; + } + bufsize += counter->offset_tf; + if ((flags & GRN_OBJ_WITH_WEIGHT)) { + bufsize += counter->offset_weight; + } + if ((flags & GRN_OBJ_WITH_POSITION)) { + bufsize += counter->offset_pos; + } + if (bufsize_ + II_BUFFER_BLOCK_READ_UNIT_SIZE < bufsize) { + bufsize += sizeof(uint32_t); + bufsize_ = bufsize; + } + } + GRN_LOG(ctx, GRN_LOG_INFO, "flushing:%d bufsize:%" GRN_FMT_SIZE, + ii_buffer->nblocks, bufsize); + return (uint8_t *)GRN_MALLOC(bufsize); +} + +/* + * The temporary file format is roughly as follows: + * + * File = Block... + * Block = Unit... + * Unit = TermChunk (key order) + * NextUnitSize (The first unit size is kept on memory) + * Chunk = Term... + * Term = ID (gtid) + * NumRecordsOrSections (nrecs), NumOccurrences (nposts) + * RecordID... (rid, diff) + * [SectionID... (sid, diff)] + * TermFrequency... (tf, diff) + * [Weight... (weight, diff)] + * [Position... (pos, diff)] + */ + +/* + * encode_terms encodes terms in ii_buffer->tmp_lexicon and returns the + * expected temporary file size. + */ +static size_t +encode_terms(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + uint8_t *outbuf, ii_buffer_block *block) +{ + grn_id tid; + uint8_t *outbufp = outbuf; + uint8_t *outbufp_ = outbuf; + grn_table_cursor *tc; + /* The first size is written into block->nextsize. */ + uint8_t *pnext = (uint8_t *)&block->nextsize; + uint32_t flags = ii_buffer->ii->header->flags; + tc = grn_table_cursor_open(ctx, ii_buffer->tmp_lexicon, + NULL, 0, NULL, 0, 0, -1, II_BUFFER_ORDER); + while ((tid = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) { + char key[GRN_TABLE_MAX_KEY_SIZE]; + int key_size = grn_table_get_key(ctx, ii_buffer->tmp_lexicon, tid, + key, GRN_TABLE_MAX_KEY_SIZE); + /* gtid is a global term ID, not in a temporary lexicon. */ + grn_id gtid = grn_table_add(ctx, ii_buffer->lexicon, key, key_size, NULL); + ii_buffer_counter *counter = &ii_buffer->counters[tid - 1]; + if (counter->nrecs) { + uint32_t offset_rid = counter->offset_rid; + uint32_t offset_sid = counter->offset_sid; + uint32_t offset_tf = counter->offset_tf; + uint32_t offset_weight = counter->offset_weight; + uint32_t offset_pos = counter->offset_pos; + GRN_B_ENC(gtid, outbufp); + GRN_B_ENC(counter->nrecs, outbufp); + GRN_B_ENC(counter->nposts, outbufp); + ii_buffer->total_size += counter->nrecs + counter->nposts; + counter->offset_rid = outbufp - outbuf; + outbufp += offset_rid; + if ((flags & GRN_OBJ_WITH_SECTION)) { + counter->offset_sid = outbufp - outbuf; + outbufp += offset_sid; + } + counter->offset_tf = outbufp - outbuf; + outbufp += offset_tf; + if ((flags & GRN_OBJ_WITH_WEIGHT)) { + counter->offset_weight = outbufp - outbuf; + outbufp += offset_weight; + } + if ((flags & GRN_OBJ_WITH_POSITION)) { + counter->offset_pos = outbufp - outbuf; + outbufp += offset_pos; + } + } + if (outbufp_ + II_BUFFER_BLOCK_READ_UNIT_SIZE < outbufp) { + uint32_t size = outbufp - outbufp_ + sizeof(uint32_t); + grn_memcpy(pnext, &size, sizeof(uint32_t)); + pnext = outbufp; + outbufp += sizeof(uint32_t); + outbufp_ = outbufp; + } + } + grn_table_cursor_close(ctx, tc); + if (outbufp_ < outbufp) { + uint32_t size = outbufp - outbufp_; + grn_memcpy(pnext, &size, sizeof(uint32_t)); + } + return outbufp - outbuf; +} + +/* encode_postings encodes data in ii_buffer->block_buf. */ +static void +encode_postings(grn_ctx *ctx, grn_ii_buffer *ii_buffer, uint8_t *outbuf) +{ + grn_id rid = 0; + unsigned int sid = 1; + unsigned int weight = 0; + uint32_t pos = 0; + uint32_t rest; + grn_id *bp = ii_buffer->block_buf; + uint32_t flags = ii_buffer->ii->header->flags; + for (rest = ii_buffer->block_pos; rest; bp++, rest--) { + grn_id id = *bp; + switch (II_BUFFER_TYPE(id)) { + case II_BUFFER_TYPE_RID : + rid = II_BUFFER_UNPACK(id, II_BUFFER_TYPE_RID); + if ((flags & GRN_OBJ_WITH_SECTION) && rest) { + sid = *++bp; + rest--; + } + weight = 0; + pos = 0; + break; + case II_BUFFER_TYPE_WEIGHT : + weight = II_BUFFER_UNPACK(id, II_BUFFER_TYPE_WEIGHT); + break; + default : + { + ii_buffer_counter *counter = &ii_buffer->counters[id - 1]; + if (counter->last_rid == rid && counter->last_sid == sid) { + counter->last_tf++; + counter->last_weight += weight; + } else { + if (counter->last_tf) { + uint8_t *p = outbuf + counter->offset_tf; + GRN_B_ENC(counter->last_tf - 1, p); + counter->offset_tf = p - outbuf; + if (flags & GRN_OBJ_WITH_WEIGHT) { + p = outbuf + counter->offset_weight; + GRN_B_ENC(counter->last_weight, p); + counter->offset_weight = p - outbuf; + } + } + { + uint8_t *p = outbuf + counter->offset_rid; + GRN_B_ENC(rid - counter->last_rid, p); + counter->offset_rid = p - outbuf; + } + if (flags & GRN_OBJ_WITH_SECTION) { + uint8_t *p = outbuf + counter->offset_sid; + if (counter->last_rid != rid) { + GRN_B_ENC(sid - 1, p); + } else { + GRN_B_ENC(sid - counter->last_sid - 1, p); + } + counter->offset_sid = p - outbuf; + } + counter->last_rid = rid; + counter->last_sid = sid; + counter->last_tf = 1; + counter->last_weight = weight; + counter->last_pos = 0; + } + if ((flags & GRN_OBJ_WITH_POSITION) && rest) { + uint8_t *p = outbuf + counter->offset_pos; + pos = *++bp; + rest--; + GRN_B_ENC(pos - counter->last_pos, p); + counter->offset_pos = p - outbuf; + counter->last_pos = pos; + } + } + break; + } + } +} + +/* encode_last_tf encodes last_tf and last_weight in counters. */ +static void +encode_last_tf(grn_ctx *ctx, grn_ii_buffer *ii_buffer, uint8_t *outbuf) +{ + ii_buffer_counter *counter = ii_buffer->counters; + grn_id tid, tid_max = grn_table_size(ctx, ii_buffer->tmp_lexicon); + for (tid = 1; tid <= tid_max; counter++, tid++) { + uint8_t *p = outbuf + counter->offset_tf; + GRN_B_ENC(counter->last_tf - 1, p); + } + if ((ii_buffer->ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { + for (tid = 1; tid <= tid_max; counter++, tid++) { + uint8_t *p = outbuf + counter->offset_weight; + GRN_B_ENC(counter->last_weight, p); + } + } +} + +/* + * grn_ii_buffer_flush flushes the current block (ii_buffer->block_buf, + * counters and tmp_lexicon) to a temporary file (ii_buffer->tmpfd). + * Also, block information is stored into ii_buffer->blocks. + */ +static void +grn_ii_buffer_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer) +{ + size_t encsize; + uint8_t *outbuf; + ii_buffer_block *block; + GRN_LOG(ctx, GRN_LOG_DEBUG, "flushing:%d npostings:%" GRN_FMT_SIZE, + ii_buffer->nblocks, ii_buffer->block_pos); + if (!(block = block_new(ctx, ii_buffer))) { return; } + if (!(outbuf = allocate_outbuf(ctx, ii_buffer))) { return; } + encsize = encode_terms(ctx, ii_buffer, outbuf, block); + encode_postings(ctx, ii_buffer, outbuf); + encode_last_tf(ctx, ii_buffer, outbuf); + { + ssize_t r = grn_write(ii_buffer->tmpfd, outbuf, encsize); + if (r != encsize) { + ERR(GRN_INPUT_OUTPUT_ERROR, + "write returned %" GRN_FMT_LLD " != %" GRN_FMT_LLU, + (long long int)r, (unsigned long long int)encsize); + GRN_FREE(outbuf); + return; + } + ii_buffer->filepos += r; + block->tail = ii_buffer->filepos; + } + GRN_FREE(outbuf); + memset(ii_buffer->counters, 0, + grn_table_size(ctx, ii_buffer->tmp_lexicon) * + sizeof(ii_buffer_counter)); + grn_obj_close(ctx, ii_buffer->tmp_lexicon); + GRN_LOG(ctx, GRN_LOG_DEBUG, "flushed: %d encsize:%" GRN_FMT_SIZE, + ii_buffer->nblocks, encsize); + ii_buffer->tmp_lexicon = NULL; + ii_buffer->nblocks++; + ii_buffer->block_pos = 0; +} + +const uint32_t PAT_CACHE_SIZE = 1<<20; + +/* + * get_tmp_lexicon returns a temporary lexicon. + * + * Note that a lexicon is created for each block and ii_buffer->tmp_lexicon is + * closed in grn_ii_buffer_flush. + */ +static grn_obj * +get_tmp_lexicon(grn_ctx *ctx, grn_ii_buffer *ii_buffer) +{ + grn_obj *tmp_lexicon = ii_buffer->tmp_lexicon; + if (!tmp_lexicon) { + grn_obj *domain = grn_ctx_at(ctx, ii_buffer->lexicon->header.domain); + grn_obj *range = grn_ctx_at(ctx, DB_OBJ(ii_buffer->lexicon)->range); + grn_obj *tokenizer; + grn_obj *normalizer; + grn_obj *token_filters; + grn_table_flags flags; + grn_table_get_info(ctx, ii_buffer->lexicon, &flags, NULL, + &tokenizer, &normalizer, &token_filters); + flags &= ~GRN_OBJ_PERSISTENT; + tmp_lexicon = grn_table_create(ctx, NULL, 0, NULL, flags, domain, range); + if (tmp_lexicon) { + ii_buffer->tmp_lexicon = tmp_lexicon; + grn_obj_set_info(ctx, tmp_lexicon, + GRN_INFO_DEFAULT_TOKENIZER, tokenizer); + grn_obj_set_info(ctx, tmp_lexicon, + GRN_INFO_NORMALIZER, normalizer); + grn_obj_set_info(ctx, tmp_lexicon, + GRN_INFO_TOKEN_FILTERS, token_filters); + if ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_PAT_KEY) { + grn_pat_cache_enable(ctx, (grn_pat *)tmp_lexicon, PAT_CACHE_SIZE); + } + } + } + return tmp_lexicon; +} + +/* get_buffer_counter returns a counter associated with tid. */ +static ii_buffer_counter * +get_buffer_counter(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + grn_obj *tmp_lexicon, grn_id tid) +{ + if (tid > ii_buffer->ncounters) { + ii_buffer_counter *counters; + uint32_t ncounters = + grn_table_size(ctx, tmp_lexicon) + II_BUFFER_NCOUNTERS_MARGIN; + counters = GRN_REALLOC(ii_buffer->counters, + ncounters * sizeof(ii_buffer_counter)); + if (!counters) { return NULL; } + memset(&counters[ii_buffer->ncounters], 0, + (ncounters - ii_buffer->ncounters) * sizeof(ii_buffer_counter)); + ii_buffer->ncounters = ncounters; + ii_buffer->counters = counters; + } + return &ii_buffer->counters[tid - 1]; +} + +/* + * grn_ii_buffer_tokenize_value tokenizes a value. + * + * The result is written into the current block (ii_buffer->tmp_lexicon, + * ii_buffer->block_buf, ii_buffer->counters, etc.). + */ +static void +grn_ii_buffer_tokenize_value(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + grn_id rid, const ii_buffer_value *value) +{ + grn_obj *tmp_lexicon; + if ((tmp_lexicon = get_tmp_lexicon(ctx, ii_buffer))) { + unsigned int token_flags = 0; + grn_token_cursor *token_cursor; + grn_id *buffer = ii_buffer->block_buf; + uint32_t block_pos = ii_buffer->block_pos; + uint32_t ii_flags = ii_buffer->ii->header->flags; + buffer[block_pos++] = II_BUFFER_PACK(rid, II_BUFFER_TYPE_RID); + if (ii_flags & GRN_OBJ_WITH_SECTION) { + buffer[block_pos++] = value->sid; + } + if (value->weight) { + buffer[block_pos++] = II_BUFFER_PACK(value->weight, + II_BUFFER_TYPE_WEIGHT); + } + if ((token_cursor = grn_token_cursor_open(ctx, tmp_lexicon, + value->p, value->len, + GRN_TOKEN_ADD, token_flags))) { + while (!token_cursor->status) { + grn_id tid; + if ((tid = grn_token_cursor_next(ctx, token_cursor))) { + ii_buffer_counter *counter; + counter = get_buffer_counter(ctx, ii_buffer, tmp_lexicon, tid); + if (!counter) { return; } + buffer[block_pos++] = tid; + if (ii_flags & GRN_OBJ_WITH_POSITION) { + buffer[block_pos++] = token_cursor->pos; + } + if (counter->last_rid != rid) { + counter->offset_rid += GRN_B_ENC_SIZE(rid - counter->last_rid); + counter->last_rid = rid; + counter->offset_sid += GRN_B_ENC_SIZE(value->sid - 1); + counter->last_sid = value->sid; + if (counter->last_tf) { + counter->offset_tf += GRN_B_ENC_SIZE(counter->last_tf - 1); + counter->last_tf = 0; + counter->offset_weight += GRN_B_ENC_SIZE(counter->last_weight); + counter->last_weight = 0; + } + counter->last_pos = 0; + counter->nrecs++; + } else if (counter->last_sid != value->sid) { + counter->offset_rid += GRN_B_ENC_SIZE(0); + counter->offset_sid += + GRN_B_ENC_SIZE(value->sid - counter->last_sid - 1); + counter->last_sid = value->sid; + if (counter->last_tf) { + counter->offset_tf += GRN_B_ENC_SIZE(counter->last_tf - 1); + counter->last_tf = 0; + counter->offset_weight += GRN_B_ENC_SIZE(counter->last_weight); + counter->last_weight = 0; + } + counter->last_pos = 0; + counter->nrecs++; + } + counter->offset_pos += + GRN_B_ENC_SIZE(token_cursor->pos - counter->last_pos); + counter->last_pos = token_cursor->pos; + counter->last_tf++; + counter->last_weight += value->weight; + counter->nposts++; + } + } + grn_token_cursor_close(ctx, token_cursor); + } + ii_buffer->block_pos = block_pos; + } +} + +/* + * grn_ii_buffer_tokenize tokenizes ii_buffer->values. + * + * grn_ii_buffer_tokenize estimates the size of tokenized values. + * If the remaining space of the current block is not enough to store the new + * tokenized values, the current block is flushed. + * Then, grn_ii_buffer_tokenize tokenizes values. + */ +static void +grn_ii_buffer_tokenize(grn_ctx *ctx, grn_ii_buffer *ii_buffer, grn_id rid) +{ + unsigned int i; + uint32_t est_len = 0; + for (i = 0; i < ii_buffer->nvalues; i++) { + est_len += ii_buffer->values[i].len * 2 + 2; + } + if (ii_buffer->block_buf_size < ii_buffer->block_pos + est_len) { + grn_ii_buffer_flush(ctx, ii_buffer); + } + if (ii_buffer->block_buf_size < est_len) { + grn_id *block_buf = (grn_id *)GRN_REALLOC(ii_buffer->block_buf, + est_len * sizeof(grn_id)); + if (block_buf) { + ii_buffer->block_buf = block_buf; + ii_buffer->block_buf_size = est_len; + } + } + + for (i = 0; i < ii_buffer->nvalues; i++) { + const ii_buffer_value *value = &ii_buffer->values[i]; + if (value->len) { + uint32_t est_len = value->len * 2 + 2; + if (ii_buffer->block_buf_size >= ii_buffer->block_pos + est_len) { + grn_ii_buffer_tokenize_value(ctx, ii_buffer, rid, value); + } + } + } + ii_buffer->nvalues = 0; +} + +/* grn_ii_buffer_fetch fetches the next term. */ +static void +grn_ii_buffer_fetch(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + ii_buffer_block *block) +{ + if (!block->rest) { + /* Read the next unit. */ + if (block->head < block->tail) { + size_t bytesize = block->nextsize; + if (block->buffersize < block->nextsize) { + void *r = GRN_REALLOC(block->buffer, bytesize); + if (r) { + block->buffer = (uint8_t *)r; + block->buffersize = block->nextsize; + } else { + GRN_LOG(ctx, GRN_LOG_WARNING, "realloc: %" GRN_FMT_LLU, + (unsigned long long int)bytesize); + return; + } + } + { + off64_t seeked_position; + seeked_position = grn_lseek(ii_buffer->tmpfd, block->head, SEEK_SET); + if (seeked_position != block->head) { + ERRNO_ERR("failed to " + "grn_lseek(%" GRN_FMT_OFF64_T ") -> %" GRN_FMT_OFF64_T, + block->head, + seeked_position); + return; + } + } + { + size_t read_bytesize; + read_bytesize = grn_read(ii_buffer->tmpfd, block->buffer, bytesize); + if (read_bytesize != bytesize) { + SERR("failed to grn_read(%" GRN_FMT_SIZE ") -> %" GRN_FMT_SIZE, + bytesize, read_bytesize); + return; + } + } + block->head += bytesize; + block->bufcur = block->buffer; + if (block->head >= block->tail) { + if (block->head > block->tail) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "fetch error: %" GRN_FMT_INT64D " > %" GRN_FMT_INT64D, + block->head, block->tail); + } + block->rest = block->nextsize; + block->nextsize = 0; + } else { + block->rest = block->nextsize - sizeof(uint32_t); + grn_memcpy(&block->nextsize, + &block->buffer[block->rest], sizeof(uint32_t)); + } + } + } + if (block->rest) { + uint8_t *p = block->bufcur; + GRN_B_DEC(block->tid, p); + GRN_B_DEC(block->nrecs, p); + GRN_B_DEC(block->nposts, p); + block->rest -= (p - block->bufcur); + block->bufcur = p; + } else { + block->tid = 0; + } +} + +/* grn_ii_buffer_chunk_flush flushes the current buffer for packed postings. */ +static void +grn_ii_buffer_chunk_flush(grn_ctx *ctx, grn_ii_buffer *ii_buffer) +{ + grn_io_win io_win; + uint32_t chunk_number; + chunk_new(ctx, ii_buffer->ii, &chunk_number, ii_buffer->packed_len); + GRN_LOG(ctx, GRN_LOG_INFO, "chunk:%d, packed_len:%" GRN_FMT_SIZE, + chunk_number, ii_buffer->packed_len); + fake_map(ctx, ii_buffer->ii->chunk, &io_win, ii_buffer->packed_buf, + chunk_number, ii_buffer->packed_len); + grn_io_win_unmap(&io_win); + ii_buffer->term_buffer->header.chunk = chunk_number; + ii_buffer->term_buffer->header.chunk_size = ii_buffer->packed_len; + ii_buffer->term_buffer->header.buffer_free = + S_SEGMENT - sizeof(buffer_header) - + ii_buffer->term_buffer->header.nterms * sizeof(buffer_term); + ii_buffer->term_buffer->header.nterms_void = 0; + buffer_segment_update(ii_buffer->ii, ii_buffer->lseg, ii_buffer->dseg); + ii_buffer->ii->header->total_chunk_size += ii_buffer->packed_len; + ii_buffer->total_chunk_size += ii_buffer->packed_len; + GRN_LOG(ctx, GRN_LOG_DEBUG, + "nterms=%d chunk=%d total=%" GRN_FMT_INT64U "KB", + ii_buffer->term_buffer->header.nterms, + ii_buffer->term_buffer->header.chunk_size, + ii_buffer->ii->header->total_chunk_size >> 10); + ii_buffer->term_buffer = NULL; + ii_buffer->packed_buf = NULL; + ii_buffer->packed_len = 0; + ii_buffer->packed_buf_size = 0; + ii_buffer->curr_size = 0; +} + +/* + * merge_hit_blocks merges hit blocks into ii_buffer->data_vectors. + * merge_hit_blocks returns the estimated maximum size in bytes. + */ +static size_t +merge_hit_blocks(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + ii_buffer_block *hits[], int nhits) +{ + uint64_t nrecs = 0; + uint64_t nposts = 0; + size_t max_size; + uint64_t flags = ii_buffer->ii->header->flags; + int i; + for (i = 0; i < nhits; i++) { + ii_buffer_block *block = hits[i]; + nrecs += block->nrecs; + nposts += block->nposts; + } + ii_buffer->curr_size += nrecs + nposts; + max_size = nrecs * (ii_buffer->ii->n_elements); + if (flags & GRN_OBJ_WITH_POSITION) { max_size += nposts - nrecs; } + datavec_reset(ctx, ii_buffer->data_vectors, + ii_buffer->ii->n_elements, nrecs, max_size); + { + int i; + uint32_t lr = 0; /* Last rid */ + uint64_t spos = 0; + uint32_t *ridp, *sidp = NULL, *tfp, *weightp = NULL, *posp = NULL; + { + /* Get write positions in datavec. */ + int j = 0; + ridp = ii_buffer->data_vectors[j++].data; + if (flags & GRN_OBJ_WITH_SECTION) { + sidp = ii_buffer->data_vectors[j++].data; + } + tfp = ii_buffer->data_vectors[j++].data; + if (flags & GRN_OBJ_WITH_WEIGHT) { + weightp = ii_buffer->data_vectors[j++].data; + } + if (flags & GRN_OBJ_WITH_POSITION) { + posp = ii_buffer->data_vectors[j++].data; + } + } + for (i = 0; i < nhits; i++) { + /* Read postings from hit blocks and join the postings into datavec. */ + ii_buffer_block *block = hits[i]; + uint8_t *p = block->bufcur; + uint32_t n = block->nrecs; + if (n) { + GRN_B_DEC(*ridp, p); + *ridp -= lr; + lr += *ridp++; + while (--n) { + GRN_B_DEC(*ridp, p); + lr += *ridp++; + } + } + if ((flags & GRN_OBJ_WITH_SECTION)) { + for (n = block->nrecs; n; n--) { + GRN_B_DEC(*sidp++, p); + } + } + for (n = block->nrecs; n; n--) { + GRN_B_DEC(*tfp++, p); + } + if ((flags & GRN_OBJ_WITH_WEIGHT)) { + for (n = block->nrecs; n; n--) { + GRN_B_DEC(*weightp++, p); + } + } + if ((flags & GRN_OBJ_WITH_POSITION)) { + for (n = block->nposts; n; n--) { + GRN_B_DEC(*posp, p); + spos += *posp++; + } + } + block->rest -= (p - block->bufcur); + block->bufcur = p; + grn_ii_buffer_fetch(ctx, ii_buffer, block); + } + { + /* Set size and flags of datavec. */ + int j = 0; + uint32_t f_s = (nrecs < 3) ? 0 : USE_P_ENC; + uint32_t f_d = ((nrecs < 16) || (nrecs <= (lr >> 8))) ? 0 : USE_P_ENC; + ii_buffer->data_vectors[j].data_size = nrecs; + ii_buffer->data_vectors[j++].flags = f_d; + if ((flags & GRN_OBJ_WITH_SECTION)) { + ii_buffer->data_vectors[j].data_size = nrecs; + ii_buffer->data_vectors[j++].flags = f_s; + } + ii_buffer->data_vectors[j].data_size = nrecs; + ii_buffer->data_vectors[j++].flags = f_s; + if ((flags & GRN_OBJ_WITH_WEIGHT)) { + ii_buffer->data_vectors[j].data_size = nrecs; + ii_buffer->data_vectors[j++].flags = f_s; + } + if ((flags & GRN_OBJ_WITH_POSITION)) { + uint32_t f_p = (((nposts < 32) || + (nposts <= (spos >> 13))) ? 0 : USE_P_ENC); + ii_buffer->data_vectors[j].data_size = nposts; + ii_buffer->data_vectors[j++].flags = f_p|ODD; + } + } + } + return (max_size + ii_buffer->ii->n_elements) * 4; +} + +static buffer * +get_term_buffer(grn_ctx *ctx, grn_ii_buffer *ii_buffer) +{ + if (!ii_buffer->term_buffer) { + uint32_t lseg; + void *term_buffer; + for (lseg = 0; lseg < GRN_II_MAX_LSEG; lseg++) { + if (ii_buffer->ii->header->binfo[lseg] == GRN_II_PSEG_NOT_ASSIGNED) { break; } + } + if (lseg == GRN_II_MAX_LSEG) { + DEFINE_NAME(ii_buffer->ii); + MERR("[ii][buffer][term-buffer] couldn't find a free buffer: " + "<%.*s>", + name_size, name); + return NULL; + } + ii_buffer->lseg = lseg; + ii_buffer->dseg = segment_get(ctx, ii_buffer->ii); + GRN_IO_SEG_REF(ii_buffer->ii->seg, ii_buffer->dseg, term_buffer); + ii_buffer->term_buffer = (buffer *)term_buffer; + } + return ii_buffer->term_buffer; +} + +/* + * try_in_place_packing tries to pack a posting in an array element. + * + * The requirements are as follows: + * - nposts == 1 + * - nhits == 1 && nrecs == 1 && tf == 0 + * - weight == 0 + * - !(flags & GRN_OBJ_WITH_SECTION) || (rid < 0x100000 && sid < 0x800) + */ +static grn_bool +try_in_place_packing(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + grn_id tid, ii_buffer_block *hits[], int nhits) +{ + if (nhits == 1 && hits[0]->nrecs == 1 && hits[0]->nposts == 1) { + grn_id rid; + uint32_t sid = 1, tf, pos = 0, weight = 0; + ii_buffer_block *block = hits[0]; + uint8_t *p = block->bufcur; + uint32_t flags = ii_buffer->ii->header->flags; + GRN_B_DEC(rid, p); + if (flags & GRN_OBJ_WITH_SECTION) { + GRN_B_DEC(sid, p); + sid++; + } + GRN_B_DEC(tf, p); + if (tf != 0) { GRN_LOG(ctx, GRN_LOG_WARNING, "tf=%d", tf); } + if (flags & GRN_OBJ_WITH_WEIGHT) { GRN_B_DEC(weight, p); } + if (flags & GRN_OBJ_WITH_POSITION) { GRN_B_DEC(pos, p); } + if (!weight) { + if (flags & GRN_OBJ_WITH_SECTION) { + if (rid < 0x100000 && sid < 0x800) { + uint32_t *a = array_get(ctx, ii_buffer->ii, tid); + a[0] = (rid << 12) + (sid << 1) + 1; + a[1] = pos; + array_unref(ii_buffer->ii, tid); + } else { + return GRN_FALSE; + } + } else { + uint32_t *a = array_get(ctx, ii_buffer->ii, tid); + a[0] = (rid << 1) + 1; + a[1] = pos; + array_unref(ii_buffer->ii, tid); + } + block->rest -= (p - block->bufcur); + block->bufcur = p; + grn_ii_buffer_fetch(ctx, ii_buffer, block); + return GRN_TRUE; + } + } + return GRN_FALSE; +} + +/* grn_ii_buffer_merge merges hit blocks and pack it. */ +static void +grn_ii_buffer_merge(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + grn_id tid, ii_buffer_block *hits[], int nhits) +{ + if (!try_in_place_packing(ctx, ii_buffer, tid, hits, nhits)) { + /* Merge hit blocks and reserve a buffer for packed data. */ + size_t max_size = merge_hit_blocks(ctx, ii_buffer, hits, nhits); + if (ii_buffer->packed_buf && + ii_buffer->packed_buf_size < ii_buffer->packed_len + max_size) { + grn_ii_buffer_chunk_flush(ctx, ii_buffer); + } + if (!ii_buffer->packed_buf) { + size_t buf_size = (max_size > II_BUFFER_PACKED_BUF_SIZE) + ? max_size : II_BUFFER_PACKED_BUF_SIZE; + if ((ii_buffer->packed_buf = GRN_MALLOC(buf_size))) { + ii_buffer->packed_buf_size = buf_size; + } + } + { + /* Pack postings into the current buffer. */ + uint16_t nterm; + size_t packed_len; + buffer_term *bt; + uint32_t *a; + buffer *term_buffer; + + a = array_get(ctx, ii_buffer->ii, tid); + if (!a) { + DEFINE_NAME(ii_buffer->ii); + MERR("[ii][buffer][merge] failed to allocate an array: " + "<%.*s>: " + "<%u>", + name_size, name, + tid); + return; + } + term_buffer = get_term_buffer(ctx, ii_buffer); + if (!term_buffer) { + DEFINE_NAME(ii_buffer->ii); + MERR("[ii][buffer][merge] failed to allocate a term buffer: " + "<%.*s>: " + "<%u>", + name_size, name, + tid); + return; + } + nterm = term_buffer->header.nterms++; + bt = &term_buffer->terms[nterm]; + a[0] = SEG2POS(ii_buffer->lseg, + (sizeof(buffer_header) + sizeof(buffer_term) * nterm)); + packed_len = grn_p_encv(ctx, ii_buffer->data_vectors, + ii_buffer->ii->n_elements, + ii_buffer->packed_buf + + ii_buffer->packed_len); + a[1] = ii_buffer->data_vectors[0].data_size; + bt->tid = tid; + bt->size_in_buffer = 0; + bt->pos_in_buffer = 0; + bt->size_in_chunk = packed_len; + bt->pos_in_chunk = ii_buffer->packed_len; + ii_buffer->packed_len += packed_len; + if (((ii_buffer->curr_size * ii_buffer->update_buffer_size) + + (ii_buffer->total_size * term_buffer->header.nterms * 16)) >= + (ii_buffer->total_size * II_BUFFER_NTERMS_PER_BUFFER * 16)) { + grn_ii_buffer_chunk_flush(ctx, ii_buffer); + } + array_unref(ii_buffer->ii, tid); + } + } +} + +grn_ii_buffer * +grn_ii_buffer_open(grn_ctx *ctx, grn_ii *ii, + long long unsigned int update_buffer_size) +{ + if (ii && ii->lexicon) { + grn_ii_buffer *ii_buffer = GRN_MALLOCN(grn_ii_buffer, 1); + if (ii_buffer) { + ii_buffer->ii = ii; + ii_buffer->lexicon = ii->lexicon; + ii_buffer->tmp_lexicon = NULL; + ii_buffer->nblocks = 0; + ii_buffer->blocks = NULL; + ii_buffer->ncounters = II_BUFFER_NCOUNTERS_MARGIN; + ii_buffer->block_pos = 0; + ii_buffer->filepos = 0; + ii_buffer->curr_size = 0; + ii_buffer->total_size = 0; + ii_buffer->update_buffer_size = update_buffer_size; + ii_buffer->counters = GRN_CALLOC(ii_buffer->ncounters * + sizeof(ii_buffer_counter)); + ii_buffer->term_buffer = NULL; + ii_buffer->packed_buf = NULL; + ii_buffer->packed_len = 0; + ii_buffer->packed_buf_size = 0; + ii_buffer->total_chunk_size = 0; + ii_buffer->values = NULL; + ii_buffer->nvalues = 0; + ii_buffer->max_nvalues = 0; + ii_buffer->last_rid = 0; + if (ii_buffer->counters) { + ii_buffer->block_buf = GRN_MALLOCN(grn_id, II_BUFFER_BLOCK_SIZE); + if (ii_buffer->block_buf) { + grn_snprintf(ii_buffer->tmpfpath, PATH_MAX, PATH_MAX, + "%-.256sXXXXXX", grn_io_path(ii->seg)); + ii_buffer->block_buf_size = II_BUFFER_BLOCK_SIZE; + ii_buffer->tmpfd = grn_mkstemp(ii_buffer->tmpfpath); + if (ii_buffer->tmpfd != -1) { + grn_table_flags flags; + grn_table_get_info(ctx, ii->lexicon, &flags, NULL, NULL, NULL, + NULL); + if ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_PAT_KEY) { + grn_pat_cache_enable(ctx, (grn_pat *)ii->lexicon, + PAT_CACHE_SIZE); + } + return ii_buffer; + } else { + SERR("failed grn_mkstemp(%-.256s)", + ii_buffer->tmpfpath); + } + GRN_FREE(ii_buffer->block_buf); + } + GRN_FREE(ii_buffer->counters); + } + GRN_FREE(ii_buffer); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "ii or ii->lexicon is NULL"); + } + return NULL; +} + +static void +ii_buffer_value_init(grn_ctx *ctx, ii_buffer_value *value) +{ + value->sid = 0; + value->weight = 0; + value->p = NULL; + value->len = 0; + value->buf = NULL; + value->cap = 0; +} + +static void +ii_buffer_value_fin(grn_ctx *ctx, ii_buffer_value *value) +{ + if (value->buf) { + GRN_FREE(value->buf); + } +} + +/* + * ii_buffer_values_append appends a value to ii_buffer. + * This function deep-copies the value if need_copy == GRN_TRUE. + */ +static void +ii_buffer_values_append(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + unsigned int sid, unsigned weight, + const char *p, uint32_t len, grn_bool need_copy) +{ + if (ii_buffer->nvalues == ii_buffer->max_nvalues) { + unsigned int i; + unsigned int new_max_nvalues = ii_buffer->max_nvalues * 2; + unsigned int new_size; + ii_buffer_value *new_values; + if (new_max_nvalues == 0) { + new_max_nvalues = 1; + } + new_size = new_max_nvalues * sizeof(ii_buffer_value); + new_values = (ii_buffer_value *)GRN_REALLOC(ii_buffer->values, new_size); + if (!new_values) { + return; + } + for (i = ii_buffer->max_nvalues; i < new_max_nvalues; i++) { + ii_buffer_value_init(ctx, &new_values[i]); + } + ii_buffer->values = new_values; + ii_buffer->max_nvalues = new_max_nvalues; + } + + { + ii_buffer_value *value = &ii_buffer->values[ii_buffer->nvalues]; + if (need_copy) { + if (len > value->cap) { + char *new_buf = (char *)GRN_REALLOC(value->buf, len); + if (!new_buf) { + return; + } + value->buf = new_buf; + value->cap = len; + } + grn_memcpy(value->buf, p, len); + p = value->buf; + } + value->sid = sid; + value->weight = weight; + value->p = p; + value->len = len; + ii_buffer->nvalues++; + } +} + +grn_rc +grn_ii_buffer_append(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + grn_id rid, unsigned int sid, grn_obj *value) +{ + if (rid != ii_buffer->last_rid) { + if (ii_buffer->last_rid) { + grn_ii_buffer_tokenize(ctx, ii_buffer, ii_buffer->last_rid); + } + ii_buffer->last_rid = rid; + } + ii_buffer_values_append(ctx, ii_buffer, sid, 0, + GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value), + GRN_TRUE); + return ctx->rc; +} + +/* + * grn_ii_buffer_commit completes tokenization and builds an inverted index + * from data in a temporary file. + */ +grn_rc +grn_ii_buffer_commit(grn_ctx *ctx, grn_ii_buffer *ii_buffer) +{ + /* Tokenize the remaining values and free resources. */ + if (ii_buffer->last_rid && ii_buffer->nvalues) { + grn_ii_buffer_tokenize(ctx, ii_buffer, ii_buffer->last_rid); + } + if (ii_buffer->block_pos) { + grn_ii_buffer_flush(ctx, ii_buffer); + } + if (ii_buffer->tmpfd != -1) { + grn_close(ii_buffer->tmpfd); + } + if (ii_buffer->block_buf) { + GRN_FREE(ii_buffer->block_buf); + ii_buffer->block_buf = NULL; + } + if (ii_buffer->counters) { + GRN_FREE(ii_buffer->counters); + ii_buffer->counters = NULL; + } + + if (ii_buffer->update_buffer_size && + ii_buffer->update_buffer_size < 20) { + if (ii_buffer->update_buffer_size < 10) { + ii_buffer->update_buffer_size = + ii_buffer->total_size >> (10 - ii_buffer->update_buffer_size); + } else { + ii_buffer->update_buffer_size = + ii_buffer->total_size << (ii_buffer->update_buffer_size - 10); + } + } + + GRN_LOG(ctx, GRN_LOG_DEBUG, + "nblocks=%d, update_buffer_size=%" GRN_FMT_INT64U, + ii_buffer->nblocks, ii_buffer->update_buffer_size); + + datavec_init(ctx, ii_buffer->data_vectors, ii_buffer->ii->n_elements, 0, 0); + grn_open(ii_buffer->tmpfd, + ii_buffer->tmpfpath, + O_RDONLY | GRN_OPEN_FLAG_BINARY); + if (ii_buffer->tmpfd == -1) { + ERRNO_ERR("failed to open path: <%-.256s>", ii_buffer->tmpfpath); + return ctx->rc; + } + { + /* Fetch the first term of each block. */ + uint32_t i; + for (i = 0; i < ii_buffer->nblocks; i++) { + grn_ii_buffer_fetch(ctx, ii_buffer, &ii_buffer->blocks[i]); + } + } + { + ii_buffer_block **hits; + if ((hits = GRN_MALLOCN(ii_buffer_block *, ii_buffer->nblocks))) { + grn_id tid; + grn_table_cursor *tc; + tc = grn_table_cursor_open(ctx, ii_buffer->lexicon, + NULL, 0, NULL, 0, 0, -1, II_BUFFER_ORDER); + if (tc) { + while ((tid = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) { + /* + * Find blocks which contain the current term. + * Then, merge the postings. + */ + int nrests = 0; + int nhits = 0; + uint32_t i; + for (i = 0; i < ii_buffer->nblocks; i++) { + if (ii_buffer->blocks[i].tid == tid) { + hits[nhits++] = &ii_buffer->blocks[i]; + } + if (ii_buffer->blocks[i].tid) { nrests++; } + } + if (nhits) { grn_ii_buffer_merge(ctx, ii_buffer, tid, hits, nhits); } + if (!nrests) { break; } + } + if (ii_buffer->packed_len) { + grn_ii_buffer_chunk_flush(ctx, ii_buffer); + } + grn_table_cursor_close(ctx, tc); + } + GRN_FREE(hits); + } + } + datavec_fin(ctx, ii_buffer->data_vectors); + GRN_LOG(ctx, GRN_LOG_DEBUG, + "tmpfile_size:%" GRN_FMT_INT64D " > total_chunk_size:%" GRN_FMT_SIZE, + ii_buffer->filepos, ii_buffer->total_chunk_size); + grn_close(ii_buffer->tmpfd); + if (grn_unlink(ii_buffer->tmpfpath) == 0) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[ii][buffer][commit] removed temporary path: <%-.256s>", + ii_buffer->tmpfpath); + } else { + ERRNO_ERR("[ii][buffer][commit] failed to remove temporary path: <%-.256s>", + ii_buffer->tmpfpath); + } + ii_buffer->tmpfd = -1; + return ctx->rc; +} + +grn_rc +grn_ii_buffer_close(grn_ctx *ctx, grn_ii_buffer *ii_buffer) +{ + uint32_t i; + grn_table_flags flags; + grn_table_get_info(ctx, ii_buffer->ii->lexicon, &flags, NULL, NULL, NULL, + NULL); + if ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_PAT_KEY) { + grn_pat_cache_disable(ctx, (grn_pat *)ii_buffer->ii->lexicon); + } + if (ii_buffer->tmp_lexicon) { + grn_obj_close(ctx, ii_buffer->tmp_lexicon); + } + if (ii_buffer->tmpfd != -1) { + grn_close(ii_buffer->tmpfd); + if (grn_unlink(ii_buffer->tmpfpath) == 0) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[ii][buffer][close] removed temporary path: <%-.256s>", + ii_buffer->tmpfpath); + } else { + ERRNO_ERR("[ii][buffer][close] failed to remove temporary path: <%-.256s>", + ii_buffer->tmpfpath); + } + } + if (ii_buffer->block_buf) { + GRN_FREE(ii_buffer->block_buf); + } + if (ii_buffer->counters) { + GRN_FREE(ii_buffer->counters); + } + if (ii_buffer->blocks) { + for (i = 0; i < ii_buffer->nblocks; i++) { + if (ii_buffer->blocks[i].buffer) { + GRN_FREE(ii_buffer->blocks[i].buffer); + } + } + GRN_FREE(ii_buffer->blocks); + } + if (ii_buffer->values) { + for (i = 0; i < ii_buffer->max_nvalues; i++) { + ii_buffer_value_fin(ctx, &ii_buffer->values[i]); + } + GRN_FREE(ii_buffer->values); + } + GRN_FREE(ii_buffer); + return ctx->rc; +} + +/* + * grn_ii_buffer_parse tokenizes values to be indexed. + * + * For each record of the target table, grn_ii_buffer_parse makes a list of + * target values and calls grn_ii_buffer_tokenize. To make a list of target + * values, ii_buffer_values_append is called for each value. Note that + * ii_buffer_values_append is called for each element for a vector. + */ +static void +grn_ii_buffer_parse(grn_ctx *ctx, grn_ii_buffer *ii_buffer, + grn_obj *target, int ncols, grn_obj **cols) +{ + grn_table_cursor *tc; + grn_obj *vobjs; + if ((vobjs = GRN_MALLOCN(grn_obj, ncols))) { + int i; + for (i = 0; i < ncols; i++) { + GRN_TEXT_INIT(&vobjs[i], 0); + } + if ((tc = grn_table_cursor_open(ctx, target, + NULL, 0, NULL, 0, 0, -1, + GRN_CURSOR_BY_ID))) { + grn_id rid; + while ((rid = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) { + unsigned int j; + int sid; + grn_obj **col; + for (sid = 1, col = cols; sid <= ncols; sid++, col++) { + grn_obj *rv = &vobjs[sid - 1]; + grn_obj_reinit_for(ctx, rv, *col); + if (GRN_OBJ_TABLEP(*col)) { + grn_table_get_key2(ctx, *col, rid, rv); + } else { + grn_obj_get_value(ctx, *col, rid, rv); + } + switch (rv->header.type) { + case GRN_BULK : + ii_buffer_values_append(ctx, ii_buffer, sid, 0, + GRN_TEXT_VALUE(rv), GRN_TEXT_LEN(rv), + GRN_FALSE); + break; + case GRN_UVECTOR : + { + unsigned int size; + unsigned int elem_size; + size = grn_uvector_size(ctx, rv); + elem_size = grn_uvector_element_size(ctx, rv); + for (j = 0; j < size; j++) { + ii_buffer_values_append(ctx, ii_buffer, sid, 0, + GRN_BULK_HEAD(rv) + (elem_size * j), + elem_size, GRN_FALSE); + } + } + break; + case GRN_VECTOR : + if (rv->u.v.body) { + int j; + int n_sections = rv->u.v.n_sections; + grn_section *sections = rv->u.v.sections; + const char *head = GRN_BULK_HEAD(rv->u.v.body); + for (j = 0; j < n_sections; j++) { + grn_section *section = sections + j; + if (section->length == 0) { + continue; + } + ii_buffer_values_append(ctx, ii_buffer, sid, section->weight, + head + section->offset, + section->length, GRN_FALSE); + } + } + break; + default : + ERR(GRN_INVALID_ARGUMENT, + "[index] invalid object assigned as value"); + break; + } + } + grn_ii_buffer_tokenize(ctx, ii_buffer, rid); + } + grn_table_cursor_close(ctx, tc); + } + for (i = 0; i < ncols; i++) { + GRN_OBJ_FIN(ctx, &vobjs[i]); + } + GRN_FREE(vobjs); + } +} + +grn_rc +grn_ii_build(grn_ctx *ctx, grn_ii *ii, uint64_t sparsity) +{ + grn_ii_buffer *ii_buffer; + + { + /* Do nothing if there are no targets. */ + grn_obj *data_table = grn_ctx_at(ctx, DB_OBJ(ii)->range); + if (!data_table) { + return ctx->rc; + } + if (grn_table_size(ctx, data_table) == 0) { + return ctx->rc; + } + } + + ii_buffer = grn_ii_buffer_open(ctx, ii, sparsity); + if (ii_buffer) { + grn_id *source = (grn_id *)ii->obj.source; + if (ii->obj.source_size && ii->obj.source) { + int ncols = ii->obj.source_size / sizeof(grn_id); + grn_obj **cols = GRN_MALLOCN(grn_obj *, ncols); + if (cols) { + int i; + for (i = 0; i < ncols; i++) { + if (!(cols[i] = grn_ctx_at(ctx, source[i]))) { break; } + } + if (i == ncols) { /* All the source columns are available. */ + grn_obj *target = cols[0]; + if (!GRN_OBJ_TABLEP(target)) { + target = grn_ctx_at(ctx, target->header.domain); + } + if (target) { + grn_ii_buffer_parse(ctx, ii_buffer, target, ncols, cols); + grn_ii_buffer_commit(ctx, ii_buffer); + } else { + ERR(GRN_INVALID_ARGUMENT, "failed to resolve the target"); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "failed to resolve a column (%d)", i); + } + GRN_FREE(cols); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "ii->obj.source is void"); + } + grn_ii_buffer_close(ctx, ii_buffer); + } + return ctx->rc; +} + +/* + * ========================================================================== + * The following part provides constants, structures and functions for static + * indexing. + * ========================================================================== + */ + +#define GRN_II_BUILDER_BUFFER_CHUNK_SIZE (S_CHUNK >> 2) + +#define GRN_II_BUILDER_MAX_LEXICON_CACHE_SIZE (1 << 24) + +#define GRN_II_BUILDER_MIN_BLOCK_THRESHOLD 1 +#define GRN_II_BUILDER_MAX_BLOCK_THRESHOLD (1 << 28) + +#define GRN_II_BUILDER_MIN_FILE_BUF_SIZE (1 << 12) +#define GRN_II_BUILDER_MAX_FILE_BUF_SIZE (1 << 30) + +#define GRN_II_BUILDER_MIN_BLOCK_BUF_SIZE (1 << 12) +#define GRN_II_BUILDER_MAX_BLOCK_BUF_SIZE (1 << 30) + +#define GRN_II_BUILDER_MIN_CHUNK_THRESHOLD 1 +#define GRN_II_BUILDER_MAX_CHUNK_THRESHOLD (1 << 28) + +#define GRN_II_BUILDER_MIN_BUFFER_MAX_N_TERMS 1 +#define GRN_II_BUILDER_MAX_BUFFER_MAX_N_TERMS \ + ((S_SEGMENT - sizeof(buffer_header)) / sizeof(buffer_term)) + +struct grn_ii_builder_options { + uint32_t lexicon_cache_size; /* Cache size of temporary lexicon */ + /* A block is flushed if builder->n reaches this value. */ + uint32_t block_threshold; + uint32_t file_buf_size; /* Buffer size for buffered output */ + uint32_t block_buf_size; /* Buffer size for buffered input */ + /* A chunk is flushed if chunk->n reaches this value. */ + uint32_t chunk_threshold; + uint32_t buffer_max_n_terms; /* Maximum number of terms in each buffer */ +}; + +static const grn_ii_builder_options grn_ii_builder_default_options = { + 0x80000, /* lexicon_cache_size */ + 0x4000000, /* block_threshold */ + 0x10000, /* file_buf_size */ + 0x10000, /* block_buf_size */ + 0x1000, /* chunk_threshold */ + 0x3000, /* buffer_max_n_terms */ +}; + +/* grn_ii_builder_options_init fills options with the default options. */ +void +grn_ii_builder_options_init(grn_ii_builder_options *options) +{ + *options = grn_ii_builder_default_options; +} + +/* grn_ii_builder_options_fix fixes out-of-range options. */ +static void +grn_ii_builder_options_fix(grn_ii_builder_options *options) +{ + if (options->lexicon_cache_size > GRN_II_BUILDER_MAX_LEXICON_CACHE_SIZE) { + options->lexicon_cache_size = GRN_II_BUILDER_MAX_LEXICON_CACHE_SIZE; + } + + if (options->block_threshold < GRN_II_BUILDER_MIN_BLOCK_THRESHOLD) { + options->block_threshold = GRN_II_BUILDER_MIN_BLOCK_THRESHOLD; + } + if (options->block_threshold > GRN_II_BUILDER_MAX_BLOCK_THRESHOLD) { + options->block_threshold = GRN_II_BUILDER_MAX_BLOCK_THRESHOLD; + } + + if (options->file_buf_size < GRN_II_BUILDER_MIN_FILE_BUF_SIZE) { + options->file_buf_size = GRN_II_BUILDER_MIN_FILE_BUF_SIZE; + } + if (options->file_buf_size > GRN_II_BUILDER_MAX_FILE_BUF_SIZE) { + options->file_buf_size = GRN_II_BUILDER_MAX_FILE_BUF_SIZE; + } + + if (options->block_buf_size < GRN_II_BUILDER_MIN_BLOCK_BUF_SIZE) { + options->block_buf_size = GRN_II_BUILDER_MIN_BLOCK_BUF_SIZE; + } + if (options->block_buf_size > GRN_II_BUILDER_MAX_BLOCK_BUF_SIZE) { + options->block_buf_size = GRN_II_BUILDER_MAX_BLOCK_BUF_SIZE; + } + + if (options->chunk_threshold < GRN_II_BUILDER_MIN_CHUNK_THRESHOLD) { + options->chunk_threshold = GRN_II_BUILDER_MIN_CHUNK_THRESHOLD; + } + if (options->chunk_threshold > GRN_II_BUILDER_MAX_CHUNK_THRESHOLD) { + options->chunk_threshold = GRN_II_BUILDER_MAX_CHUNK_THRESHOLD; + } + + if (options->buffer_max_n_terms < GRN_II_BUILDER_MIN_BUFFER_MAX_N_TERMS) { + options->buffer_max_n_terms = GRN_II_BUILDER_MIN_BUFFER_MAX_N_TERMS; + } + if (options->buffer_max_n_terms > GRN_II_BUILDER_MAX_BUFFER_MAX_N_TERMS) { + options->buffer_max_n_terms = GRN_II_BUILDER_MAX_BUFFER_MAX_N_TERMS; + } +} + +#define GRN_II_BUILDER_TERM_INPLACE_SIZE\ + (sizeof(grn_ii_builder_term) - (uintptr_t)&((grn_ii_builder_term *)0)->dummy) + +typedef struct { + grn_id rid; /* Last record ID */ + uint32_t sid; /* Last section ID */ + /* Last position (GRN_OBJ_WITH_POSITION) or frequency. */ + uint32_t pos_or_freq; + uint32_t offset; /* Buffer write offset */ + uint32_t size; /* Buffer size */ + uint32_t dummy; /* Padding */ + uint8_t *buf; /* Buffer (to be freed) */ +} grn_ii_builder_term; + +/* grn_ii_builder_term_is_inplace returns whether a term buffer is inplace. */ +inline static grn_bool +grn_ii_builder_term_is_inplace(grn_ii_builder_term *term) +{ + return term->size == GRN_II_BUILDER_TERM_INPLACE_SIZE; +} + +/* grn_ii_builder_term_get_buf returns a term buffer. */ +inline static uint8_t * +grn_ii_builder_term_get_buf(grn_ii_builder_term *term) +{ + if (grn_ii_builder_term_is_inplace(term)) { + return (uint8_t *)&term->dummy; + } else { + return term->buf; + } +} + +/* + * grn_ii_builder_term_init initializes a term. Note that an initialized term + * must be finalized by grn_ii_builder_term_fin. + */ +static void +grn_ii_builder_term_init(grn_ctx *ctx, grn_ii_builder_term *term) +{ + term->rid = GRN_ID_NIL; + term->sid = 0; + term->pos_or_freq = 0; + term->offset = 0; + term->size = GRN_II_BUILDER_TERM_INPLACE_SIZE; +} + +/* grn_ii_builder_term_fin finalizes a term. */ +static void +grn_ii_builder_term_fin(grn_ctx *ctx, grn_ii_builder_term *term) +{ + if (!grn_ii_builder_term_is_inplace(term)) { + GRN_FREE(term->buf); + } +} + +/* grn_ii_builder_term_reinit reinitializes a term. */ +static void +grn_ii_builder_term_reinit(grn_ctx *ctx, grn_ii_builder_term *term) +{ + grn_ii_builder_term_fin(ctx, term); + grn_ii_builder_term_init(ctx, term); +} + +/* grn_ii_builder_term_extend extends a term buffer. */ +static grn_rc +grn_ii_builder_term_extend(grn_ctx *ctx, grn_ii_builder_term *term) +{ + uint8_t *buf; + uint32_t size = term->size * 2; + if (grn_ii_builder_term_is_inplace(term)) { + buf = (uint8_t *)GRN_MALLOC(size); + if (!buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for term buffer: size = %u", size); + return ctx->rc; + } + grn_memcpy(buf, &term->dummy, term->offset); + } else { + buf = (uint8_t *)GRN_REALLOC(term->buf, size); + if (!buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to reallocate memory for term buffer: size = %u", size); + return ctx->rc; + } + } + term->buf = buf; + term->size = size; + return GRN_SUCCESS; +} + +/* grn_ii_builder_term_append appends an integer to a term buffer. */ +inline static grn_rc +grn_ii_builder_term_append(grn_ctx *ctx, grn_ii_builder_term *term, + uint64_t value) +{ + uint8_t *p; + if (value < (uint64_t)1 << 5) { + if (term->offset + 1 > term->size) { + grn_rc rc = grn_ii_builder_term_extend(ctx, term); + if (rc != GRN_SUCCESS) { + return rc; + } + } + p = grn_ii_builder_term_get_buf(term) + term->offset; + p[0] = (uint8_t)value; + term->offset++; + return GRN_SUCCESS; + } else if (value < (uint64_t)1 << 13) { + if (term->offset + 2 > term->size) { + grn_rc rc = grn_ii_builder_term_extend(ctx, term); + if (rc != GRN_SUCCESS) { + return rc; + } + } + p = grn_ii_builder_term_get_buf(term) + term->offset; + p[0] = (uint8_t)((value & 0x1f) | (1 << 5)); + p[1] = (uint8_t)(value >> 5); + term->offset += 2; + return GRN_SUCCESS; + } else { + uint8_t i, n; + if (value < (uint64_t)1 << 21) { + n = 3; + } else if (value < (uint64_t)1 << 29) { + n = 4; + } else if (value < (uint64_t)1 << 37) { + n = 5; + } else if (value < (uint64_t)1 << 45) { + n = 6; + } else if (value < (uint64_t)1 << 53) { + n = 7; + } else { + n = 8; + } + if (term->offset + n > term->size) { + grn_rc rc = grn_ii_builder_term_extend(ctx, term); + if (rc != GRN_SUCCESS) { + return rc; + } + } + p = grn_ii_builder_term_get_buf(term) + term->offset; + p[0] = (uint8_t)(value & 0x1f) | ((n - 1) << 5); + value >>= 5; + for (i = 1; i < n; i++) { + p[i] = (uint8_t)value; + value >>= 8; + } + term->offset += n; + return GRN_SUCCESS; + } +} + +typedef struct { + uint64_t offset; /* File offset */ + uint32_t rest; /* Remaining size */ + uint8_t *buf; /* Buffer (to be freed) */ + uint8_t *cur; /* Current pointer */ + uint8_t *end; /* End pointer */ + uint32_t tid; /* Term ID */ +} grn_ii_builder_block; + +/* + * grn_ii_builder_block_init initializes a block. Note that an initialized + * block must be finalized by grn_ii_builder_block_fin. + */ +static void +grn_ii_builder_block_init(grn_ctx *ctx, grn_ii_builder_block *block) +{ + block->offset = 0; + block->rest = 0; + block->buf = NULL; + block->cur = NULL; + block->end = NULL; + block->tid = GRN_ID_NIL; +} + +/* grn_ii_builder_block_fin finalizes a block. */ +static void +grn_ii_builder_block_fin(grn_ctx *ctx, grn_ii_builder_block *block) +{ + if (block->buf) { + GRN_FREE(block->buf); + } +} + +/* + * grn_ii_builder_block_next reads the next integer. Note that this function + * returns GRN_END_OF_DATA if it reaches the end of a block. + */ +inline static grn_rc +grn_ii_builder_block_next(grn_ctx *ctx, grn_ii_builder_block *block, + uint64_t *value) +{ + uint8_t n; + if (block->cur == block->end) { + return GRN_END_OF_DATA; + } + n = (*block->cur >> 5) + 1; + if (n > block->end - block->cur) { + return GRN_END_OF_DATA; + } + *value = 0; + switch (n) { + case 8 : + *value |= (uint64_t)block->cur[7] << 53; + case 7 : + *value |= (uint64_t)block->cur[6] << 45; + case 6 : + *value |= (uint64_t)block->cur[5] << 37; + case 5 : + *value |= (uint64_t)block->cur[4] << 29; + case 4 : + *value |= (uint64_t)block->cur[3] << 21; + case 3 : + *value |= (uint64_t)block->cur[2] << 13; + case 2 : + *value |= (uint64_t)block->cur[1] << 5; + case 1 : + *value |= block->cur[0] & 0x1f; + break; + } + block->cur += n; + return GRN_SUCCESS; +} + +typedef struct { + grn_ii *ii; /* Inverted index */ + uint32_t buf_id; /* Buffer ID */ + uint32_t buf_seg_id; /* Buffer segment ID */ + buffer *buf; /* Buffer (to be unreferenced) */ + uint32_t chunk_id; /* Chunk ID */ + uint32_t chunk_seg_id; /* Chunk segment ID */ + uint8_t *chunk; /* Chunk (to be unreferenced) */ + uint32_t chunk_offset; /* Chunk write position */ + uint32_t chunk_size; /* Chunk size */ +} grn_ii_builder_buffer; + +/* + * grn_ii_builder_buffer_init initializes a buffer. Note that a buffer must be + * finalized by grn_ii_builder_buffer_fin. + */ +static void +grn_ii_builder_buffer_init(grn_ctx *ctx, grn_ii_builder_buffer *buf, + grn_ii *ii) +{ + buf->ii = ii; + buf->buf_id = 0; + buf->buf_seg_id = 0; + buf->buf = NULL; + buf->chunk_id = 0; + buf->chunk_seg_id = 0; + buf->chunk = NULL; + buf->chunk_offset = 0; + buf->chunk_size = 0; +} + +/* grn_ii_builder_buffer_fin finalizes a buffer. */ +static void +grn_ii_builder_buffer_fin(grn_ctx *ctx, grn_ii_builder_buffer *buf) +{ + if (buf->buf) { + GRN_IO_SEG_UNREF(buf->ii->seg, buf->buf_seg_id); + } + if (buf->chunk) { + GRN_IO_SEG_UNREF(buf->ii->chunk, buf->chunk_seg_id); + } +} + +/* grn_ii_builder_buffer_is_assigned returns whether a buffer is assigned. */ +static grn_bool +grn_ii_builder_buffer_is_assigned(grn_ctx *ctx, grn_ii_builder_buffer *buf) +{ + return buf->buf != NULL; +} + +/* grn_ii_builder_buffer_assign assigns a buffer. */ +static grn_rc +grn_ii_builder_buffer_assign(grn_ctx *ctx, grn_ii_builder_buffer *buf, + size_t min_chunk_size) +{ + void *seg; + size_t chunk_size; + grn_rc rc; + + /* Create a buffer. */ + buf->buf_id = GRN_II_PSEG_NOT_ASSIGNED; + rc = buffer_segment_new(ctx, buf->ii, &buf->buf_id); + if (rc != GRN_SUCCESS) { + if (ctx->rc != GRN_SUCCESS) { + ERR(rc, "failed to allocate segment for buffer"); + } + return rc; + } + buf->buf_seg_id = buf->ii->header->binfo[buf->buf_id]; + GRN_IO_SEG_REF(buf->ii->seg, buf->buf_seg_id, seg); + if (!seg) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, + "failed access buffer segment: buf_id = %u, seg_id = %u", + buf->buf_id, buf->buf_seg_id); + } + return ctx->rc; + } + buf->buf = (buffer *)seg; + + /* Create a chunk. */ + chunk_size = GRN_II_BUILDER_BUFFER_CHUNK_SIZE; + while (chunk_size < min_chunk_size) { + chunk_size *= 2; + } + rc = chunk_new(ctx, buf->ii, &buf->chunk_id, chunk_size); + if (rc != GRN_SUCCESS) { + return rc; + } + buf->chunk_seg_id = buf->chunk_id >> GRN_II_N_CHUNK_VARIATION; + GRN_IO_SEG_REF(buf->ii->chunk, buf->chunk_seg_id, seg); + if (!seg) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, + "failed access chunk segment: chunk_id = %u, seg_id = %u", + buf->chunk_id, buf->chunk_seg_id); + } + return ctx->rc; + } + buf->chunk = (uint8_t *)seg; + buf->chunk += (buf->chunk_id & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << + GRN_II_W_LEAST_CHUNK; + buf->chunk_offset = 0; + buf->chunk_size = chunk_size; + + buf->buf->header.chunk = buf->chunk_id; + buf->buf->header.chunk_size = chunk_size; + buf->buf->header.buffer_free = S_SEGMENT - sizeof(buffer_header); + buf->buf->header.nterms = 0; + buf->buf->header.nterms_void = 0; + buf->ii->header->total_chunk_size += chunk_size; + return GRN_SUCCESS; +} + +/* grn_ii_builder_buffer_flush flushes a buffer. */ +static grn_rc +grn_ii_builder_buffer_flush(grn_ctx *ctx, grn_ii_builder_buffer *buf) +{ + grn_ii *ii; + + buf->buf->header.buffer_free = S_SEGMENT - sizeof(buffer_header) - + buf->buf->header.nterms * sizeof(buffer_term); + GRN_LOG(ctx, GRN_LOG_DEBUG, + "n_terms = %u, chunk_offset = %u, chunk_size = %u, total = %" + GRN_FMT_INT64U "KB", + buf->buf->header.nterms, + buf->chunk_offset, + buf->buf->header.chunk_size, + buf->ii->header->total_chunk_size >> 10); + + ii = buf->ii; + grn_ii_builder_buffer_fin(ctx, buf); + grn_ii_builder_buffer_init(ctx, buf, ii); + return GRN_SUCCESS; +} + +typedef struct { + grn_id tid; /* Term ID */ + uint32_t n; /* Number of integers in buffers */ + grn_id rid; /* Record ID */ + uint32_t rid_gap; /* Record ID gap */ + uint64_t pos_sum; /* Sum of position gaps */ + + uint32_t offset; /* Write offset */ + uint32_t size; /* Buffer size */ + grn_id *rid_buf; /* Buffer for record IDs (to be freed) */ + uint32_t *sid_buf; /* Buffer for section IDs (to be freed) */ + uint32_t *freq_buf; /* Buffer for frequencies (to be freed) */ + uint32_t *weight_buf; /* Buffer for weights (to be freed) */ + + uint32_t pos_offset; /* Write offset of pos_buf */ + uint32_t pos_size; /* Buffer size of pos_buf */ + uint32_t *pos_buf; /* Buffer for positions (to be freed) */ + + size_t enc_offset; /* Write offset of enc_buf */ + size_t enc_size; /* Buffer size of enc_buf */ + uint8_t *enc_buf; /* Buffer for encoded data (to be freed) */ +} grn_ii_builder_chunk; + +/* + * grn_ii_builder_chunk_init initializes a chunk. Note that an initialized + * chunk must be finalized by grn_ii_builder_chunk_fin. + */ +static void +grn_ii_builder_chunk_init(grn_ctx *ctx, grn_ii_builder_chunk *chunk) +{ + chunk->tid = GRN_ID_NIL; + chunk->n = 0; + chunk->rid = GRN_ID_NIL; + chunk->rid_gap = 0; + chunk->pos_sum = 0; + + chunk->offset = 0; + chunk->size = 0; + chunk->rid_buf = NULL; + chunk->sid_buf = NULL; + chunk->freq_buf = NULL; + chunk->weight_buf = NULL; + + chunk->pos_offset = 0; + chunk->pos_size = 0; + chunk->pos_buf = NULL; + + chunk->enc_offset = 0; + chunk->enc_size = 0; + chunk->enc_buf = NULL; +} + +/* grn_ii_builder_chunk_fin finalizes a chunk. */ +static void +grn_ii_builder_chunk_fin(grn_ctx *ctx, grn_ii_builder_chunk *chunk) +{ + if (chunk->enc_buf) { + GRN_FREE(chunk->enc_buf); + } + if (chunk->pos_buf) { + GRN_FREE(chunk->pos_buf); + } + if (chunk->weight_buf) { + GRN_FREE(chunk->weight_buf); + } + if (chunk->freq_buf) { + GRN_FREE(chunk->freq_buf); + } + if (chunk->sid_buf) { + GRN_FREE(chunk->sid_buf); + } + if (chunk->rid_buf) { + GRN_FREE(chunk->rid_buf); + } +} + +/* + * grn_ii_builder_chunk_clear clears stats except rid and buffers except + * enc_buf. + */ +static void +grn_ii_builder_chunk_clear(grn_ctx *ctx, grn_ii_builder_chunk *chunk) +{ + chunk->n = 0; + chunk->rid_gap = 0; + chunk->pos_sum = 0; + chunk->offset = 0; + chunk->pos_offset = 0; +} + +/* + * grn_ii_builder_chunk_extend_bufs extends buffers except pos_buf and enc_buf. + */ +static grn_rc +grn_ii_builder_chunk_extend_bufs(grn_ctx *ctx, grn_ii_builder_chunk *chunk, + uint32_t ii_flags) +{ + uint32_t *buf, size = chunk->size ? chunk->size * 2 : 1; + size_t n_bytes = size * sizeof(uint32_t); + + buf = (uint32_t *)GRN_REALLOC(chunk->rid_buf, n_bytes); + if (!buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for record IDs: n_bytes = %" GRN_FMT_SIZE, + n_bytes); + return ctx->rc; + } + chunk->rid_buf = buf; + + if (ii_flags & GRN_OBJ_WITH_SECTION) { + buf = (uint32_t *)GRN_REALLOC(chunk->sid_buf, n_bytes); + if (!buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for section IDs:" + " n_bytes = %" GRN_FMT_SIZE, + n_bytes); + return ctx->rc; + } + chunk->sid_buf = buf; + } + + buf = (uint32_t *)GRN_REALLOC(chunk->freq_buf, n_bytes); + if (!buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for frequencies: n_bytes = %" GRN_FMT_SIZE, + n_bytes); + return ctx->rc; + } + chunk->freq_buf = buf; + + if (ii_flags & GRN_OBJ_WITH_WEIGHT) { + buf = (uint32_t *)GRN_REALLOC(chunk->weight_buf, n_bytes); + if (!buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for weights: n_bytes = %" GRN_FMT_SIZE, + n_bytes); + return ctx->rc; + } + chunk->weight_buf = buf; + } + + chunk->size = size; + return GRN_SUCCESS; +} + +/* grn_ii_builder_chunk_extend_pos_buf extends pos_buf. */ +static grn_rc +grn_ii_builder_chunk_extend_pos_buf(grn_ctx *ctx, grn_ii_builder_chunk *chunk) +{ + uint32_t *buf, size = chunk->pos_size ? chunk->pos_size * 2 : 1; + size_t n_bytes = size * sizeof(uint32_t); + buf = (uint32_t *)GRN_REALLOC(chunk->pos_buf, n_bytes); + if (!buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for positions: n_bytes = %" GRN_FMT_SIZE, + n_bytes); + return ctx->rc; + } + chunk->pos_buf = buf; + chunk->pos_size = size; + return GRN_SUCCESS; +} + +/* + * grn_ii_builder_chunk_reserve_enc_buf estimates a size that is enough to + * store encoded data and allocates memory to enc_buf. + */ +static grn_rc +grn_ii_builder_chunk_reserve_enc_buf(grn_ctx *ctx, grn_ii_builder_chunk *chunk, + uint32_t n_cinfos) +{ + size_t rich_size = (chunk->n + 4) * sizeof(uint32_t) + + n_cinfos * sizeof(chunk_info); + if (chunk->enc_size < rich_size) { + size_t size = chunk->enc_size ? chunk->enc_size * 2 : 1; + uint8_t *buf; + while (size < rich_size) { + size *= 2; + } + buf = GRN_REALLOC(chunk->enc_buf, size); + if (!buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for encoding: size = %" GRN_FMT_SIZE, + size); + return ctx->rc; + } + chunk->enc_buf = buf; + chunk->enc_size = size; + } + chunk->enc_offset = 0; + return GRN_SUCCESS; +} + +/* grn_ii_builder_chunk_encode encodes a chunk buffer. */ +static void +grn_ii_builder_chunk_encode_buf(grn_ctx *ctx, grn_ii_builder_chunk *chunk, + uint32_t *values, uint32_t n_values, + grn_bool use_p_enc) +{ + uint8_t *p = chunk->enc_buf + chunk->enc_offset; + uint32_t i; + if (use_p_enc) { + uint8_t freq[33]; + uint32_t buf[UNIT_SIZE]; + while (n_values >= UNIT_SIZE) { + memset(freq, 0, 33); + for (i = 0; i < UNIT_SIZE; i++) { + buf[i] = values[i]; + if (buf[i]) { + uint32_t w; + GRN_BIT_SCAN_REV(buf[i], w); + freq[w + 1]++; + } else { + freq[0]++; + } + } + p = pack(buf, UNIT_SIZE, freq, p); + values += UNIT_SIZE; + n_values -= UNIT_SIZE; + } + if (n_values) { + memset(freq, 0, 33); + for (i = 0; i < n_values; i++) { + buf[i] = values[i]; + if (buf[i]) { + uint32_t w; + GRN_BIT_SCAN_REV(buf[i], w); + freq[w + 1]++; + } else { + freq[0]++; + } + } + p = pack(buf, n_values, freq, p); + } + } else { + for (i = 0; i < n_values; i++) { + GRN_B_ENC(values[i], p); + } + } + chunk->enc_offset = p - chunk->enc_buf; +} + +/* grn_ii_builder_chunk_encode encodes a chunk. */ +static grn_rc +grn_ii_builder_chunk_encode(grn_ctx *ctx, grn_ii_builder_chunk *chunk, + chunk_info *cinfos, uint32_t n_cinfos) +{ + grn_rc rc; + uint8_t *p; + uint8_t shift = 0, use_p_enc_flags = 0; + uint8_t rid_use_p_enc, rest_use_p_enc, pos_use_p_enc = 0; + + /* Choose an encoding. */ + rid_use_p_enc = chunk->offset >= 16 && chunk->offset > (chunk->rid >> 8); + use_p_enc_flags |= rid_use_p_enc << shift++; + rest_use_p_enc = chunk->offset >= 3; + if (chunk->sid_buf) { + use_p_enc_flags |= rest_use_p_enc << shift++; + } + use_p_enc_flags |= rest_use_p_enc << shift++; + if (chunk->weight_buf) { + use_p_enc_flags |= rest_use_p_enc << shift++; + } + if (chunk->pos_buf) { + pos_use_p_enc = chunk->pos_offset >= 32 && + chunk->pos_offset > (chunk->pos_sum >> 13); + use_p_enc_flags |= pos_use_p_enc << shift++; + } + + rc = grn_ii_builder_chunk_reserve_enc_buf(ctx, chunk, n_cinfos); + if (rc != GRN_SUCCESS) { + return rc; + } + + /* Encode a header. */ + p = chunk->enc_buf; + if (n_cinfos) { + uint32_t i; + GRN_B_ENC(n_cinfos, p); + for (i = 0; i < n_cinfos; i++) { + GRN_B_ENC(cinfos[i].segno, p); + GRN_B_ENC(cinfos[i].size, p); + GRN_B_ENC(cinfos[i].dgap, p); + } + } + if (use_p_enc_flags) { + GRN_B_ENC(use_p_enc_flags << 1, p); + GRN_B_ENC(chunk->offset, p); + if (chunk->pos_buf) { + GRN_B_ENC(chunk->pos_offset - chunk->offset, p); + } + } else { + GRN_B_ENC((chunk->offset << 1) | 1, p); + } + chunk->enc_offset = p - chunk->enc_buf; + + /* Encode a body. */ + grn_ii_builder_chunk_encode_buf(ctx, chunk, chunk->rid_buf, chunk->offset, + rid_use_p_enc); + if (chunk->sid_buf) { + grn_ii_builder_chunk_encode_buf(ctx, chunk, chunk->sid_buf, chunk->offset, + rest_use_p_enc); + } + grn_ii_builder_chunk_encode_buf(ctx, chunk, chunk->freq_buf, chunk->offset, + rest_use_p_enc); + if (chunk->weight_buf) { + grn_ii_builder_chunk_encode_buf(ctx, chunk, chunk->weight_buf, + chunk->offset, rest_use_p_enc); + } + if (chunk->pos_buf) { + grn_ii_builder_chunk_encode_buf(ctx, chunk, chunk->pos_buf, + chunk->pos_offset, pos_use_p_enc); + } + + return GRN_SUCCESS; +} + +typedef struct { + grn_ii *ii; /* Building inverted index */ + grn_ii_builder_options options; /* Options */ + + grn_obj *src_table; /* Source table */ + grn_obj **srcs; /* Source columns (to be freed) */ + uint32_t n_srcs; /* Number of source columns */ + uint8_t sid_bits; /* Number of bits for section ID */ + uint64_t sid_mask; /* Mask bits for section ID */ + + grn_obj *lexicon; /* Block lexicon (to be closed) */ + grn_obj *tokenizer; /* Lexicon's tokenizer */ + grn_obj *normalizer; /* Lexicon's normalzier */ + + uint32_t n; /* Number of integers appended to the current block */ + grn_id rid; /* Record ID */ + uint32_t sid; /* Section ID */ + uint32_t pos; /* Position */ + + grn_ii_builder_term *terms; /* Terms (to be freed) */ + uint32_t n_terms; /* Number of distinct terms */ + uint32_t max_n_terms; /* Maximum number of distinct terms */ + uint32_t terms_size; /* Buffer size of terms */ + + /* A temporary file to save blocks. */ + char path[PATH_MAX]; /* File path */ + int fd; /* File descriptor (to be closed) */ + uint8_t *file_buf; /* File buffer for buffered output (to be freed) */ + uint32_t file_buf_offset; /* File buffer write offset */ + + grn_ii_builder_block *blocks; /* Blocks (to be freed) */ + uint32_t n_blocks; /* Number of blocks */ + uint32_t blocks_size; /* Buffer size of blocks */ + + grn_ii_builder_buffer buf; /* Buffer (to be finalized) */ + grn_ii_builder_chunk chunk; /* Chunk (to be finalized) */ + + uint32_t df; /* Document frequency (number of sections) */ + chunk_info *cinfos; /* Chunk headers (to be freed) */ + uint32_t n_cinfos; /* Number of chunks */ + uint32_t cinfos_size; /* Size of cinfos */ +} grn_ii_builder; + +/* + * grn_ii_builder_init initializes a builder. Note that an initialized builder + * must be finalized by grn_ii_builder_fin. + */ +static grn_rc +grn_ii_builder_init(grn_ctx *ctx, grn_ii_builder *builder, + grn_ii *ii, const grn_ii_builder_options *options) +{ + builder->ii = ii; + builder->options = *options; + if (grn_ii_builder_block_threshold_force > 0) { + builder->options.block_threshold = grn_ii_builder_block_threshold_force; + } + grn_ii_builder_options_fix(&builder->options); + + builder->src_table = NULL; + builder->srcs = NULL; + builder->n_srcs = 0; + builder->sid_bits = 0; + builder->sid_mask = 0; + + builder->lexicon = NULL; + builder->tokenizer = NULL; + builder->normalizer = NULL; + + builder->n = 0; + builder->rid = GRN_ID_NIL; + builder->sid = 0; + builder->pos = 0; + + builder->terms = NULL; + builder->n_terms = 0; + builder->max_n_terms = 0; + builder->terms_size = 0; + + builder->path[0] = '\0'; + builder->fd = -1; + builder->file_buf = NULL; + builder->file_buf_offset = 0; + + builder->blocks = NULL; + builder->n_blocks = 0; + builder->blocks_size = 0; + + grn_ii_builder_buffer_init(ctx, &builder->buf, ii); + grn_ii_builder_chunk_init(ctx, &builder->chunk); + + builder->df = 0; + builder->cinfos = NULL; + builder->n_cinfos = 0; + builder->cinfos_size = 0; + + return GRN_SUCCESS; +} + +/* grn_ii_builder_fin_terms finalizes terms. */ +static void +grn_ii_builder_fin_terms(grn_ctx *ctx, grn_ii_builder *builder) +{ + if (builder->terms) { + uint32_t i; + for (i = 0; i < builder->max_n_terms; i++) { + grn_ii_builder_term_fin(ctx, &builder->terms[i]); + } + GRN_FREE(builder->terms); + + /* To avoid double finalization. */ + builder->terms = NULL; + } +} + +/* grn_ii_builder_fin finalizes a builder. */ +static grn_rc +grn_ii_builder_fin(grn_ctx *ctx, grn_ii_builder *builder) +{ + if (builder->cinfos) { + GRN_FREE(builder->cinfos); + } + grn_ii_builder_chunk_fin(ctx, &builder->chunk); + grn_ii_builder_buffer_fin(ctx, &builder->buf); + if (builder->blocks) { + uint32_t i; + for (i = 0; i < builder->n_blocks; i++) { + grn_ii_builder_block_fin(ctx, &builder->blocks[i]); + } + GRN_FREE(builder->blocks); + } + if (builder->file_buf) { + GRN_FREE(builder->file_buf); + } + if (builder->fd != -1) { + grn_close(builder->fd); + if (grn_unlink(builder->path) == 0) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[ii][builder][fin] removed path: <%-.256s>", + builder->path); + } else { + ERRNO_ERR("[ii][builder][fin] failed to remove path: <%-.256s>", + builder->path); + } + } + grn_ii_builder_fin_terms(ctx, builder); + if (builder->lexicon) { + grn_obj_close(ctx, builder->lexicon); + } + if (builder->srcs) { + GRN_FREE(builder->srcs); + } + return GRN_SUCCESS; +} + +/* + * grn_ii_builder_open creates a builder. Note that a builder must be closed by + * grn_ii_builder_close. + */ +static grn_rc +grn_ii_builder_open(grn_ctx *ctx, grn_ii *ii, + const grn_ii_builder_options *options, + grn_ii_builder **builder) +{ + grn_rc rc; + grn_ii_builder *new_builder = GRN_MALLOCN(grn_ii_builder, 1); + if (!new_builder) { + return GRN_NO_MEMORY_AVAILABLE; + } + if (!options) { + options = &grn_ii_builder_default_options; + } + rc = grn_ii_builder_init(ctx, new_builder, ii, options); + if (rc != GRN_SUCCESS) { + GRN_FREE(new_builder); + return rc; + } + *builder = new_builder; + return GRN_SUCCESS; +} + +/* grn_ii_builder_close closes a builder. */ +static grn_rc +grn_ii_builder_close(grn_ctx *ctx, grn_ii_builder *builder) +{ + grn_rc rc; + if (!builder) { + ERR(GRN_INVALID_ARGUMENT, "builder is null"); + return ctx->rc; + } + rc = grn_ii_builder_fin(ctx, builder); + GRN_FREE(builder); + return rc; +} + +/* grn_ii_builder_create_lexicon creates a block lexicon. */ +static grn_rc +grn_ii_builder_create_lexicon(grn_ctx *ctx, grn_ii_builder *builder) +{ + grn_table_flags flags; + grn_obj *domain = grn_ctx_at(ctx, builder->ii->lexicon->header.domain); + grn_obj *range = grn_ctx_at(ctx, DB_OBJ(builder->ii->lexicon)->range); + grn_obj *tokenizer, *normalizer, *token_filters; + grn_rc rc = grn_table_get_info(ctx, builder->ii->lexicon, &flags, NULL, + &tokenizer, &normalizer, &token_filters); + if (rc != GRN_SUCCESS) { + return rc; + } + flags &= ~GRN_OBJ_PERSISTENT; + builder->lexicon = grn_table_create(ctx, NULL, 0, NULL, + flags, domain, range); + if (!builder->lexicon) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, "[index] failed to create a block lexicon"); + } + return ctx->rc; + } + builder->tokenizer = tokenizer; + builder->normalizer = normalizer; + rc = grn_obj_set_info(ctx, builder->lexicon, + GRN_INFO_DEFAULT_TOKENIZER, tokenizer); + if (rc == GRN_SUCCESS) { + rc = grn_obj_set_info(ctx, builder->lexicon, + GRN_INFO_NORMALIZER, normalizer); + if (rc == GRN_SUCCESS) { + rc = grn_obj_set_info(ctx, builder->lexicon, + GRN_INFO_TOKEN_FILTERS, token_filters); + } + } + if (rc != GRN_SUCCESS) { + return rc; + } + if ((flags & GRN_OBJ_TABLE_TYPE_MASK) == GRN_OBJ_TABLE_PAT_KEY) { + if (builder->options.lexicon_cache_size) { + rc = grn_pat_cache_enable(ctx, (grn_pat *)builder->lexicon, + builder->options.lexicon_cache_size); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + return GRN_SUCCESS; +} + +/* + * grn_ii_builder_extend_terms extends a buffer for terms in order to make + * terms[n_terms - 1] available. + */ +static grn_rc +grn_ii_builder_extend_terms(grn_ctx *ctx, grn_ii_builder *builder, + uint32_t n_terms) +{ + if (n_terms <= builder->n_terms) { + return GRN_SUCCESS; + } + + if (n_terms > builder->max_n_terms) { + uint32_t i; + if (n_terms > builder->terms_size) { + /* Resize builder->terms for new terms. */ + size_t n_bytes; + uint32_t terms_size = builder->terms_size ? builder->terms_size * 2 : 1; + grn_ii_builder_term *terms; + while (terms_size < n_terms) { + terms_size *= 2; + } + n_bytes = terms_size * sizeof(grn_ii_builder_term); + terms = (grn_ii_builder_term *)GRN_REALLOC(builder->terms, n_bytes); + if (!terms) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for terms: n_bytes = %" GRN_FMT_SIZE, + n_bytes); + return ctx->rc; + } + builder->terms = terms; + builder->terms_size = terms_size; + } + /* Initialize new terms. */ + for (i = builder->max_n_terms; i < n_terms; i++) { + grn_ii_builder_term_init(ctx, &builder->terms[i]); + } + builder->max_n_terms = n_terms; + } + + builder->n += n_terms - builder->n_terms; + builder->n_terms = n_terms; + return GRN_SUCCESS; +} + +/* grn_ii_builder_get_term gets a term associated with tid. */ +inline static grn_rc +grn_ii_builder_get_term(grn_ctx *ctx, grn_ii_builder *builder, grn_id tid, + grn_ii_builder_term **term) +{ + uint32_t n_terms = tid; + if (n_terms > builder->n_terms) { + grn_rc rc = grn_ii_builder_extend_terms(ctx, builder, n_terms); + if (rc != GRN_SUCCESS) { + return rc; + } + } + *term = &builder->terms[tid - 1]; + return GRN_SUCCESS; +} + +/* grn_ii_builder_flush_file_buf flushes buffered data as a block. */ +static grn_rc +grn_ii_builder_flush_file_buf(grn_ctx *ctx, grn_ii_builder *builder) +{ + if (builder->file_buf_offset) { + ssize_t size = grn_write(builder->fd, builder->file_buf, + builder->file_buf_offset); + if ((uint64_t)size != builder->file_buf_offset) { + SERR("failed to write data: expected = %u, actual = %" GRN_FMT_INT64D, + builder->file_buf_offset, (int64_t)size); + } + builder->file_buf_offset = 0; + } + return GRN_SUCCESS; +} + +/* grn_ii_builder_flush_term flushes a term and clears it */ +static grn_rc +grn_ii_builder_flush_term(grn_ctx *ctx, grn_ii_builder *builder, + grn_ii_builder_term *term) +{ + grn_rc rc; + uint8_t *term_buf; + + /* Append sentinels. */ + if (term->rid != GRN_ID_NIL) { + if (builder->ii->header->flags & GRN_OBJ_WITH_POSITION) { + rc = grn_ii_builder_term_append(ctx, term, 0); + } else { + rc = grn_ii_builder_term_append(ctx, term, term->pos_or_freq); + } + if (rc != GRN_SUCCESS) { + return rc; + } + } + rc = grn_ii_builder_term_append(ctx, term, 0); + if (rc != GRN_SUCCESS) { + return rc; + } + + { + /* Put the global term ID. */ + int key_size; + char key[GRN_TABLE_MAX_KEY_SIZE]; + uint8_t *p; + uint32_t rest, value; + grn_rc rc; + grn_id local_tid = term - builder->terms + 1, global_tid; + key_size = grn_table_get_key(ctx, builder->lexicon, local_tid, + key, GRN_TABLE_MAX_KEY_SIZE); + if (!key_size) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, "failed to get key: tid = %u", local_tid); + } + return ctx->rc; + } + global_tid = grn_table_add(ctx, builder->ii->lexicon, key, key_size, NULL); + if (global_tid == GRN_ID_NIL) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, + "failed to get global term ID: tid = %u, key = \"%.*s\"", + local_tid, key_size, key); + } + return ctx->rc; + } + + rest = builder->options.file_buf_size - builder->file_buf_offset; + if (rest < 10) { + rc = grn_ii_builder_flush_file_buf(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + } + value = global_tid; + p = builder->file_buf + builder->file_buf_offset; + if (value < 1U << 5) { + p[0] = (uint8_t)value; + builder->file_buf_offset++; + } else if (value < 1U << 13) { + p[0] = (uint8_t)((value & 0x1f) | (1 << 5)); + p[1] = (uint8_t)(value >> 5); + builder->file_buf_offset += 2; + } else { + uint8_t i, n; + if (value < 1U << 21) { + n = 3; + } else if (value < 1U << 29) { + n = 4; + } else { + n = 5; + } + p[0] = (uint8_t)(value & 0x1f) | ((n - 1) << 5); + value >>= 5; + for (i = 1; i < n; i++) { + p[i] = (uint8_t)value; + value >>= 8; + } + builder->file_buf_offset += n; + } + } + + /* Flush a term buffer. */ + term_buf = grn_ii_builder_term_get_buf(term); + if (term->offset > builder->options.file_buf_size) { + ssize_t size; + rc = grn_ii_builder_flush_file_buf(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + size = grn_write(builder->fd, term_buf, term->offset); + if ((uint64_t)size != term->offset) { + SERR("failed to write data: expected = %u, actual = %" GRN_FMT_INT64D, + term->offset, (int64_t)size); + } + } else { + uint32_t rest = builder->options.file_buf_size - builder->file_buf_offset; + if (term->offset <= rest) { + grn_memcpy(builder->file_buf + builder->file_buf_offset, + term_buf, term->offset); + builder->file_buf_offset += term->offset; + } else { + grn_memcpy(builder->file_buf + builder->file_buf_offset, + term_buf, rest); + builder->file_buf_offset += rest; + rc = grn_ii_builder_flush_file_buf(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->file_buf_offset = term->offset - rest; + grn_memcpy(builder->file_buf, term_buf + rest, builder->file_buf_offset); + } + } + grn_ii_builder_term_reinit(ctx, term); + return GRN_SUCCESS; +} + +/* + * grn_ii_builder_create_file creates a temporary file and allocates memory for + * buffered output. + */ +static grn_rc +grn_ii_builder_create_file(grn_ctx *ctx, grn_ii_builder *builder) +{ + grn_snprintf(builder->path, PATH_MAX, PATH_MAX, + "%-.256sXXXXXX", grn_io_path(builder->ii->seg)); + builder->fd = grn_mkstemp(builder->path); + if (builder->fd == -1) { + SERR("failed to create a temporary file: path = \"%-.256s\"", + builder->path); + return ctx->rc; + } + builder->file_buf = (uint8_t *)GRN_MALLOC(builder->options.file_buf_size); + if (!builder->file_buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for buffered output: size = %u", + builder->options.file_buf_size); + return ctx->rc; + } + return GRN_SUCCESS; +} + +/* grn_ii_builder_register_block registers a block. */ +static grn_rc +grn_ii_builder_register_block(grn_ctx *ctx, grn_ii_builder *builder) +{ + grn_ii_builder_block *block; + uint64_t file_offset = grn_lseek(builder->fd, 0, SEEK_CUR); + if (file_offset == (uint64_t)-1) { + SERR("failed to get file offset"); + return ctx->rc; + } + if (builder->n_blocks >= builder->blocks_size) { + size_t n_bytes; + uint32_t blocks_size = 1; + grn_ii_builder_block *blocks; + while (blocks_size <= builder->n_blocks) { + blocks_size *= 2; + } + n_bytes = blocks_size * sizeof(grn_ii_builder_block); + blocks = (grn_ii_builder_block *)GRN_REALLOC(builder->blocks, n_bytes); + if (!blocks) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for block: n_bytes = %" GRN_FMT_SIZE, + n_bytes); + return ctx->rc; + } + builder->blocks = blocks; + builder->blocks_size = blocks_size; + } + block = &builder->blocks[builder->n_blocks]; + grn_ii_builder_block_init(ctx, block); + if (!builder->n_blocks) { + block->offset = 0; + } else { + grn_ii_builder_block *prev_block = &builder->blocks[builder->n_blocks - 1]; + block->offset = prev_block->offset + prev_block->rest; + } + block->rest = (uint32_t)(file_offset - block->offset); + builder->n_blocks++; + return GRN_SUCCESS; +} + +/* grn_ii_builder_flush_block flushes a block to a temporary file. */ +static grn_rc +grn_ii_builder_flush_block(grn_ctx *ctx, grn_ii_builder *builder) +{ + grn_rc rc; + grn_table_cursor *cursor; + + if (!builder->n) { + /* Do nothing if there are no output data. */ + return GRN_SUCCESS; + } + if (builder->fd == -1) { + rc = grn_ii_builder_create_file(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + } + + /* Flush terms into a temporary file. */ + cursor = grn_table_cursor_open(ctx, builder->lexicon, + NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_BY_KEY); + for (;;) { + grn_id tid = grn_table_cursor_next(ctx, cursor); + if (tid == GRN_ID_NIL) { + break; + } + rc = grn_ii_builder_flush_term(ctx, builder, &builder->terms[tid - 1]); + if (rc != GRN_SUCCESS) { + return rc; + } + } + grn_table_cursor_close(ctx, cursor); + rc = grn_ii_builder_flush_file_buf(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + + /* Register a block and clear the current data. */ + rc = grn_ii_builder_register_block(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_table_truncate(ctx, builder->lexicon); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->rid = GRN_ID_NIL; + builder->n_terms = 0; + builder->n = 0; + return GRN_SUCCESS; +} + +/* grn_ii_builder_append_token appends a token. */ +static grn_rc +grn_ii_builder_append_token(grn_ctx *ctx, grn_ii_builder *builder, + grn_id rid, uint32_t sid, uint32_t weight, + grn_id tid, uint32_t pos) +{ + grn_rc rc; + uint32_t ii_flags = builder->ii->header->flags; + grn_ii_builder_term *term; + rc = grn_ii_builder_get_term(ctx, builder, tid, &term); + if (rc != GRN_SUCCESS) { + return rc; + } + if (rid != term->rid || sid != term->sid) { + uint64_t rsid; + if (term->rid != GRN_ID_NIL) { + if (ii_flags & GRN_OBJ_WITH_POSITION) { + /* Append the end of positions. */ + rc = grn_ii_builder_term_append(ctx, term, 0); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->n++; + } else { + /* Append a frequency if positions are not available. */ + rc = grn_ii_builder_term_append(ctx, term, term->pos_or_freq); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->n++; + } + } + rsid = ((uint64_t)(rid - term->rid) << builder->sid_bits) | (sid - 1); + rc = grn_ii_builder_term_append(ctx, term, rsid); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->n++; + if (ii_flags & GRN_OBJ_WITH_WEIGHT) { + rc = grn_ii_builder_term_append(ctx, term, weight); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->n++; + } + term->rid = rid; + term->sid = sid; + term->pos_or_freq = 0; + } + if (ii_flags & GRN_OBJ_WITH_POSITION) { + rc = grn_ii_builder_term_append(ctx, term, pos - term->pos_or_freq); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->n++; + term->pos_or_freq = pos; + } else { + term->pos_or_freq++; + } + return GRN_SUCCESS; +} + +/* + * grn_ii_builder_append_value appends a value. Note that values must be + * appended in ascending rid and sid order. + */ +static grn_rc +grn_ii_builder_append_value(grn_ctx *ctx, grn_ii_builder *builder, + grn_id rid, uint32_t sid, uint32_t weight, + const char *value, uint32_t value_size) +{ + uint32_t pos = 0; + grn_token_cursor *cursor; + if (rid != builder->rid) { + builder->rid = rid; + builder->sid = sid; + builder->pos = 1; + } else if (sid != builder->sid) { + builder->sid = sid; + builder->pos = 1; + } else { + /* Insert a space between values. */ + builder->pos++; + } + if (value_size) { + if (!builder->tokenizer && !builder->normalizer) { + grn_id tid; + switch (builder->lexicon->header.type) { + case GRN_TABLE_PAT_KEY : + tid = grn_pat_add(ctx, (grn_pat *)builder->lexicon, + value, value_size, NULL, NULL); + break; + case GRN_TABLE_DAT_KEY : + tid = grn_dat_add(ctx, (grn_dat *)builder->lexicon, + value, value_size, NULL, NULL); + break; + case GRN_TABLE_HASH_KEY : + tid = grn_hash_add(ctx, (grn_hash *)builder->lexicon, + value, value_size, NULL, NULL); + break; + case GRN_TABLE_NO_KEY : + tid = *(grn_id *)value; + break; + default : + tid = GRN_ID_NIL; + break; + } + if (tid != GRN_ID_NIL) { + grn_rc rc; + pos = builder->pos; + rc = grn_ii_builder_append_token(ctx, builder, rid, sid, + weight, tid, pos); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } else { + cursor = grn_token_cursor_open(ctx, builder->lexicon, value, value_size, + GRN_TOKEN_ADD, 0); + if (!cursor) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, + "grn_token_cursor_open failed: value = <%.*s>", + value_size, value); + } + return ctx->rc; + } + while (cursor->status == GRN_TOKEN_CURSOR_DOING) { + grn_id tid = grn_token_cursor_next(ctx, cursor); + if (tid != GRN_ID_NIL) { + grn_rc rc; + pos = builder->pos + cursor->pos; + rc = grn_ii_builder_append_token(ctx, builder, rid, sid, + weight, tid, pos); + if (rc != GRN_SUCCESS) { + break; + } + } + } + grn_token_cursor_close(ctx, cursor); + } + } + builder->pos = pos + 1; + return ctx->rc; +} + +/* grn_ii_builder_append_obj appends a BULK, UVECTOR or VECTOR object. */ +static grn_rc +grn_ii_builder_append_obj(grn_ctx *ctx, grn_ii_builder *builder, + grn_id rid, uint32_t sid, grn_obj *obj) +{ + switch (obj->header.type) { + case GRN_BULK : + return grn_ii_builder_append_value(ctx, builder, rid, sid, 0, + GRN_TEXT_VALUE(obj), GRN_TEXT_LEN(obj)); + case GRN_UVECTOR : + { + const char *p = GRN_BULK_HEAD(obj); + uint32_t i, n_values = grn_uvector_size(ctx, obj); + uint32_t value_size = grn_uvector_element_size(ctx, obj); + for (i = 0; i < n_values; i++) { + grn_rc rc = grn_ii_builder_append_value(ctx, builder, rid, sid, 0, + p, value_size); + if (rc != GRN_SUCCESS) { + return rc; + } + p += value_size; + } + } + return GRN_SUCCESS; + case GRN_VECTOR : + if (obj->u.v.body) { + /* + * Note that the following sections and n_sections don't correspond to + * source columns. + */ + int i, n_secs = obj->u.v.n_sections; + grn_section *secs = obj->u.v.sections; + const char *head = GRN_BULK_HEAD(obj->u.v.body); + for (i = 0; i < n_secs; i++) { + grn_rc rc; + grn_section *sec = &secs[i]; + if (sec->length == 0) { + continue; + } + if (builder->tokenizer) { + sid = i + 1; + } + rc = grn_ii_builder_append_value(ctx, builder, rid, sid, sec->weight, + head + sec->offset, sec->length); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + return GRN_SUCCESS; + default : + ERR(GRN_INVALID_ARGUMENT, "[index] invalid object assigned as value"); + return ctx->rc; + } +} + +/* + * grn_ii_builder_append_srcs reads values from source columns and appends the + * values. + */ +static grn_rc +grn_ii_builder_append_srcs(grn_ctx *ctx, grn_ii_builder *builder) +{ + size_t i; + grn_rc rc = GRN_SUCCESS; + grn_obj *objs; + grn_table_cursor *cursor; + + /* Allocate memory for objects to store source values. */ + objs = GRN_MALLOCN(grn_obj, builder->n_srcs); + if (!objs) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for objs: n_srcs = %u", builder->n_srcs); + return ctx->rc; + } + + /* Create a cursor to get records in the ID order. */ + cursor = grn_table_cursor_open(ctx, builder->src_table, NULL, 0, NULL, 0, + 0, -1, GRN_CURSOR_BY_ID); + if (!cursor) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_OBJECT_CORRUPT, "[index] failed to open table cursor"); + } + GRN_FREE(objs); + return ctx->rc; + } + + /* Read source values and append it. */ + for (i = 0; i < builder->n_srcs; i++) { + GRN_TEXT_INIT(&objs[i], 0); + } + while (rc == GRN_SUCCESS) { + grn_id rid = grn_table_cursor_next(ctx, cursor); + if (rid == GRN_ID_NIL) { + break; + } + for (i = 0; i < builder->n_srcs; i++) { + grn_obj *obj = &objs[i]; + grn_obj *src = builder->srcs[i]; + rc = grn_obj_reinit_for(ctx, obj, src); + if (rc == GRN_SUCCESS) { + if (GRN_OBJ_TABLEP(src)) { + int len = grn_table_get_key2(ctx, src, rid, obj); + if (len <= 0) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, "failed to get key: rid = %u, len = %d", + rid, len); + } + rc = ctx->rc; + } + } else { + if (!grn_obj_get_value(ctx, src, rid, obj)) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, "failed to get value: rid = %u", rid); + } + rc = ctx->rc; + } + } + if (rc == GRN_SUCCESS) { + uint32_t sid = (uint32_t)(i + 1); + rc = grn_ii_builder_append_obj(ctx, builder, rid, sid, obj); + } + } + } + if (rc == GRN_SUCCESS && builder->n >= builder->options.block_threshold) { + rc = grn_ii_builder_flush_block(ctx, builder); + } + } + if (rc == GRN_SUCCESS) { + rc = grn_ii_builder_flush_block(ctx, builder); + } + for (i = 0; i < builder->n_srcs; i++) { + GRN_OBJ_FIN(ctx, &objs[i]); + } + grn_table_cursor_close(ctx, cursor); + GRN_FREE(objs); + return rc; +} + +/* grn_ii_builder_set_src_table sets a source table. */ +static grn_rc +grn_ii_builder_set_src_table(grn_ctx *ctx, grn_ii_builder *builder) +{ + builder->src_table = grn_ctx_at(ctx, DB_OBJ(builder->ii)->range); + if (!builder->src_table) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_INVALID_ARGUMENT, "source table is null: range = %d", + DB_OBJ(builder->ii)->range); + } + return ctx->rc; + } + return GRN_SUCCESS; +} + +/* grn_ii_builder_set_sid_bits calculates sid_bits and sid_mask. */ +static grn_rc +grn_ii_builder_set_sid_bits(grn_ctx *ctx, grn_ii_builder *builder) +{ + /* Calculate the number of bits required to represent a section ID. */ + if (builder->n_srcs == 1 && builder->tokenizer && + (builder->srcs[0]->header.flags & GRN_OBJ_COLUMN_VECTOR) != 0) { + /* If the source column is a vector column and the index has a tokenizer, */ + /* the maximum sid equals to the maximum number of elements. */ + size_t max_elems = 0; + grn_table_cursor *cursor; + grn_obj obj; + cursor = grn_table_cursor_open(ctx, builder->src_table, NULL, 0, NULL, 0, + 0, -1, GRN_CURSOR_BY_ID); + if (!cursor) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_OBJECT_CORRUPT, "[index] failed to open table cursor"); + } + return ctx->rc; + } + GRN_TEXT_INIT(&obj, 0); + for (;;) { + grn_id rid = grn_table_cursor_next(ctx, cursor); + if (rid == GRN_ID_NIL) { + break; + } + if (!grn_obj_get_value(ctx, builder->srcs[0], rid, &obj)) { + continue; + } + if (obj.u.v.n_sections > max_elems) { + max_elems = obj.u.v.n_sections; + } + } + GRN_OBJ_FIN(ctx, &obj); + grn_table_cursor_close(ctx, cursor); + while (((uint32_t)1 << builder->sid_bits) < max_elems) { + builder->sid_bits++; + } + } + if (builder->sid_bits == 0) { + while (((uint32_t)1 << builder->sid_bits) < builder->n_srcs) { + builder->sid_bits++; + } + } + builder->sid_mask = ((uint64_t)1 << builder->sid_bits) - 1; + return GRN_SUCCESS; +} + +/* grn_ii_builder_set_srcs sets source columns. */ +static grn_rc +grn_ii_builder_set_srcs(grn_ctx *ctx, grn_ii_builder *builder) +{ + size_t i; + grn_id *source; + builder->n_srcs = builder->ii->obj.source_size / sizeof(grn_id); + source = (grn_id *)builder->ii->obj.source; + if (!source || !builder->n_srcs) { + ERR(GRN_INVALID_ARGUMENT, + "source is not available: source = %p, source_size = %u", + builder->ii->obj.source, builder->ii->obj.source_size); + return ctx->rc; + } + builder->srcs = GRN_MALLOCN(grn_obj *, builder->n_srcs); + if (!builder->srcs) { + return GRN_NO_MEMORY_AVAILABLE; + } + for (i = 0; i < builder->n_srcs; i++) { + builder->srcs[i] = grn_ctx_at(ctx, source[i]); + if (!builder->srcs[i]) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_OBJECT_CORRUPT, "source not found: id = %d", source[i]); + } + return ctx->rc; + } + } + return grn_ii_builder_set_sid_bits(ctx, builder); +} + +/* grn_ii_builder_append_source appends values in source columns. */ +static grn_rc +grn_ii_builder_append_source(grn_ctx *ctx, grn_ii_builder *builder) +{ + grn_rc rc = grn_ii_builder_set_src_table(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + if (grn_table_size(ctx, builder->src_table) == 0) { + /* Nothing to do because there are no values. */ + return ctx->rc; + } + /* Create a block lexicon. */ + rc = grn_ii_builder_create_lexicon(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ii_builder_set_srcs(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ii_builder_append_srcs(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + grn_ii_builder_fin_terms(ctx, builder); + return GRN_SUCCESS; +} + +/* + * grn_ii_builder_fill_block reads the next data from a temporary file and fill + * a block buffer. + */ +static grn_rc +grn_ii_builder_fill_block(grn_ctx *ctx, grn_ii_builder *builder, + uint32_t block_id) +{ + ssize_t size; + uint32_t buf_rest; + uint64_t file_offset; + grn_ii_builder_block *block = &builder->blocks[block_id]; + if (!block->rest) { + return GRN_END_OF_DATA; + } + if (!block->buf) { + block->buf = (uint8_t *)GRN_MALLOC(builder->options.block_buf_size); + if (!block->buf) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for buffered input: size = %u", + builder->options.block_buf_size); + return ctx->rc; + } + } + + /* Move the remaining data to the head. */ + buf_rest = block->end - block->cur; + if (buf_rest) { + grn_memmove(block->buf, block->cur, buf_rest); + } + block->cur = block->buf; + block->end = block->buf + buf_rest; + + /* Read the next data. */ + file_offset = grn_lseek(builder->fd, block->offset, SEEK_SET); + if (file_offset != block->offset) { + SERR("failed to seek file: expected = %" GRN_FMT_INT64U + ", actual = %" GRN_FMT_INT64D, + block->offset, file_offset); + return ctx->rc; + } + buf_rest = builder->options.block_buf_size - buf_rest; + if (block->rest < buf_rest) { + buf_rest = block->rest; + } + size = grn_read(builder->fd, block->end, buf_rest); + if (size <= 0) { + SERR("failed to read data: expected = %u, actual = %" GRN_FMT_INT64D, + buf_rest, (int64_t)size); + return ctx->rc; + } + block->offset += size; + block->rest -= size; + block->end += size; + return GRN_SUCCESS; +} + +/* grn_ii_builder_read_from_block reads the next value from a block. */ +static grn_rc +grn_ii_builder_read_from_block(grn_ctx *ctx, grn_ii_builder *builder, + uint32_t block_id, uint64_t *value) +{ + grn_ii_builder_block *block = &builder->blocks[block_id]; + grn_rc rc = grn_ii_builder_block_next(ctx, block, value); + if (rc == GRN_SUCCESS) { + return GRN_SUCCESS; + } else if (rc == GRN_END_OF_DATA) { + rc = grn_ii_builder_fill_block(ctx, builder, block_id); + if (rc != GRN_SUCCESS) { + return rc; + } + return grn_ii_builder_block_next(ctx, block, value); + } + return rc; +} + +/* grn_ii_builder_pack_chunk tries to pack a chunk. */ +static grn_rc +grn_ii_builder_pack_chunk(grn_ctx *ctx, grn_ii_builder *builder, + grn_bool *packed) +{ + grn_id rid; + uint32_t sid, pos, *a; + grn_ii_builder_chunk *chunk = &builder->chunk; + *packed = GRN_FALSE; + if (chunk->offset != 1) { /* df != 1 */ + return GRN_SUCCESS; + } + if (chunk->weight_buf && chunk->weight_buf[0]) { /* weight != 0 */ + return GRN_SUCCESS; + } + if (chunk->freq_buf[0] != 0) { /* freq != 1 */ + return GRN_SUCCESS; + } + rid = chunk->rid_buf[0]; + if (chunk->sid_buf) { + if (rid >= 0x100000) { + return GRN_SUCCESS; + } + sid = chunk->sid_buf[0] + 1; + if (sid >= 0x800) { + return GRN_SUCCESS; + } + a = array_get(ctx, builder->ii, chunk->tid); + if (!a) { + DEFINE_NAME(builder->ii); + MERR("[ii][builder][chunk][pack] failed to allocate an array: " + "<%.*s>: " + "<%u>:<%u>:<%u>", + name_size, name, + rid, sid, chunk->tid); + return ctx->rc; + } + a[0] = ((rid << 12) + (sid << 1)) | 1; + } else { + a = array_get(ctx, builder->ii, chunk->tid); + if (!a) { + DEFINE_NAME(builder->ii); + MERR("[ii][builder][chunk][pack] failed to allocate an array: " + "<%.*s>: " + "<%u>:<%u>", + name_size, name, + rid, chunk->tid); + return ctx->rc; + } + a[0] = (rid << 1) | 1; + } + pos = 0; + if (chunk->pos_buf) { + pos = chunk->pos_buf[0]; + } + a[1] = pos; + array_unref(builder->ii, chunk->tid); + *packed = GRN_TRUE; + + grn_ii_builder_chunk_clear(ctx, chunk); + return GRN_SUCCESS; +} + +/* grn_ii_builder_get_cinfo returns a new cinfo. */ +static grn_rc +grn_ii_builder_get_cinfo(grn_ctx *ctx, grn_ii_builder *builder, + chunk_info **cinfo) +{ + if (builder->n_cinfos == builder->cinfos_size) { + uint32_t size = builder->cinfos_size ? (builder->cinfos_size * 2) : 1; + size_t n_bytes = size * sizeof(chunk_info); + chunk_info *cinfos = (chunk_info *)GRN_REALLOC(builder->cinfos, n_bytes); + if (!cinfos) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate memory for cinfos: n_bytes = %" GRN_FMT_SIZE, + n_bytes); + return ctx->rc; + } + builder->cinfos = cinfos; + builder->cinfos_size = size; + } + *cinfo = &builder->cinfos[builder->n_cinfos++]; + return GRN_SUCCESS; +} + +/* grn_ii_builder_flush_chunk flushes a chunk. */ +static grn_rc +grn_ii_builder_flush_chunk(grn_ctx *ctx, grn_ii_builder *builder) +{ + grn_rc rc; + chunk_info *cinfo = NULL; + grn_ii_builder_chunk *chunk = &builder->chunk; + void *seg; + uint8_t *in; + uint32_t in_size, chunk_id, seg_id, seg_offset, seg_rest; + + rc = grn_ii_builder_chunk_encode(ctx, chunk, NULL, 0); + if (rc != GRN_SUCCESS) { + return rc; + } + in = chunk->enc_buf; + in_size = chunk->enc_offset; + + rc = chunk_new(ctx, builder->ii, &chunk_id, chunk->enc_offset); + if (rc != GRN_SUCCESS) { + return rc; + } + + /* Copy to the first segment. */ + seg_id = chunk_id >> GRN_II_N_CHUNK_VARIATION; + seg_offset = (chunk_id & ((1 << GRN_II_N_CHUNK_VARIATION) - 1)) << + GRN_II_W_LEAST_CHUNK; + GRN_IO_SEG_REF(builder->ii->chunk, seg_id, seg); + if (!seg) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, + "failed access chunk segment: chunk_id = %u, seg_id = %u", + chunk_id, seg_id); + } + return ctx->rc; + } + seg_rest = S_CHUNK - seg_offset; + if (in_size <= seg_rest) { + grn_memcpy((uint8_t *)seg + seg_offset, in, in_size); + in_size = 0; + } else { + grn_memcpy((uint8_t *)seg + seg_offset, in, seg_rest); + in += seg_rest; + in_size -= seg_rest; + } + GRN_IO_SEG_UNREF(builder->ii->chunk, seg_id); + + /* Copy to the next segments. */ + while (in_size) { + seg_id++; + GRN_IO_SEG_REF(builder->ii->chunk, seg_id, seg); + if (!seg) { + if (ctx->rc == GRN_SUCCESS) { + ERR(GRN_UNKNOWN_ERROR, + "failed access chunk segment: chunk_id = %u, seg_id = %u", + chunk_id, seg_id); + } + return ctx->rc; + } + if (in_size <= S_CHUNK) { + grn_memcpy(seg, in, in_size); + in_size = 0; + } else { + grn_memcpy(seg, in, S_CHUNK); + in += S_CHUNK; + in_size -= S_CHUNK; + } + GRN_IO_SEG_UNREF(builder->ii->chunk, seg_id); + } + + /* Append a cinfo. */ + rc = grn_ii_builder_get_cinfo(ctx, builder, &cinfo); + if (rc != GRN_SUCCESS) { + return rc; + } + cinfo->segno = chunk_id; + cinfo->size = chunk->enc_offset; + cinfo->dgap = chunk->rid_gap; + + builder->buf.ii->header->total_chunk_size += chunk->enc_offset; + grn_ii_builder_chunk_clear(ctx, chunk); + return GRN_SUCCESS; +} + +/* grn_ii_builder_read_to_chunk read values from a block to a chunk. */ +static grn_rc +grn_ii_builder_read_to_chunk(grn_ctx *ctx, grn_ii_builder *builder, + uint32_t block_id) +{ + grn_rc rc; + uint64_t value; + uint32_t rid = GRN_ID_NIL, last_sid = 0; + uint32_t ii_flags = builder->ii->header->flags; + grn_ii_builder_chunk *chunk = &builder->chunk; + + for (;;) { + uint32_t gap, freq; + uint64_t value; + rc = grn_ii_builder_read_from_block(ctx, builder, block_id, &value); + if (rc != GRN_SUCCESS) { + return rc; + } + if (!value) { + break; + } + if (builder->chunk.offset == builder->chunk.size) { + rc = grn_ii_builder_chunk_extend_bufs(ctx, chunk, ii_flags); + if (rc != GRN_SUCCESS) { + return rc; + } + } + + /* Read record ID. */ + gap = value >> builder->sid_bits; /* In-block gap */ + if (gap) { + if (chunk->n >= builder->options.chunk_threshold) { + rc = grn_ii_builder_flush_chunk(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + } + last_sid = 0; + } + rid += gap; + gap = rid - chunk->rid; /* Global gap */ + chunk->rid_buf[chunk->offset] = chunk->offset ? gap : rid; + chunk->n++; + chunk->rid = rid; + chunk->rid_gap += gap; + builder->df++; + + /* Read section ID. */ + if (ii_flags & GRN_OBJ_WITH_SECTION) { + uint32_t sid = (value & builder->sid_mask) + 1; + chunk->sid_buf[chunk->offset] = sid - last_sid - 1; + chunk->n++; + last_sid = sid; + } + + /* Read weight. */ + if (ii_flags & GRN_OBJ_WITH_WEIGHT) { + uint32_t weight; + rc = grn_ii_builder_read_from_block(ctx, builder, block_id, &value); + if (rc != GRN_SUCCESS) { + return rc; + } + weight = value; + chunk->weight_buf[chunk->offset] = weight; + chunk->n++; + } + + /* Read positions or a frequency. */ + if (ii_flags & GRN_OBJ_WITH_POSITION) { + uint32_t pos = -1; + freq = 0; + for (;;) { + rc = grn_ii_builder_read_from_block(ctx, builder, block_id, &value); + if (rc != GRN_SUCCESS) { + return rc; + } + if (!value) { + break; + } + if (builder->chunk.pos_offset == builder->chunk.pos_size) { + rc = grn_ii_builder_chunk_extend_pos_buf(ctx, chunk); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (pos == -1) { + chunk->pos_buf[chunk->pos_offset] = value - 1; + chunk->pos_sum += value - 1; + } else { + chunk->pos_buf[chunk->pos_offset] = value; + chunk->pos_sum += value; + } + chunk->n++; + pos += value; + chunk->pos_offset++; + freq++; + } + } else { + rc = grn_ii_builder_read_from_block(ctx, builder, block_id, &value); + if (rc != GRN_SUCCESS) { + return rc; + } + freq = value; + } + chunk->freq_buf[chunk->offset] = freq - 1; + chunk->n++; + chunk->offset++; + } + rc = grn_ii_builder_read_from_block(ctx, builder, block_id, &value); + if (rc == GRN_SUCCESS) { + builder->blocks[block_id].tid = value; + } else if (rc == GRN_END_OF_DATA) { + builder->blocks[block_id].tid = GRN_ID_NIL; + } else { + return rc; + } + return GRN_SUCCESS; +} + +/* grn_ii_builder_register_chunks registers chunks. */ +static grn_rc +grn_ii_builder_register_chunks(grn_ctx *ctx, grn_ii_builder *builder) +{ + grn_rc rc; + uint32_t buf_tid, *a; + buffer_term *buf_term; + + rc = grn_ii_builder_chunk_encode(ctx, &builder->chunk, builder->cinfos, + builder->n_cinfos); + if (rc != GRN_SUCCESS) { + return rc; + } + + if (!grn_ii_builder_buffer_is_assigned(ctx, &builder->buf)) { + rc = grn_ii_builder_buffer_assign(ctx, &builder->buf, + builder->chunk.enc_offset); + if (rc != GRN_SUCCESS) { + return rc; + } + } + buf_tid = builder->buf.buf->header.nterms; + if (buf_tid >= builder->options.buffer_max_n_terms || + builder->buf.chunk_size - builder->buf.chunk_offset < + builder->chunk.enc_offset) { + rc = grn_ii_builder_buffer_flush(ctx, &builder->buf); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ii_builder_buffer_assign(ctx, &builder->buf, + builder->chunk.enc_offset); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_tid = 0; + } + buf_term = &builder->buf.buf->terms[buf_tid]; + buf_term->tid = builder->chunk.tid; + if (builder->n_cinfos) { + buf_term->tid |= CHUNK_SPLIT; + } + buf_term->size_in_buffer = 0; + buf_term->pos_in_buffer = 0; + buf_term->size_in_chunk = builder->chunk.enc_offset; + buf_term->pos_in_chunk = builder->buf.chunk_offset; + + grn_memcpy(builder->buf.chunk + builder->buf.chunk_offset, + builder->chunk.enc_buf, builder->chunk.enc_offset); + builder->buf.chunk_offset += builder->chunk.enc_offset; + + a = array_get(ctx, builder->ii, builder->chunk.tid); + if (!a) { + DEFINE_NAME(builder->ii); + MERR("[ii][builder][chunk][register] " + "failed to allocate an array in segment: " + "<%.*s>: " + "tid=<%u>: max_n_segments=<%u>", + name_size, name, + builder->chunk.tid, + builder->ii->seg->header->max_segment); + return ctx->rc; + } + a[0] = SEG2POS(builder->buf.buf_id, + sizeof(buffer_header) + buf_tid * sizeof(buffer_term)); + a[1] = builder->df; + array_unref(builder->ii, builder->chunk.tid); + + builder->buf.buf->header.nterms++; + builder->n_cinfos = 0; + grn_ii_builder_chunk_clear(ctx, &builder->chunk); + return GRN_SUCCESS; +} + +static grn_rc +grn_ii_builder_commit(grn_ctx *ctx, grn_ii_builder *builder) +{ + uint32_t i; + grn_rc rc; + grn_table_cursor *cursor; + + for (i = 0; i < builder->n_blocks; i++) { + uint64_t value; + rc = grn_ii_builder_read_from_block(ctx, builder, i, &value); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->blocks[i].tid = value; + } + + cursor = grn_table_cursor_open(ctx, builder->ii->lexicon, + NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_BY_KEY); + for (;;) { + grn_id tid = grn_table_cursor_next(ctx, cursor); + if (tid == GRN_ID_NIL) { + break; + } + builder->chunk.tid = tid; + builder->chunk.rid = GRN_ID_NIL; + builder->df = 0; + for (i = 0; i < builder->n_blocks; i++) { + if (tid == builder->blocks[i].tid) { + rc = grn_ii_builder_read_to_chunk(ctx, builder, i); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + if (!builder->chunk.n) { + /* This term does not appear. */ + continue; + } + if (!builder->n_cinfos) { + grn_bool packed; + rc = grn_ii_builder_pack_chunk(ctx, builder, &packed); + if (rc != GRN_SUCCESS) { + return rc; + } + if (packed) { + continue; + } + } + rc = grn_ii_builder_register_chunks(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + } + grn_table_cursor_close(ctx, cursor); + if (grn_ii_builder_buffer_is_assigned(ctx, &builder->buf)) { + rc = grn_ii_builder_buffer_flush(ctx, &builder->buf); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +grn_rc +grn_ii_build2(grn_ctx *ctx, grn_ii *ii, const grn_ii_builder_options *options) +{ + grn_rc rc, rc_close; + grn_ii_builder *builder; + rc = grn_ii_builder_open(ctx, ii, options, &builder); + if (rc == GRN_SUCCESS) { + rc = grn_ii_builder_append_source(ctx, builder); + if (rc == GRN_SUCCESS) { + rc = grn_ii_builder_commit(ctx, builder); + } + rc_close = grn_ii_builder_close(ctx, builder); + if (rc == GRN_SUCCESS) { + rc = rc_close; + } + } + return rc; +} diff --git a/storage/mroonga/vendor/groonga/lib/index_column.c b/storage/mroonga/vendor/groonga/lib/index_column.c new file mode 100644 index 00000000..c4a2a7c6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/index_column.c @@ -0,0 +1,194 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_index_column.h" +#include "grn_ii.h" +#include "grn_hash.h" + +#include + +static uint64_t grn_index_sparsity = 10; +static grn_bool grn_index_chunk_split_enable = GRN_TRUE; + +void +grn_index_column_init_from_env(void) +{ + { + char grn_index_sparsity_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_INDEX_SPARSITY", + grn_index_sparsity_env, + GRN_ENV_BUFFER_SIZE); + if (grn_index_sparsity_env[0]) { + uint64_t sparsity; + errno = 0; + sparsity = strtoull(grn_index_sparsity_env, NULL, 0); + if (errno == 0) { + grn_index_sparsity = sparsity; + } + } + } + + { + char grn_index_chunk_split_enable_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_INDEX_CHUNK_SPLIT_ENABLE", + grn_index_chunk_split_enable_env, + GRN_ENV_BUFFER_SIZE); + if (strcmp(grn_index_chunk_split_enable_env, "no") == 0) { + grn_index_chunk_split_enable = GRN_FALSE; + } else { + grn_index_chunk_split_enable = GRN_TRUE; + } + } +} + +inline static void +grn_index_column_build_call_hook(grn_ctx *ctx, grn_obj *obj, + grn_id id, grn_obj *value, int flags) +{ + grn_hook *hooks = DB_OBJ(obj)->hooks[GRN_HOOK_SET]; + + if (hooks) { + grn_obj oldvalue; + /* todo : grn_proc_ctx_open() */ + grn_obj id_, flags_; + grn_proc_ctx pctx = {{0}, hooks->proc, NULL, hooks, hooks, PROC_INIT, 4, 4}; + GRN_TEXT_INIT(&oldvalue, 0); + GRN_UINT32_INIT(&id_, 0); + GRN_UINT32_INIT(&flags_, 0); + GRN_UINT32_SET(ctx, &id_, id); + GRN_UINT32_SET(ctx, &flags_, flags); + while (hooks) { + grn_ctx_push(ctx, &id_); + grn_ctx_push(ctx, &oldvalue); + grn_ctx_push(ctx, value); + grn_ctx_push(ctx, &flags_); + pctx.caller = NULL; + pctx.currh = hooks; + if (hooks->proc) { + hooks->proc->funcs[PROC_INIT](ctx, 1, &obj, &pctx.user_data); + } else { + grn_obj_default_set_value_hook(ctx, 1, &obj, &pctx.user_data); + } + if (ctx->rc) { + grn_obj_close(ctx, &oldvalue); + return; + } + hooks = hooks->next; + pctx.offset++; + } + grn_obj_close(ctx, &oldvalue); + } +} + +grn_rc +grn_index_column_build(grn_ctx *ctx, grn_obj *index_column) +{ + grn_obj *src, **cp, **col, *target; + grn_id *s = DB_OBJ(index_column)->source; + if (!(DB_OBJ(index_column)->source_size) || !s) { return ctx->rc; } + if ((src = grn_ctx_at(ctx, *s))) { + target = GRN_OBJ_TABLEP(src) ? src : grn_ctx_at(ctx, src->header.domain); + if (target) { + int i, ncol = DB_OBJ(index_column)->source_size / sizeof(grn_id); + grn_table_flags flags; + grn_ii *ii = (grn_ii *)index_column; + grn_bool use_grn_ii_build; + grn_obj *tokenizer = NULL; + grn_table_get_info(ctx, ii->lexicon, &flags, NULL, &tokenizer, NULL, NULL); + switch (flags & GRN_OBJ_TABLE_TYPE_MASK) { + case GRN_OBJ_TABLE_PAT_KEY : + case GRN_OBJ_TABLE_DAT_KEY : + use_grn_ii_build = GRN_TRUE; + break; + default : + use_grn_ii_build = GRN_FALSE; + break; + } + if ((ii->header->flags & GRN_OBJ_WITH_WEIGHT)) { + use_grn_ii_build = GRN_FALSE; + } + if ((ii->header->flags & GRN_OBJ_WITH_POSITION) && + (!tokenizer && + !GRN_TYPE_IS_TEXT_FAMILY(ii->lexicon->header.domain))) { + /* TODO: Support offline index construction for WITH_POSITION + * index against UInt32 vector column. */ + use_grn_ii_build = GRN_FALSE; + } + if ((col = GRN_MALLOC(ncol * sizeof(grn_obj *)))) { + for (cp = col, i = ncol; i; s++, cp++, i--) { + if (!(*cp = grn_ctx_at(ctx, *s))) { + ERR(GRN_INVALID_ARGUMENT, "source invalid, n=%d",i); + GRN_FREE(col); + return ctx->rc; + } + if (GRN_OBJ_TABLEP(grn_ctx_at(ctx, DB_OBJ(*cp)->range))) { + use_grn_ii_build = GRN_FALSE; + } + } + if (use_grn_ii_build) { + if (grn_index_chunk_split_enable) { + grn_ii_build2(ctx, ii, NULL); + } else { + grn_ii_build(ctx, ii, grn_index_sparsity); + } + } else { + grn_table_cursor *tc; + if ((tc = grn_table_cursor_open(ctx, target, NULL, 0, NULL, 0, + 0, -1, GRN_CURSOR_BY_ID))) { + grn_id id; + grn_obj rv; + GRN_TEXT_INIT(&rv, 0); + while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) { + for (cp = col, i = ncol; i; i--, cp++) { + GRN_BULK_REWIND(&rv); + if (GRN_OBJ_TABLEP(*cp)) { + grn_table_get_key2(ctx, *cp, id, &rv); + } else { + grn_obj_get_value(ctx, *cp, id, &rv); + } + grn_index_column_build_call_hook(ctx, *cp, id, &rv, 0); + } + } + GRN_OBJ_FIN(ctx, &rv); + grn_table_cursor_close(ctx, tc); + } + } + GRN_FREE(col); + grn_obj_touch(ctx, index_column, NULL); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "invalid target"); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "invalid source"); + } + return ctx->rc; +} + +grn_rc +grn_index_column_rebuild(grn_ctx *ctx, grn_obj *index_column) +{ + grn_ii *ii = (grn_ii *)index_column; + + GRN_API_ENTER; + + grn_ii_truncate(ctx, ii); + grn_index_column_build(ctx, index_column); + + GRN_API_RETURN(ctx->rc); +} diff --git a/storage/mroonga/vendor/groonga/lib/io.c b/storage/mroonga/vendor/groonga/lib/io.c new file mode 100644 index 00000000..01359521 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/io.c @@ -0,0 +1,2201 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" + +#include +#include +#include +#include +#include + +#include "grn_ctx.h" +#include "grn_io.h" +#include "grn_plugin.h" +#include "grn_hash.h" +#include "grn_ctx_impl.h" +#include "grn_util.h" + +#ifdef WIN32 +# include +# include +#endif /* WIN32 */ + +#define GRN_IO_IDSTR "GROONGA:IO:00001" +#define GRN_IO_IDSTR_LEN (sizeof(GRN_IO_IDSTR) - 1) + +#define GRN_IO_VERSION_DEFAULT 1 + +#define GRN_IO_FILE_SIZE_V1 1073741824UL + +#ifdef WIN32 +# define GRN_IO_FILE_SIZE_V0 134217728L +#else /* WIN32 */ +# define GRN_IO_FILE_SIZE_V0 GRN_IO_FILE_SIZE_V1 +#endif /* WIN32 */ + +typedef struct _grn_io_fileinfo { +#ifdef WIN32 + HANDLE fh; + HANDLE fmo; + grn_critical_section cs; +#else /* WIN32 */ + int fd; + dev_t dev; + ino_t inode; +#endif /* WIN32 */ +} fileinfo; + +#define IO_HEADER_SIZE 64 + +static uint32_t grn_io_version_default = GRN_IO_VERSION_DEFAULT; +static grn_bool grn_io_use_sparse = GRN_FALSE; + +inline static grn_rc grn_fileinfo_open(grn_ctx *ctx, fileinfo *fi, + const char *path, int flags); +inline static void grn_fileinfo_init(fileinfo *fis, int nfis); +inline static int grn_fileinfo_opened(fileinfo *fi); +inline static grn_rc grn_fileinfo_close(grn_ctx *ctx, fileinfo *fi); +#ifdef WIN32 +inline static void * grn_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, HANDLE *fmo, fileinfo *fi, + off_t offset, size_t length); +inline static int grn_munmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, HANDLE *fmo, fileinfo *fi, + void *start, size_t length); +inline static int grn_msync(grn_ctx *ctx, HANDLE fh, + void *start, size_t length); +# define GRN_MMAP(ctx,owner_ctx,io,fmo,fi,offset,length)\ + (grn_mmap((ctx), (owner_ctx), (io), (fmo), (fi), (offset), (length))) +# define GRN_MUNMAP(ctx,owner_ctx,io,fmo,fi,start,length)\ + (grn_munmap((ctx), (owner_ctx), (io), (fmo), (fi), (start), (length))) +# define GRN_MSYNC(ctx,fh,start,length) \ + (grn_msync((ctx), (fh), (start), (length))) +#else /* WIN32 */ +inline static void * grn_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, fileinfo *fi, + off_t offset, size_t length); +inline static int grn_munmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, fileinfo *fi, + void *start, size_t length); +inline static int grn_msync(grn_ctx *ctx, void *start, size_t length); +# define GRN_MUNMAP(ctx,owner_ctx,io,fmo,fi,start,length) \ + (grn_munmap((ctx), (owner_ctx), (io), (fi), (start), (length))) +# define GRN_MSYNC(ctx,fh,start,length) \ + (grn_msync((ctx), (start), (length))) +# ifdef USE_FAIL_MALLOC +inline static void * grn_fail_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, + grn_io *io, fileinfo *fi, + off_t offset, size_t length, + const char* file, int line, const char *func); +# define GRN_MMAP(ctx,owner_ctx,io,fmo,fi,offset,length)\ + (grn_fail_mmap((ctx), (owner_ctx), (io), (fi), (offset), (length),\ + __FILE__, __LINE__, __FUNCTION__)) +# else /* USE_FAIL_MALLOC */ +# define GRN_MMAP(ctx,owner_ctx,io,fmo,fi,offset,length)\ + (grn_mmap((ctx), (owner_ctx), (io), (fi), (offset), (length))) +# endif /* USE_FAIL_MALLOC */ +#endif /* WIN32 */ +inline static grn_rc grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, + size_t count, off_t offset); +inline static grn_rc grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, + size_t count, off_t offset); + +void +grn_io_init_from_env(void) +{ + { + char version_env[GRN_ENV_BUFFER_SIZE]; + + grn_getenv("GRN_IO_VERSION", + version_env, + GRN_ENV_BUFFER_SIZE); + if (version_env[0]) { + grn_io_version_default = atoi(version_env); + } + } + + { + char use_sparse_env[GRN_ENV_BUFFER_SIZE]; + + grn_getenv("GRN_IO_USE_SPARSE", + use_sparse_env, + GRN_ENV_BUFFER_SIZE); + if (use_sparse_env[0] && strcmp(use_sparse_env, "yes") == 0) { + grn_io_use_sparse = GRN_TRUE; + } + } +} + +static inline uint32_t +grn_io_compute_base(uint32_t header_size) +{ + uint32_t total_header_size; + total_header_size = IO_HEADER_SIZE + header_size; + return (total_header_size + grn_pagesize - 1) & ~(grn_pagesize - 1); +} + +static inline uint32_t +grn_io_compute_base_segment(uint32_t base, uint32_t segment_size) +{ + return (base + segment_size - 1) / segment_size; +} + +static uint32_t +grn_io_compute_max_n_files(uint32_t segment_size, uint32_t max_segment, + unsigned int base_segument, unsigned long file_size) +{ + uint64_t last_segment_end; + last_segment_end = ((uint64_t)segment_size) * (max_segment + base_segument); + return (uint32_t)((last_segment_end + file_size - 1) / file_size); +} + +static inline unsigned long +grn_io_compute_file_size(uint32_t version) +{ + if (version == 0) { + return GRN_IO_FILE_SIZE_V0; + } else { + return GRN_IO_FILE_SIZE_V1; + } +} + +static inline uint32_t +grn_io_max_segment(grn_io *io) +{ + if (io->header->segment_tail) { + return io->header->segment_tail; + } else { + return io->header->max_segment; + } +} + +static uint32_t +grn_io_max_n_files(grn_io *io) +{ + unsigned long file_size; + + file_size = grn_io_compute_file_size(io->header->version); + return grn_io_compute_max_n_files(io->header->segment_size, + grn_io_max_segment(io), + io->base_seg, + file_size); +} + +static inline uint32_t +grn_io_compute_nth_file_info(grn_io *io, uint32_t nth_segment) +{ + uint32_t segment_size; + unsigned long file_size; + uint32_t segments_per_file; + uint32_t resolved_nth_segment; + + segment_size = io->header->segment_size; + file_size = grn_io_compute_file_size(io->header->version); + segments_per_file = file_size / segment_size; + resolved_nth_segment = nth_segment + io->base_seg; + return resolved_nth_segment / segments_per_file; +} + +static grn_io * +grn_io_create_tmp(grn_ctx *ctx, uint32_t header_size, uint32_t segment_size, + uint32_t max_segment, grn_io_mode mode, uint32_t flags) +{ + grn_io *io; + uint32_t b; + struct _grn_io_header *header; + b = grn_io_compute_base(header_size); + header = (struct _grn_io_header *)GRN_MMAP(ctx, &grn_gctx, NULL, NULL, NULL, + 0, b); + if (header) { + header->version = grn_io_version_default; + header->header_size = header_size; + header->segment_size = segment_size; + header->max_segment = max_segment; + header->n_arrays = 0; + header->flags = flags; + header->lock = 0; + grn_memcpy(header->idstr, GRN_IO_IDSTR, 16); + if ((io = GRN_MALLOCN(grn_io, 1))) { + grn_io_mapinfo *maps = NULL; + if ((maps = GRN_CALLOC(sizeof(grn_io_mapinfo) * max_segment))) { + io->header = header; + io->user_header = (((byte *) header) + IO_HEADER_SIZE); + io->maps = maps; + io->base = b; + io->base_seg = 0; + io->mode = mode; + io->header->curr_size = b; + io->fis = NULL; + io->ainfo = NULL; + io->max_map_seg = 0; + io->nmaps = 0; + io->count = 0; + io->flags = GRN_IO_TEMPORARY; + io->lock = &header->lock; + io->path[0] = '\0'; + return io; + } + GRN_FREE(io); + } + GRN_MUNMAP(ctx, &grn_gctx, NULL, NULL, NULL, header, b); + } + return NULL; +} + +static void +grn_io_register(grn_ctx *ctx, grn_io *io) +{ + if (io->fis && (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) { + grn_bool succeeded = GRN_FALSE; + CRITICAL_SECTION_ENTER(grn_glock); + if (grn_gctx.impl && grn_gctx.impl->ios && + grn_hash_add(&grn_gctx, grn_gctx.impl->ios, io->path, strlen(io->path), + (void **)&io, NULL)) { + succeeded = GRN_TRUE; + } + CRITICAL_SECTION_LEAVE(grn_glock); + if (!succeeded) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "grn_io_register(%s) failed", io->path); + } + } +} + +static void +grn_io_unregister(grn_ctx *ctx, grn_io *io) +{ + if (io->fis && (io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) { + grn_bool succeeded = GRN_FALSE; + CRITICAL_SECTION_ENTER(grn_glock); + if (grn_gctx.impl && grn_gctx.impl->ios) { + grn_hash_delete(&grn_gctx, grn_gctx.impl->ios, + io->path, strlen(io->path), NULL); + succeeded = GRN_TRUE; + } + CRITICAL_SECTION_LEAVE(grn_glock); + if (!succeeded) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "grn_io_unregister(%s) failed", io->path); + } + } +} + +grn_io * +grn_io_create(grn_ctx *ctx, const char *path, uint32_t header_size, + uint32_t segment_size, uint32_t max_segment, grn_io_mode mode, + uint32_t flags) +{ + grn_io *io; + fileinfo *fis; + uint32_t b, max_nfiles; + uint32_t bs; + struct _grn_io_header *header; + uint32_t version = grn_io_version_default; + unsigned long file_size; + + if (!path) { + return grn_io_create_tmp(ctx, header_size, segment_size, max_segment, + mode, flags); + } + if (!*path || (strlen(path) > PATH_MAX - 4)) { return NULL; } + b = grn_io_compute_base(header_size); + bs = grn_io_compute_base_segment(b, segment_size); + file_size = grn_io_compute_file_size(version); + max_nfiles = grn_io_compute_max_n_files(segment_size, max_segment, + bs, file_size); + if ((fis = GRN_MALLOCN(fileinfo, max_nfiles))) { + grn_fileinfo_init(fis, max_nfiles); + if (!grn_fileinfo_open(ctx, fis, path, O_RDWR|O_CREAT|O_EXCL)) { + header = (struct _grn_io_header *)GRN_MMAP(ctx, &grn_gctx, NULL, + &fis->fmo, fis, 0, b); + if (header) { + header->version = version; + header->header_size = header_size; + header->segment_size = segment_size; + header->max_segment = max_segment; + header->n_arrays = 0; + header->flags = flags; + header->lock = 0; + grn_memcpy(header->idstr, GRN_IO_IDSTR, 16); + GRN_MSYNC(ctx, fis[0].fh, header, b); + if ((io = GRN_MALLOCN(grn_io, 1))) { + grn_io_mapinfo *maps = NULL; + if ((maps = GRN_CALLOC(sizeof(grn_io_mapinfo) * max_segment))) { + grn_strncpy(io->path, PATH_MAX, path, PATH_MAX); + io->header = header; + io->user_header = (((byte *) header) + IO_HEADER_SIZE); + io->maps = maps; + io->base = b; + io->base_seg = bs; + io->mode = mode; + io->header->curr_size = b; + io->fis = fis; + io->ainfo = NULL; + io->max_map_seg = 0; + io->nmaps = 0; + io->count = 0; + io->flags = flags; + io->lock = &header->lock; + grn_io_register(ctx, io); + return io; + } + GRN_FREE(io); + } + GRN_MUNMAP(ctx, &grn_gctx, NULL, &fis->fmo, fis, header, b); + } + grn_fileinfo_close(ctx, fis); + if (grn_unlink(path) == 0) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][create][error] removed path: <%s>", path); + } else { + ERRNO_ERR("[io][create][error] failed to remove path: <%s>", path); + } + } + GRN_FREE(fis); + } + return NULL; +} + +static grn_rc +array_init_(grn_ctx *ctx, grn_io *io, int n_arrays, size_t hsize, size_t msize) +{ + int i; + uint32_t ws; + byte *hp, *mp; + grn_io_array_spec *array_specs = (grn_io_array_spec *)io->user_header; + hp = io->user_header; + if (!(mp = GRN_CALLOC(msize))) { + return GRN_NO_MEMORY_AVAILABLE; + } + io->ainfo = (grn_io_array_info *)mp; + hp += sizeof(grn_io_array_spec) * n_arrays; + mp += sizeof(grn_io_array_info) * n_arrays; + for (ws = 0; (1 << ws) < io->header->segment_size; ws++); + for (i = 0; i < n_arrays; i++) { + uint32_t we = ws - array_specs[i].w_of_element; + io->ainfo[i].w_of_elm_in_a_segment = we; + io->ainfo[i].elm_mask_in_a_segment = (1 << we) - 1; + io->ainfo[i].max_n_segments = array_specs[i].max_n_segments; + io->ainfo[i].element_size = 1 << array_specs[i].w_of_element; + io->ainfo[i].segments = (uint32_t *)hp; + io->ainfo[i].addrs = (void **)mp; + hp += sizeof(uint32_t) * array_specs[i].max_n_segments; + mp += sizeof(void *) * array_specs[i].max_n_segments; + } + io->user_header += hsize; + return GRN_SUCCESS; +} + +static grn_rc +array_init(grn_ctx *ctx, grn_io *io, int n_arrays) +{ + if (n_arrays) { + int i; + grn_io_array_spec *array_specs = (grn_io_array_spec *)io->user_header; + size_t hsize = sizeof(grn_io_array_spec) * n_arrays; + size_t msize = sizeof(grn_io_array_info) * n_arrays; + for (i = 0; i < n_arrays; i++) { + hsize += sizeof(uint32_t) * array_specs[i].max_n_segments; + msize += sizeof(void *) * array_specs[i].max_n_segments; + } + return array_init_(ctx, io, n_arrays, hsize, msize); + } + return GRN_SUCCESS; +} + +grn_io * +grn_io_create_with_array(grn_ctx *ctx, const char *path, + uint32_t header_size, uint32_t segment_size, + grn_io_mode mode, int n_arrays, + grn_io_array_spec *array_specs) +{ + if (n_arrays) { + int i; + grn_io *io; + byte *hp; + uint32_t nsegs = 0; + size_t hsize = sizeof(grn_io_array_spec) * n_arrays; + size_t msize = sizeof(grn_io_array_info) * n_arrays; + for (i = 0; i < n_arrays; i++) { + nsegs += array_specs[i].max_n_segments; + hsize += sizeof(uint32_t) * array_specs[i].max_n_segments; + msize += sizeof(void *) * array_specs[i].max_n_segments; + } + if ((io = grn_io_create(ctx, path, header_size + hsize, + segment_size, nsegs, mode, GRN_IO_EXPIRE_GTICK))) { + grn_rc rc; + hp = io->user_header; + grn_memcpy(hp, array_specs, sizeof(grn_io_array_spec) * n_arrays); + io->header->n_arrays = n_arrays; + io->header->segment_tail = 1; + rc = array_init_(ctx, io, n_arrays, hsize, msize); + if (rc == GRN_SUCCESS) { + return io; + } + ERR(GRN_NO_MEMORY_AVAILABLE, "grn_io_create_with_array failed"); + grn_io_close(ctx, io); + } + } + return NULL; +} + +inline static uint32_t +segment_alloc(grn_ctx *ctx, grn_io *io) +{ + uint32_t n, s; + grn_io_array_info *ai; + if (io->header->segment_tail) { + if (io->header->segment_tail > io->header->max_segment) { + s = 0; + } else { + s = io->header->segment_tail++; + } + } else { + char *used = GRN_CALLOC(io->header->max_segment + 1); + if (!used) { return 0; } + for (n = io->header->n_arrays, ai = io->ainfo; n; n--, ai++) { + for (s = 0; s < ai->max_n_segments; s++) { + used[ai->segments[s]] = 1; + } + } + for (s = 1; ; s++) { + if (s > io->header->max_segment) { + io->header->segment_tail = s; + s = 0; + break; + } + if (!used[s]) { + io->header->segment_tail = s + 1; + break; + } + } + GRN_FREE(used); + } + return s; +} + +void +grn_io_segment_alloc(grn_ctx *ctx, grn_io *io, grn_io_array_info *ai, + uint32_t lseg, int *flags, void **p) +{ + uint32_t *sp = &ai->segments[lseg]; + if (!*sp) { + if ((*flags & GRN_TABLE_ADD)) { + if ((*sp = segment_alloc(ctx, io))) { + *flags |= GRN_TABLE_ADDED; + } + } + } + if (*sp) { + uint32_t pseg = *sp - 1; + GRN_IO_SEG_REF(io, pseg, *p); + if (*p) { GRN_IO_SEG_UNREF(io, pseg); }; + } +} + +void * +grn_io_array_at(grn_ctx *ctx, grn_io *io, uint32_t array, off_t offset, int *flags) +{ + void *res; + GRN_IO_ARRAY_AT(io,array,offset,flags,res); + return res; +} + +uint32_t +grn_io_detect_type(grn_ctx *ctx, const char *path) +{ + struct _grn_io_header h; + uint32_t res = 0; + int fd; + grn_open(fd, path, O_RDONLY | GRN_OPEN_FLAG_BINARY); + if (fd != -1) { + struct stat s; + if (fstat(fd, &s) != -1 && s.st_size >= sizeof(struct _grn_io_header)) { + if (grn_read(fd, &h, sizeof(struct _grn_io_header)) == + sizeof(struct _grn_io_header)) { + if (!memcmp(h.idstr, GRN_IO_IDSTR, GRN_IO_IDSTR_LEN)) { + res = h.type; + } else { + ERR(GRN_INCOMPATIBLE_FILE_FORMAT, + "failed to detect type: format ID is different: <%s>: <%.*s>", + path, + (int)GRN_IO_IDSTR_LEN, GRN_IO_IDSTR); + } + } else { + SERR("failed to read enough data for detecting type: <%s>", + path); + } + } else { + ERR(GRN_INVALID_FORMAT, "grn_io_detect_type failed"); + } + grn_close(fd); + } else { + ERRNO_ERR("failed to open path for detecting type: <%s>", + path); + } + return res; +} + +grn_io * +grn_io_open(grn_ctx *ctx, const char *path, grn_io_mode mode) +{ + size_t max_path_len = PATH_MAX - 4; + grn_io *io; + struct stat s; + fileinfo fi; + uint32_t flags = 0; + uint32_t b; + uint32_t header_size = 0, segment_size = 0, max_segment = 0, bs; + if (!path || !*path) { + ERR(GRN_INVALID_ARGUMENT, "[io][open] path is missing"); + return NULL; + } + if ((strlen(path) > max_path_len)) { + int truncate_length = 10; + ERR(GRN_INVALID_ARGUMENT, + "[io][open] path is too long: " + "<%" GRN_FMT_SIZE ">(max: %" GRN_FMT_SIZE "): <%.*s...>", + strlen(path), + max_path_len, + truncate_length, + path); + return NULL; + } + { + struct _grn_io_header h; + int fd; + ssize_t read_bytes; + grn_open(fd, path, O_RDWR | GRN_OPEN_FLAG_BINARY); + if (fd == -1) { + ERRNO_ERR("failed to open path: <%s>", + path); + return NULL; + } + if (fstat(fd, &s) == -1) { + ERRNO_ERR("[io][open] failed to file status: <%s>", + path); + grn_close(fd); + return NULL; + } + if (s.st_size < sizeof(struct _grn_io_header)) { + ERR(GRN_INCOMPATIBLE_FILE_FORMAT, + "[io][open] file size is too small: " + "<%" GRN_FMT_INT64D ">(required: >= %" GRN_FMT_SIZE "): <%s>", + (int64_t)(s.st_size), + sizeof(struct _grn_io_header), + path); + grn_close(fd); + return NULL; + } + read_bytes = grn_read(fd, &h, sizeof(struct _grn_io_header)); + if (read_bytes != sizeof(struct _grn_io_header)) { + ERRNO_ERR("[io][open] failed to read header data: " + "<%" GRN_FMT_SSIZE ">(expected: %" GRN_FMT_SSIZE "): <%s>", + read_bytes, + sizeof(struct _grn_io_header), + path); + grn_close(fd); + return NULL; + } + if (memcmp(h.idstr, GRN_IO_IDSTR, GRN_IO_IDSTR_LEN) != 0) { + ERR(GRN_INCOMPATIBLE_FILE_FORMAT, + "failed to open: format ID is different: <%s>: <%.*s>", + path, + (int)GRN_IO_IDSTR_LEN, GRN_IO_IDSTR); + grn_close(fd); + return NULL; + } + header_size = h.header_size; + segment_size = h.segment_size; + max_segment = h.max_segment; + flags = h.flags; + grn_close(fd); + if (segment_size == 0) { + ERR(GRN_INCOMPATIBLE_FILE_FORMAT, "failed to open: segment size is 0"); + return NULL; + } + } + b = grn_io_compute_base(header_size); + bs = grn_io_compute_base_segment(b, segment_size); + grn_fileinfo_init(&fi, 1); + if (!grn_fileinfo_open(ctx, &fi, path, O_RDWR)) { + struct _grn_io_header *header; + header = GRN_MMAP(ctx, &grn_gctx, NULL, &(fi.fmo), &fi, 0, b); + if (header) { + unsigned long file_size; + unsigned int max_nfiles; + fileinfo *fis; + + file_size = grn_io_compute_file_size(header->version); + max_nfiles = grn_io_compute_max_n_files(segment_size, max_segment, + bs, file_size); + fis = GRN_MALLOCN(fileinfo, max_nfiles); + if (!fis) { + GRN_MUNMAP(ctx, &grn_gctx, NULL, &(fi.fmo), &fi, header, b); + grn_fileinfo_close(ctx, &fi); + return NULL; + } + grn_fileinfo_init(fis, max_nfiles); + grn_memcpy(fis, &fi, sizeof(fileinfo)); + if ((io = GRN_MALLOC(sizeof(grn_io)))) { + grn_io_mapinfo *maps = NULL; + if ((maps = GRN_CALLOC(sizeof(grn_io_mapinfo) * max_segment))) { + grn_strncpy(io->path, PATH_MAX, path, PATH_MAX); + io->header = header; + io->user_header = (((byte *) header) + IO_HEADER_SIZE); + { + io->maps = maps; + io->base = b; + io->base_seg = bs; + io->mode = mode; + io->fis = fis; + io->ainfo = NULL; + io->max_map_seg = 0; + io->nmaps = 0; + io->count = 0; + io->flags = header->flags; + io->lock = &header->lock; + if (!array_init(ctx, io, io->header->n_arrays)) { + grn_io_register(ctx, io); + return io; + } + } + if (io->maps) { GRN_FREE(io->maps); } + } + GRN_FREE(io); + } + GRN_FREE(fis); + GRN_MUNMAP(ctx, &grn_gctx, NULL, &(fi.fmo), &fi, header, b); + } + grn_fileinfo_close(ctx, &fi); + } + return NULL; +} + +grn_rc +grn_io_close(grn_ctx *ctx, grn_io *io) +{ + uint32_t max_nfiles; + + max_nfiles = grn_io_max_n_files(io); + grn_io_unregister(ctx, io); + if (io->ainfo) { GRN_FREE(io->ainfo); } + if (io->maps) { + int i; + uint32_t max_segment; + uint32_t segment_size; + unsigned long file_size; + uint32_t segments_per_file; + + max_segment = grn_io_max_segment(io); + segment_size = io->header->segment_size; + file_size = grn_io_compute_file_size(io->header->version); + segments_per_file = file_size / segment_size; + for (i = 0; i < max_segment; i++) { + grn_io_mapinfo *mi; + mi = &(io->maps[i]); + if (mi->map) { + fileinfo *fi = NULL; + /* if (atomic_read(mi->nref)) { return STILL_IN_USE ; } */ + if (io->fis) { + uint32_t bseg = i + io->base_seg; + uint32_t fno = bseg / segments_per_file; + fi = &io->fis[fno]; + } + GRN_MUNMAP(ctx, &grn_gctx, io, &mi->fmo, fi, mi->map, segment_size); + } + } + GRN_FREE(io->maps); + } + GRN_MUNMAP(ctx, &grn_gctx, io, (io->fis ? &io->fis->fmo : NULL), + io->fis, io->header, io->base); + if (io->fis) { + int i; + for (i = 0; i < max_nfiles; i++) { + fileinfo *fi = &(io->fis[i]); + grn_fileinfo_close(ctx, fi); + } + GRN_FREE(io->fis); + } + GRN_FREE(io); + return GRN_SUCCESS; +} + +uint32_t +grn_io_base_seg(grn_io *io) +{ + return io->base_seg; +} + +const char * +grn_io_path(grn_io *io) +{ + return io->path; +} + +void * +grn_io_header(grn_io *io) +{ + return io->user_header; +} + +grn_rc +grn_io_set_type(grn_io *io, uint32_t type) +{ + if (!io || !io->header) { + return GRN_INVALID_ARGUMENT; + } + io->header->type = type; + return GRN_SUCCESS; +} + +uint32_t +grn_io_get_type(grn_io *io) +{ + if (!io || !io->header) { return GRN_VOID; } + return io->header->type; +} + +inline static void +gen_pathname(const char *path, char *buffer, int fno) +{ + size_t len = strlen(path); + grn_memcpy(buffer, path, len); + if (fno) { + buffer[len] = '.'; + grn_itoh(fno, buffer + len + 1, 3); + buffer[len + 4] = '\0'; + } else { + buffer[len] = '\0'; + } +} + +static uint32_t +grn_io_n_files(grn_ctx *ctx, grn_io *io) +{ + unsigned long file_size; + file_size = grn_io_compute_file_size(io->header->version); + return ((io->header->curr_size + file_size - 1) / file_size); +} + +grn_rc +grn_io_size(grn_ctx *ctx, grn_io *io, uint64_t *size) +{ + int fno; + struct stat s; + uint64_t tsize = 0; + char buffer[PATH_MAX]; + uint32_t n_files; + + n_files = grn_io_n_files(ctx, io); + for (fno = 0; fno < n_files; fno++) { + gen_pathname(io->path, buffer, fno); + if (stat(buffer, &s)) { + SERR("failed to stat path to compute size: <%s>", + buffer); + } else { + tsize += s.st_size; + } + } + *size = tsize; + return GRN_SUCCESS; +} + +grn_rc +grn_io_remove_raw(grn_ctx *ctx, const char *path) +{ + grn_rc rc = GRN_SUCCESS; + int fno; + char buffer[PATH_MAX]; + + if (grn_unlink(path) != 0) { + ERRNO_ERR("[io][remove] failed to remove path: <%s>", + path); + return ctx->rc; + } + GRN_LOG(ctx, GRN_LOG_INFO, "[io][remove] removed path: <%s>", path); + + for (fno = 1; ; fno++) { + struct stat s; + gen_pathname(path, buffer, fno); + if (stat(buffer, &s) != 0) { + break; + } + if (grn_unlink(buffer) == 0) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][remove] removed numbered path: <%d>: <%s>", fno, buffer); + } else { + ERRNO_ERR("[io][remove] failed to remove numbered path: <%d>: <%s>", + fno, buffer); + rc = ctx->rc; + } + } + return rc; +} + +grn_rc +grn_io_remove(grn_ctx *ctx, const char *path) +{ + struct stat s; + + if (stat(path, &s) != 0) { + SERR("failed to stat: <%s>", path); + return ctx->rc; + } + + return grn_io_remove_raw(ctx, path); +} + +grn_rc +grn_io_remove_if_exist(grn_ctx *ctx, const char *path) +{ + struct stat s; + if (stat(path, &s) == 0) { + return grn_io_remove_raw(ctx, path); + } + return GRN_SUCCESS; +} + +grn_rc +grn_io_rename(grn_ctx *ctx, const char *old_name, const char *new_name) +{ + struct stat s; + if (stat(old_name, &s)) { + SERR("failed to stat path to be renamed: <%s>", old_name); + return ctx->rc; + } else if (rename(old_name, new_name)) { + SERR("failed to rename path: <%s> -> <%s>", + old_name, new_name); + return ctx->rc; + } else { + int fno; + char old_buffer[PATH_MAX]; + char new_buffer[PATH_MAX]; + for (fno = 1; ; fno++) { + gen_pathname(old_name, old_buffer, fno); + if (!stat(old_buffer, &s)) { + gen_pathname(new_name, new_buffer, fno); + if (rename(old_buffer, new_buffer)) { + SERR("failed to rename path: <%s> -> <%s>", + old_buffer, new_buffer); + } + } else { + SERR("failed to stat path to be renamed: <%s>", + old_buffer); + return ctx->rc; + } + } + return GRN_SUCCESS; + } +} + +typedef struct { + grn_io_ja_ehead head; + char body[256]; +} ja_element; + +grn_rc +grn_io_read_ja(grn_io *io, grn_ctx *ctx, grn_io_ja_einfo *einfo, uint32_t epos, + uint32_t key, uint32_t segment, uint32_t offset, void **value, + uint32_t *value_len) +{ + uint32_t rest = 0, size = *value_len + sizeof(grn_io_ja_ehead); + uint32_t segment_size = io->header->segment_size; + unsigned long file_size = grn_io_compute_file_size(io->header->version); + uint32_t segments_per_file = file_size / segment_size; + uint32_t bseg = segment + io->base_seg; + int fno = bseg / segments_per_file; + fileinfo *fi = &io->fis[fno]; + off_t base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg; + off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base; + ja_element *v = GRN_MALLOC(size); + if (!v) { + *value = NULL; + *value_len = 0; + return GRN_NO_MEMORY_AVAILABLE; + } + if (pos + size > file_size) { + rest = pos + size - file_size; + size = file_size - pos; + } + if (!grn_fileinfo_opened(fi)) { + char path[PATH_MAX]; + gen_pathname(io->path, path, fno); + if (grn_fileinfo_open(ctx, fi, path, O_RDWR|O_CREAT)) { + *value = NULL; + *value_len = 0; + GRN_FREE(v); + return ctx->rc; + } + } + if (grn_pread(ctx, fi, v, size, pos)) { + *value = NULL; + *value_len = 0; + GRN_FREE(v); + return ctx->rc; + } + if (einfo->pos != epos) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "einfo pos changed %x => %x", einfo->pos, epos); + *value = NULL; + *value_len = 0; + GRN_FREE(v); + return GRN_FILE_CORRUPT; + } + if (einfo->size != *value_len) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "einfo size changed %d => %d", einfo->size, *value_len); + *value = NULL; + *value_len = 0; + GRN_FREE(v); + return GRN_FILE_CORRUPT; + } + if (v->head.key != key) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "ehead key unmatch %x => %x", key, v->head.key); + *value = NULL; + *value_len = 0; + GRN_FREE(v); + return GRN_INVALID_FORMAT; + } + if (v->head.size != *value_len) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "ehead size unmatch %d => %d", *value_len, v->head.size); + *value = NULL; + *value_len = 0; + GRN_FREE(v); + return GRN_INVALID_FORMAT; + } + if (rest) { + byte *vr = (byte *)v + size; + do { + fi = &io->fis[++fno]; + if (!grn_fileinfo_opened(fi)) { + char path[PATH_MAX]; + gen_pathname(io->path, path, fno); + if (grn_fileinfo_open(ctx, fi, path, O_RDWR|O_CREAT)) { + *value = NULL; + *value_len = 0; + GRN_FREE(v); + return ctx->rc; + } + } + size = rest > file_size ? file_size : rest; + if (grn_pread(ctx, fi, vr, size, 0)) { + *value = NULL; + *value_len = 0; + GRN_FREE(v); + return ctx->rc; + } + vr += size; + rest -= size; + } while (rest); + } + *value = v->body; + return GRN_SUCCESS; +} + +grn_rc +grn_io_write_ja(grn_io *io, grn_ctx *ctx, uint32_t key, + uint32_t segment, uint32_t offset, void *value, + uint32_t value_len) +{ + grn_rc rc; + uint32_t rest = 0, size = value_len + sizeof(grn_io_ja_ehead); + uint32_t segment_size = io->header->segment_size; + unsigned long file_size = grn_io_compute_file_size(io->header->version); + uint32_t segments_per_file = file_size / segment_size; + uint32_t bseg = segment + io->base_seg; + int fno = bseg / segments_per_file; + fileinfo *fi = &io->fis[fno]; + off_t base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg; + off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base; + if (pos + size > file_size) { + rest = pos + size - file_size; + size = file_size - pos; + } + if (!grn_fileinfo_opened(fi)) { + char path[PATH_MAX]; + gen_pathname(io->path, path, fno); + if ((rc = grn_fileinfo_open(ctx, fi, path, O_RDWR|O_CREAT))) { return rc; } + } + if (value_len <= 256) { + ja_element je; + je.head.size = value_len; + je.head.key = key; + grn_memcpy(je.body, value, value_len); + rc = grn_pwrite(ctx, fi, &je, size, pos); + } else { + grn_io_ja_ehead eh; + eh.size = value_len; + eh.key = key; + if ((rc = grn_pwrite(ctx, fi, &eh, sizeof(grn_io_ja_ehead), pos))) { + return rc; + } + pos += sizeof(grn_io_ja_ehead); + rc = grn_pwrite(ctx, fi, value, size - sizeof(grn_io_ja_ehead), pos); + } + if (rc) { return rc; } + if (rest) { + byte *vr = (byte *)value + size - sizeof(grn_io_ja_ehead); + do { + fi = &io->fis[++fno]; + if (!grn_fileinfo_opened(fi)) { + char path[PATH_MAX]; + gen_pathname(io->path, path, fno); + if ((rc = grn_fileinfo_open(ctx, fi, path, O_RDWR|O_CREAT))) { + return rc; + } + } + size = rest > file_size ? file_size : rest; + if ((rc = grn_pwrite(ctx, fi, vr, size, 0))) { return rc; } + vr += size; + rest -= size; + } while (rest); + } + return rc; +} + +grn_rc +grn_io_write_ja_ehead(grn_io *io, grn_ctx *ctx, uint32_t key, + uint32_t segment, uint32_t offset, uint32_t value_len) +{ + grn_rc rc; + uint32_t segment_size = io->header->segment_size; + unsigned long file_size = grn_io_compute_file_size(io->header->version); + uint32_t segments_per_file = file_size / segment_size; + uint32_t bseg = segment + io->base_seg; + int fno = bseg / segments_per_file; + fileinfo *fi = &io->fis[fno]; + off_t base = fno ? 0 : io->base - (uint64_t)segment_size + io->base_seg; + off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + offset + base; + if (!grn_fileinfo_opened(fi)) { + char path[PATH_MAX]; + gen_pathname(io->path, path, fno); + if ((rc = grn_fileinfo_open(ctx, fi, path, O_RDWR|O_CREAT))) { return rc; } + } + { + grn_io_ja_ehead eh; + eh.size = value_len; + eh.key = key; + return grn_pwrite(ctx, fi, &eh, sizeof(grn_io_ja_ehead), pos); + } +} + +void * +grn_io_win_map(grn_io *io, grn_ctx *ctx, grn_io_win *iw, uint32_t segment, + uint32_t offset, uint32_t size, grn_io_rw_mode mode) +{ + uint32_t nseg, segment_size = io->header->segment_size; + if (offset >= segment_size) { + segment += offset / segment_size; + offset = offset % segment_size; + } + nseg = (offset + size + segment_size - 1) / segment_size; + if (!size || !ctx || segment + nseg > io->header->max_segment) { + return NULL; + } + iw->ctx = ctx; + iw->diff = 0; + iw->io = io; + iw->mode = mode; + iw->tiny_p = 0; + iw->segment = segment; + iw->offset = offset; + iw->nseg = nseg; + iw->size = size; + if (nseg == 1) { + byte *addr = NULL; + GRN_IO_SEG_REF(io, segment, addr); + if (!addr) { return NULL; } + iw->cached = 1; + iw->addr = addr + offset; + } else { + if (!(iw->addr = GRN_MALLOC(size))) { return NULL; } + iw->cached = 0; + switch (mode) { + case grn_io_rdonly: + case grn_io_rdwr: + { + byte *p, *q = NULL; + uint32_t s, r; + for (p = iw->addr, r = size; r; p += s, r -= s, segment++, offset = 0) { + GRN_IO_SEG_REF(io, segment, q); + if (!q) { + GRN_FREE(iw->addr); + return NULL; + } + s = (offset + r > segment_size) ? segment_size - offset : r; + grn_memcpy(p, q + offset, s); + GRN_IO_SEG_UNREF(io, segment); + } + } + break; + case grn_io_wronly: + break; + default : + return NULL; + } + } + return iw->addr; +} + +grn_rc +grn_io_win_unmap(grn_io_win *iw) +{ + if (!iw || !iw->io ||!iw->ctx) { return GRN_INVALID_ARGUMENT; } + if (iw->cached) { + if (!iw->tiny_p) { GRN_IO_SEG_UNREF(iw->io, iw->segment); } + return GRN_SUCCESS; + } + { + grn_io *io = iw->io; + grn_ctx *ctx = iw->ctx; + switch (iw->mode) { + case grn_io_rdonly: + if (!iw->addr) { return GRN_INVALID_ARGUMENT; } + GRN_FREE(iw->addr); + return GRN_SUCCESS; + case grn_io_rdwr: + case grn_io_wronly: + { + byte *p, *q = NULL; + uint32_t segment_size = io->header->segment_size; + uint32_t s, r, offset = iw->offset, segment = iw->segment; + for (p = iw->addr, r = iw->size; r; + p += s, r -= s, segment++, offset = 0) { + GRN_IO_SEG_REF(io, segment, q); + if (!q) { return GRN_NO_MEMORY_AVAILABLE; } + s = (offset + r > segment_size) ? segment_size - offset : r; + grn_memcpy(q + offset, p, s); + GRN_IO_SEG_UNREF(io, segment); + } + } + GRN_FREE(iw->addr); + return GRN_SUCCESS; + default : + return GRN_INVALID_ARGUMENT; + } + } +} + +#define DO_MAP(io,fmo,fi,pos,size,segno,res) do {\ + (res) = GRN_MMAP(ctx, &grn_gctx, (io), (fmo), (fi), (pos), (size));\ + if ((res)) {\ + uint32_t nmaps;\ + if (io->max_map_seg < segno) { io->max_map_seg = segno; }\ + GRN_ATOMIC_ADD_EX(&io->nmaps, 1, nmaps);\ + {\ + uint64_t tail = io->base + (uint64_t)(size) * ((segno) + 1);\ + if (tail > io->header->curr_size) { io->header->curr_size = tail; }\ + }\ + }\ +} while (0) + +void +grn_io_seg_map_(grn_ctx *ctx, grn_io *io, uint32_t segno, grn_io_mapinfo *info) +{ + uint32_t segment_size = io->header->segment_size; + if ((io->flags & GRN_IO_TEMPORARY)) { + DO_MAP(io, &info->fmo, NULL, 0, segment_size, segno, info->map); + } else { + unsigned long file_size = grn_io_compute_file_size(io->header->version); + uint32_t segments_per_file = file_size / segment_size; + uint32_t bseg = segno + io->base_seg; + uint32_t fno = bseg / segments_per_file; + off_t base = fno ? 0 : io->base - (uint64_t)segment_size * io->base_seg; + off_t pos = (uint64_t)segment_size * (bseg % segments_per_file) + base; + fileinfo *fi = &io->fis[fno]; + if (!grn_fileinfo_opened(fi)) { + char path[PATH_MAX]; + grn_bool path_exist = GRN_TRUE; + gen_pathname(io->path, path, fno); + path_exist = grn_path_exist(path); + if (!grn_fileinfo_open(ctx, fi, path, O_RDWR|O_CREAT)) { + DO_MAP(io, &info->fmo, fi, pos, segment_size, segno, info->map); + if (!info->map && !path_exist) { + if (grn_unlink(path) == 0) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][map][error] memory mapping is failed and then " + "removed created map file: <%s>", path); + } else { + ERRNO_ERR("[io][map][error] memory mapping is failed and then " + "failed to remove created map file: <%s>", path); + } + } + } + } else { + DO_MAP(io, &info->fmo, fi, pos, segment_size, segno, info->map); + } + } +} + +grn_rc +grn_io_seg_expire(grn_ctx *ctx, grn_io *io, uint32_t segno, uint32_t nretry) +{ + uint32_t retry, *pnref; + grn_io_mapinfo *info; + if (!io->maps || segno >= io->header->max_segment) { return GRN_INVALID_ARGUMENT; } + info = &io->maps[segno]; + if (!info->map) { return GRN_INVALID_ARGUMENT; } + pnref = &info->nref; + for (retry = 0;; retry++) { + uint32_t nref; + GRN_ATOMIC_ADD_EX(pnref, 1, nref); + if (nref) { + GRN_ATOMIC_ADD_EX(pnref, -1, nref); + if (retry >= GRN_IO_MAX_RETRY) { + GRN_LOG(ctx, GRN_LOG_CRIT, + "deadlock detected! in grn_io_seg_expire(%p, %u, %u)", + io, segno, nref); + return GRN_RESOURCE_DEADLOCK_AVOIDED; + } + } else { + GRN_ATOMIC_ADD_EX(pnref, GRN_IO_MAX_REF, nref); + if (nref > 1) { + GRN_ATOMIC_ADD_EX(pnref, -(GRN_IO_MAX_REF + 1), nref); + GRN_FUTEX_WAKE(pnref); + if (retry >= GRN_IO_MAX_RETRY) { + GRN_LOG(ctx, GRN_LOG_CRIT, + "deadlock detected!! in grn_io_seg_expire(%p, %u, %u)", + io, segno, nref); + return GRN_RESOURCE_DEADLOCK_AVOIDED; + } + } else { + uint32_t nmaps; + fileinfo *fi = &(io->fis[segno]); + GRN_MUNMAP(ctx, &grn_gctx, io, &info->fmo, fi, + info->map, io->header->segment_size); + info->map = NULL; + GRN_ATOMIC_ADD_EX(pnref, -(GRN_IO_MAX_REF + 1), nref); + GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps); + GRN_FUTEX_WAKE(pnref); + return GRN_SUCCESS; + } + } + if (retry >= nretry) { return GRN_RESOURCE_DEADLOCK_AVOIDED; } + GRN_FUTEX_WAIT(pnref); + } +} + +uint32_t +grn_io_expire(grn_ctx *ctx, grn_io *io, int count_thresh, uint32_t limit) +{ + uint32_t m, n = 0, ln = io->nmaps; + switch ((io->flags & (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT))) { + case GRN_IO_EXPIRE_GTICK : + { + uint32_t nref, nmaps, *pnref = &io->nref; + GRN_ATOMIC_ADD_EX(pnref, 1, nref); + if (!nref && grn_gtick - io->count > count_thresh) { + { + uint32_t i = io->header->n_arrays; + grn_io_array_spec *array_specs = (grn_io_array_spec *)io->user_header; + while (i--) { + memset(io->ainfo[i].addrs, 0, + sizeof(void *) * array_specs[i].max_n_segments); + } + } + { + uint32_t fno; + for (fno = 0; fno < io->max_map_seg; fno++) { + grn_io_mapinfo *info = &(io->maps[fno]); + if (info->map) { + fileinfo *fi = &(io->fis[fno]); + GRN_MUNMAP(ctx, &grn_gctx, io, &info->fmo, fi, + info->map, io->header->segment_size); + info->map = NULL; + info->nref = 0; + info->count = grn_gtick; + GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps); + n++; + } + } + } + } + GRN_ATOMIC_ADD_EX(pnref, -1, nref); + } + break; + case GRN_IO_EXPIRE_SEGMENT : + for (m = io->max_map_seg; n < limit && m; m--) { + if (!grn_io_seg_expire(ctx, io, m, 0)) { n++; } + } + break; + case (GRN_IO_EXPIRE_GTICK|GRN_IO_EXPIRE_SEGMENT) : + { + grn_io_mapinfo *info = io->maps; + for (m = io->max_map_seg; n < limit && m; info++, m--) { + if (info->map && (grn_gtick - info->count) > count_thresh) { + uint32_t nmaps, nref, *pnref = &info->nref; + GRN_ATOMIC_ADD_EX(pnref, 1, nref); + if (!nref && info->map && (grn_gtick - info->count) > count_thresh) { + GRN_MUNMAP(ctx, &grn_gctx, io, &info->fmo, NULL, + info->map, io->header->segment_size); + GRN_ATOMIC_ADD_EX(&io->nmaps, -1, nmaps); + info->map = NULL; + info->count = grn_gtick; + n++; + } + GRN_ATOMIC_ADD_EX(pnref, -1, nref); + } + } + } + break; + } + if (n) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "<%p:%x> expired i=%p max=%d (%d/%d)", + ctx, grn_gtick, io, io->max_map_seg, n, ln); + } + return n; +} + +void * +grn_io_anon_map(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length) +{ + return (mi->map = GRN_MMAP(ctx, ctx, NULL, &mi->fmo, NULL, 0, length)); +} + +void +grn_io_anon_unmap(grn_ctx *ctx, grn_io_mapinfo *mi, size_t length) +{ + GRN_MUNMAP(ctx, ctx, NULL, &mi->fmo, NULL, mi->map, length); +} + +grn_rc +grn_io_lock(grn_ctx *ctx, grn_io *io, int timeout) +{ + static int _ncalls = 0, _ncolls = 0; + uint32_t count, count_log_border = 1000; + uint32_t rc_check_interval = 1000; + _ncalls++; + if (!io) { return GRN_INVALID_ARGUMENT; } + for (count = 0;; count++) { + uint32_t lock; + GRN_ATOMIC_ADD_EX(io->lock, 1, lock); + if (lock) { + GRN_ATOMIC_ADD_EX(io->lock, -1, lock); + if (count == count_log_border) { + GRN_LOG(ctx, GRN_LOG_NOTICE, + "io(%s) collisions(%d/%d): lock failed %d times", + io->path, _ncolls, _ncalls, count_log_border); + } + if (!timeout || (timeout > 0 && timeout == count)) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "[DB Locked] time out(%d): io(%s) collisions(%d/%d)", + timeout, io->path, _ncolls, _ncalls); + break; + } + if (!(++_ncolls % 1000000) && (_ncolls > _ncalls)) { + if (_ncolls < 0 || _ncalls < 0) { + _ncolls = 0; _ncalls = 0; + } else { + GRN_LOG(ctx, GRN_LOG_NOTICE, + "io(%s) collisions(%d/%d)", io->path, _ncolls, _ncalls); + } + } + if ((count % rc_check_interval) == 0) { + if (ctx->rc != GRN_SUCCESS) { + return ctx->rc; + } + } + grn_nanosleep(GRN_LOCK_WAIT_TIME_NANOSECOND); + continue; + } + return GRN_SUCCESS; + } + ERR(GRN_RESOURCE_DEADLOCK_AVOIDED, "grn_io_lock failed"); + return ctx->rc; +} + +void +grn_io_unlock(grn_io *io) +{ + if (io) { + uint32_t lock; + GRN_ATOMIC_ADD_EX(io->lock, -1, lock); + } +} + +void +grn_io_clear_lock(grn_io *io) +{ + if (io) { *io->lock = 0; } +} + +uint32_t +grn_io_is_locked(grn_io *io) +{ + return io ? *io->lock : 0; +} + +grn_rc +grn_io_flush(grn_ctx *ctx, grn_io *io) +{ + grn_rc rc = GRN_SUCCESS; + struct _grn_io_header *header; + uint32_t aligned_header_size; + + if (io->path[0] == '\0') { + return GRN_SUCCESS; + } + + header = io->header; + aligned_header_size = grn_io_compute_base(header->header_size); + + if (GRN_MSYNC(ctx, io->fis[0].fh, header, aligned_header_size) != 0) { + return ctx->rc; + } + + if (io->maps) { + uint32_t i; + uint32_t max_mapped_segment; + uint32_t segment_size; + + max_mapped_segment = grn_io_max_segment(io); + segment_size = header->segment_size; + for (i = 0; i < max_mapped_segment; i++) { + grn_io_mapinfo *info = &(io->maps[i]); + uint32_t nth_file_info; + uint32_t *pnref; + uint32_t nref; + int msync_result; + + if (!info) { + continue; + } + + pnref = &info->nref; + GRN_ATOMIC_ADD_EX(pnref, 1, nref); + if (nref != 0) { + GRN_ATOMIC_ADD_EX(pnref, -1, nref); + continue; + } + + if (!info->map) { + GRN_ATOMIC_ADD_EX(pnref, -1, nref); + GRN_FUTEX_WAKE(pnref); + continue; + } + + nth_file_info = grn_io_compute_nth_file_info(io, i); + msync_result = GRN_MSYNC(ctx, + io->fis[nth_file_info].fh, + info->map, + segment_size); + GRN_ATOMIC_ADD_EX(pnref, -1, nref); + GRN_FUTEX_WAKE(pnref); + + if (msync_result != 0) { + rc = ctx->rc; + break; + } + } + } + + return rc; +} + +grn_bool +grn_io_is_corrupt(grn_ctx *ctx, grn_io *io) +{ + uint32_t i; + uint32_t n_files; + + if (!io) { + return GRN_FALSE; + } + + n_files = grn_io_n_files(ctx, io); + for (i = 0; i < n_files; i++) { + char path[PATH_MAX]; + struct stat s; + gen_pathname(io->path, path, i); + if (stat(path, &s) != 0) { + SERR("[io][corrupt] used path doesn't exist: <%s>", + path); + return GRN_TRUE; + } + } + + return GRN_FALSE; +} + +size_t +grn_io_get_disk_usage(grn_ctx *ctx, grn_io *io) +{ + size_t usage = 0; + uint32_t i; + uint32_t n_files; + + if (!io) { + return usage; + } + + n_files = grn_io_n_files(ctx, io); + for (i = 0; i < n_files; i++) { + char path[PATH_MAX]; + struct stat s; + gen_pathname(io->path, path, i); + if (stat(path, &s) != 0) { + continue; + } + usage += s.st_size; + } + + return usage; +} + +/** mmap abstraction **/ + +static size_t mmap_size = 0; + +#ifdef WIN32 + +inline static grn_rc +grn_fileinfo_open_v1(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) +{ + CRITICAL_SECTION_INIT(fi->cs); + return GRN_SUCCESS; +} + +inline static void * +grn_mmap_v1(grn_ctx *ctx, grn_ctx *owner_ctx, HANDLE *fmo, fileinfo *fi, + off_t offset, size_t length) +{ + void *res; + if (!fi) { + if (fmo) { + *fmo = NULL; + } + /* TODO: Try to support VirtualAlloc() as anonymous mmap in POSIX. + * If VirtualAlloc() provides better performance rather than malloc(), + * we'll use it. + */ + return GRN_CALLOC(length); + } + /* CRITICAL_SECTION_ENTER(fi->cs); */ + /* try to create fmo */ + *fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, offset + length, NULL); + if (!*fmo) { + SERR("CreateFileMapping(%lu + %" GRN_FMT_SIZE ") failed " + "<%" GRN_FMT_SIZE ">", + (DWORD)offset, length, + mmap_size); + return NULL; + } + res = MapViewOfFile(*fmo, FILE_MAP_WRITE, 0, (DWORD)offset, (SIZE_T)length); + if (!res) { + SERR("MapViewOfFile(%lu,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + (DWORD)offset, length, mmap_size); + return NULL; + } + /* CRITICAL_SECTION_LEAVE(fi->cs); */ + mmap_size += length; + return res; +} + +inline static int +grn_munmap_v1(grn_ctx *ctx, grn_ctx *owner_ctx, HANDLE *fmo, fileinfo *fi, + void *start, size_t length) +{ + int r = 0; + + if (!fi) { + GRN_FREE(start); + return r; + } + + if (!fmo) { + GRN_FREE(start); + return r; + } + + if (*fmo) { + if (UnmapViewOfFile(start)) { + mmap_size -= length; + } else { + SERR("UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + start, length, mmap_size); + r = -1; + } + if (!CloseHandle(*fmo)) { + SERR("CloseHandle(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + start, length, mmap_size); + } + *fmo = NULL; + } else { + GRN_FREE(start); + } + + return r; +} + +inline static grn_rc +grn_fileinfo_open_v0(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) +{ + /* signature may be wrong.. */ + fi->fmo = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, NULL); + /* open failed */ + if (fi->fmo == NULL) { + // flock + /* retry to open */ + fi->fmo = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, NULL); + /* failed again */ + if (fi->fmo == NULL) { + /* try to create fmo */ + fi->fmo = CreateFileMapping(fi->fh, NULL, PAGE_READWRITE, 0, + GRN_IO_FILE_SIZE_V0, NULL); + } + // funlock + } + if (fi->fmo != NULL) { + if (GetLastError() != ERROR_ALREADY_EXISTS) { + CRITICAL_SECTION_INIT(fi->cs); + return GRN_SUCCESS; + } else { + GRN_LOG(ctx, GRN_LOG_ERROR, + "fmo object already exists! handle=%p", fi->fh); + CloseHandle(fi->fmo); + } + } else { + GRN_LOG(ctx, GRN_LOG_ALERT, + "failed to get FileMappingObject #%lu", GetLastError()); + } + CloseHandle(fi->fh); + SERR("OpenFileMapping"); + return ctx->rc; +} + +inline static void * +grn_mmap_v0(grn_ctx *ctx, grn_ctx *owner_ctx, fileinfo *fi, off_t offset, + size_t length) +{ + void *res; + if (!fi) { return GRN_CALLOC(length); } + /* file must be exceeded to GRN_IO_FILE_SIZE_V0 when FileMappingObject created. + and, after fmo created, it's not allowed to expand the size of file. + DWORD tail = (DWORD)(offset + length); + DWORD filesize = GetFileSize(fi->fh, NULL); + if (filesize < tail) { + if (SetFilePointer(fi->fh, tail, NULL, FILE_BEGIN) != tail) { + grn_log("SetFilePointer failed"); + return NULL; + } + if (!SetEndOfFile(fi->fh)) { + grn_log("SetEndOfFile failed"); + return NULL; + } + filesize = tail; + } + */ + res = MapViewOfFile(fi->fmo, FILE_MAP_WRITE, 0, (DWORD)offset, (SIZE_T)length); + if (!res) { + MERR("MapViewOfFile failed: <%" GRN_FMT_SIZE ">: %s", + mmap_size, grn_current_error_message()); + return NULL; + } + mmap_size += length; + return res; +} + +inline static int +grn_munmap_v0(grn_ctx *ctx, grn_ctx *owner_ctx, fileinfo *fi, void *start, + size_t length) +{ + if (!fi) { + GRN_FREE(start); + return 0; + } + + if (UnmapViewOfFile(start)) { + mmap_size -= length; + return 0; + } else { + SERR("UnmapViewOfFile(%p,%" GRN_FMT_SIZE ") failed <%" GRN_FMT_SIZE ">", + start, length, mmap_size); + return -1; + } +} + +inline static grn_rc +grn_fileinfo_open_common(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) +{ + /* may be wrong if flags is just only O_RDWR */ + if ((flags & O_CREAT)) { + DWORD dwCreationDisposition; + const char *flags_description; + if (flags & O_EXCL) { + dwCreationDisposition = CREATE_NEW; + flags_description = "O_RDWR|O_CREAT|O_EXCL"; + } else { + dwCreationDisposition = OPEN_ALWAYS; + flags_description = "O_RDWR|O_CREAT"; + } + fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, 0); + if (fi->fh == INVALID_HANDLE_VALUE) { + SERR("CreateFile(<%s>, <%s>) failed", + path, flags_description); + goto exit; + } + + switch (dwCreationDisposition) { + case CREATE_NEW : + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] create new file: <%s>", path); + break; + case OPEN_ALWAYS : + if (GetLastError() == ERROR_ALREADY_EXISTS) { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] open existing file because it exists: <%s>", path); + } else { + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] create new file because it doesn't exist: <%s>", + path); + } + break; + default : + break; + } + + if (grn_io_use_sparse) { + FILE_SET_SPARSE_BUFFER buffer; + buffer.SetSparse = TRUE; + DWORD returned_bytes; + if (!DeviceIoControl(fi->fh, + FSCTL_SET_SPARSE, + &buffer, + sizeof(FILE_SET_SPARSE_BUFFER), + NULL, + 0, + &returned_bytes, + NULL)) { + GRN_LOG(ctx, GRN_LOG_INFO, + "Tried to make file sparse but failed: " + "DeviceIoControl(FSCTL_SET_SPARSE): " + "<%s>: <%s>", + path, grn_current_error_message()); + } + } + + goto exit; + } + + if ((flags & O_TRUNC)) { + CloseHandle(fi->fh); + /* unable to assign OPEN_ALWAYS and TRUNCATE_EXISTING at once */ + fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (fi->fh == INVALID_HANDLE_VALUE) { + SERR("CreateFile(<%s>, ) failed", + path); + goto exit; + } + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] truncated: <%s>", path); + goto exit; + } + /* O_RDWR only */ + fi->fh = CreateFile(path, GRN_IO_FILE_CREATE_MODE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (fi->fh == INVALID_HANDLE_VALUE) { + SERR("CreateFile(<%s>, ) failed", + path); + goto exit; + } + GRN_LOG(ctx, GRN_LOG_INFO, + "[io][open] open existing file: <%s>", path); + +exit : + return ctx->rc; +} + +inline static grn_rc +grn_fileinfo_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) +{ + grn_rc rc; + struct _grn_io_header io_header; + LARGE_INTEGER file_size; + int version = grn_io_version_default; + + rc = grn_fileinfo_open_common(ctx, fi, path, flags); + if (rc != GRN_SUCCESS) { + if (fi->fh) { + CloseHandle(fi->fh); + fi->fh = INVALID_HANDLE_VALUE; + } + return rc; + } + + if (GetFileSizeEx(fi->fh, &file_size) && file_size.QuadPart > 0) { + DWORD header_size; + DWORD read_bytes; + header_size = sizeof(struct _grn_io_header); + ReadFile(fi->fh, &io_header, header_size, &read_bytes, NULL); + if (read_bytes == header_size) { + version = io_header.version; + } + SetFilePointer(fi->fh, 0, NULL, FILE_BEGIN); + } + + if (version == 0) { + return grn_fileinfo_open_v0(ctx, fi, path, flags); + } else { + return grn_fileinfo_open_v1(ctx, fi, path, flags); + } +} + +inline static int +grn_guess_io_version(grn_ctx *ctx, grn_io *io, fileinfo *fi) +{ + if (io) { + return io->header->version; + } + + if (fi) { + if (fi->fmo) { + return 0; + } else { + return 1; + } + } + + return grn_io_version_default; +} + +inline static void * +grn_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, HANDLE *fmo, + fileinfo *fi, off_t offset, size_t length) +{ + int version; + + version = grn_guess_io_version(ctx, io, fi); + + if (version == 0) { + return grn_mmap_v0(ctx, owner_ctx, fi, offset, length); + } else { + return grn_mmap_v1(ctx, owner_ctx, fmo, fi, offset, length); + } +} + +inline static int +grn_munmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, + HANDLE *fmo, fileinfo *fi, void *start, size_t length) +{ + int version; + + version = grn_guess_io_version(ctx, io, fi); + + if (version == 0) { + return grn_munmap_v0(ctx, owner_ctx, fi, start, length); + } else { + return grn_munmap_v1(ctx, owner_ctx, fmo, fi, start, length); + } +} + +inline static grn_rc +grn_fileinfo_close(grn_ctx *ctx, fileinfo *fi) +{ + if (fi->fmo != NULL) { + CloseHandle(fi->fmo); + fi->fmo = NULL; + } + if (fi->fh != INVALID_HANDLE_VALUE) { + CloseHandle(fi->fh); + CRITICAL_SECTION_FIN(fi->cs); + fi->fh = INVALID_HANDLE_VALUE; + } + return GRN_SUCCESS; +} + +inline static void +grn_fileinfo_init(fileinfo *fis, int nfis) +{ + for (; nfis--; fis++) { + fis->fh = INVALID_HANDLE_VALUE; + fis->fmo = NULL; + } +} + +inline static int +grn_fileinfo_opened(fileinfo *fi) +{ + return fi->fh != INVALID_HANDLE_VALUE; +} + +inline static int +grn_msync(grn_ctx *ctx, HANDLE handle, void *start, size_t length) +{ + BOOL succeeded; + SYSTEMTIME system_time; + FILETIME file_time; + + succeeded = FlushViewOfFile(start, length); + if (!succeeded) { + SERR("FlushViewOfFile(<%p>, <%" GRN_FMT_SIZE ">) failed", + start, length); + return -1; + } + + if (handle == INVALID_HANDLE_VALUE) { + return 0; + } + + GetSystemTime(&system_time); + succeeded = SystemTimeToFileTime(&system_time, &file_time); + if (!succeeded) { + SERR("SystemTimeToFileTime(<%04u-%02u-%02uT%02u:%02u:%02u.%03u>) failed", + system_time.wYear, + system_time.wMonth, + system_time.wDay, + system_time.wHour, + system_time.wMinute, + system_time.wSecond, + system_time.wMilliseconds); + return -1; + } + + succeeded = SetFileTime(handle, NULL, NULL, &file_time); + if (!succeeded) { + SERR("SetFileTime(<%p>, <%p>, <%" GRN_FMT_SIZE ">) failed", + handle, start, length); + return -1; + } + + return 0; +} + +inline static grn_rc +grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset) +{ + DWORD r, len; + CRITICAL_SECTION_ENTER(fi->cs); + r = SetFilePointer(fi->fh, offset, NULL, FILE_BEGIN); + if (r == INVALID_SET_FILE_POINTER) { + SERR("SetFilePointer"); + } else { + if (!ReadFile(fi->fh, buf, (DWORD)count, &len, NULL)) { + SERR("ReadFile"); + } else if (len != count) { + /* todo : should retry ? */ + ERR(GRN_INPUT_OUTPUT_ERROR, + "ReadFile %" GRN_FMT_SIZE " != %lu", + count, len); + } + } + CRITICAL_SECTION_LEAVE(fi->cs); + return ctx->rc; +} + +inline static grn_rc +grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset) +{ + DWORD r, len; + CRITICAL_SECTION_ENTER(fi->cs); + r = SetFilePointer(fi->fh, offset, NULL, FILE_BEGIN); + if (r == INVALID_SET_FILE_POINTER) { + SERR("SetFilePointer"); + } else { + if (!WriteFile(fi->fh, buf, (DWORD)count, &len, NULL)) { + SERR("WriteFile"); + } else if (len != count) { + /* todo : should retry ? */ + ERR(GRN_INPUT_OUTPUT_ERROR, + "WriteFile %" GRN_FMT_SIZE " != %lu", + count, len); + } + } + CRITICAL_SECTION_LEAVE(fi->cs); + return ctx->rc; +} + +#else /* WIN32 */ + +inline static grn_rc +grn_fileinfo_open(grn_ctx *ctx, fileinfo *fi, const char *path, int flags) +{ + struct stat st; + grn_open(fi->fd, path, flags); + if (fi->fd == -1) { + ERRNO_ERR("failed to open file info path: <%s>", + path); + return ctx->rc; + } + if (fstat(fi->fd, &st) == -1) { + ERRNO_ERR("failed to stat file info path: <%s>", + path); + return ctx->rc; + } + fi->dev = st.st_dev; + fi->inode = st.st_ino; + return GRN_SUCCESS; +} + +inline static void +grn_fileinfo_init(fileinfo *fis, int nfis) +{ + for (; nfis--; fis++) { fis->fd = -1; } +} + +inline static int +grn_fileinfo_opened(fileinfo *fi) +{ + return fi->fd != -1; +} + +inline static grn_rc +grn_fileinfo_close(grn_ctx *ctx, fileinfo *fi) +{ + if (fi->fd != -1) { + if (grn_close(fi->fd) == -1) { + SERR("close"); + return ctx->rc; + } + fi->fd = -1; + } + return GRN_SUCCESS; +} + +#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) +#define MAP_ANONYMOUS MAP_ANON +#endif + +#include + +inline static void * +grn_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, fileinfo *fi, + off_t offset, size_t length) +{ + void *res; + int fd, flags; + if (fi) { + struct stat s; + off_t tail = offset + length; + fd = fi->fd; + if ((fstat(fd, &s) == -1) || (s.st_size < tail && ftruncate(fd, tail) == -1)) { + SERR("fstat"); + return NULL; + } + flags = MAP_SHARED; + } else { + fd = -1; + flags = MAP_PRIVATE|MAP_ANONYMOUS; + } + res = mmap(NULL, length, PROT_READ|PROT_WRITE, flags, fd, offset); + if (MAP_FAILED == res) { + MERR("mmap(%" GRN_FMT_LLU ",%d,%" GRN_FMT_LLD ")=%s <%" GRN_FMT_LLU ">", + (unsigned long long int)length, fd, (long long int)offset, + strerror(errno), (unsigned long long int)mmap_size); + return NULL; + } + mmap_size += length; + return res; +} + +#ifdef USE_FAIL_MALLOC +inline static void * +grn_fail_mmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, fileinfo *fi, + off_t offset, size_t length, + const char* file, int line, const char *func) +{ + if (grn_fail_malloc_check(length, file, line, func)) { + return grn_mmap(ctx, io, fi, offset, length); + } else { + MERR("fail_mmap(%" GRN_FMT_SIZE ",%d,%" GRN_FMT_LLU ") " + "(%s:%d@%s) <%" GRN_FMT_SIZE ">", + length, + fi ? fi->fd : 0, + (long long unsigned int)offset, + file, + line, + func, + mmap_size); + return NULL; + } +} +#endif /* USE_FAIL_MALLOC */ + +inline static int +grn_msync(grn_ctx *ctx, void *start, size_t length) +{ + int r = msync(start, length, MS_SYNC); + if (r == -1) { SERR("msync"); } + return r; +} + +inline static int +grn_munmap(grn_ctx *ctx, grn_ctx *owner_ctx, grn_io *io, fileinfo *fi, + void *start, size_t length) +{ + int res; + res = munmap(start, length); + if (res) { + SERR("munmap(%p,%" GRN_FMT_LLU ") failed <%" GRN_FMT_LLU ">", + start, + (unsigned long long int)length, + (unsigned long long int)mmap_size); + } else { + mmap_size -= length; + } + return res; +} + +inline static grn_rc +grn_pread(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset) +{ + ssize_t r = pread(fi->fd, buf, count, offset); + if (r != count) { + if (r == -1) { + SERR("pread"); + } else { + /* todo : should retry ? */ + ERR(GRN_INPUT_OUTPUT_ERROR, + "pread returned %" GRN_FMT_LLD " != %" GRN_FMT_LLU, + (long long int)r, (unsigned long long int)count); + } + return ctx->rc; + } + return GRN_SUCCESS; +} + +inline static grn_rc +grn_pwrite(grn_ctx *ctx, fileinfo *fi, void *buf, size_t count, off_t offset) +{ + ssize_t r = pwrite(fi->fd, buf, count, offset); + if (r != count) { + if (r == -1) { + SERR("pwrite"); + } else { + /* todo : should retry ? */ + ERR(GRN_INPUT_OUTPUT_ERROR, + "pwrite returned %" GRN_FMT_LLD " != %" GRN_FMT_LLU, + (long long int)r, (unsigned long long int)count); + } + return ctx->rc; + } + return GRN_SUCCESS; +} + +#endif /* WIN32 */ diff --git a/storage/mroonga/vendor/groonga/lib/load.c b/storage/mroonga/vendor/groonga/lib/load.c new file mode 100644 index 00000000..b840a0dc --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/load.c @@ -0,0 +1,1229 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_load.h" +#include "grn_ctx_impl.h" +#include "grn_db.h" +#include "grn_util.h" + +static void +grn_loader_save_error(grn_ctx *ctx, grn_loader *loader) +{ + loader->rc = ctx->rc; + grn_strcpy(loader->errbuf, GRN_CTX_MSGSIZE, ctx->errbuf); +} + +static grn_obj * +values_add(grn_ctx *ctx, grn_loader *loader) +{ + grn_obj *res; + uint32_t curr_size = loader->values_size * sizeof(grn_obj); + if (curr_size < GRN_TEXT_LEN(&loader->values)) { + res = (grn_obj *)(GRN_TEXT_VALUE(&loader->values) + curr_size); + res->header.domain = GRN_DB_TEXT; + GRN_BULK_REWIND(res); + } else { + if (grn_bulk_space(ctx, &loader->values, sizeof(grn_obj))) { return NULL; } + res = (grn_obj *)(GRN_TEXT_VALUE(&loader->values) + curr_size); + GRN_TEXT_INIT(res, 0); + } + loader->values_size++; + loader->last = res; + return res; +} + +static grn_obj * +values_next(grn_ctx *ctx, grn_obj *value) +{ + if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET || + value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) { + value += GRN_UINT32_VALUE(value); + } + return value + 1; +} + +static int +values_len(grn_ctx *ctx, grn_obj *head, grn_obj *tail) +{ + int len; + for (len = 0; head < tail; head = values_next(ctx, head), len++) ; + return len; +} + +static grn_id +loader_add(grn_ctx *ctx, grn_obj *key) +{ + int added = 0; + grn_loader *loader = &ctx->impl->loader; + grn_id id = grn_table_add_by_key(ctx, loader->table, key, &added); + if (id == GRN_ID_NIL) { + grn_loader_save_error(ctx, loader); + return id; + } + if (!added && loader->ifexists) { + grn_obj *v = grn_expr_get_var_by_offset(ctx, loader->ifexists, 0); + grn_obj *result; + GRN_RECORD_SET(ctx, v, id); + result = grn_expr_exec(ctx, loader->ifexists, 0); + if (!grn_obj_is_true(ctx, result)) { + id = 0; + } + } + return id; +} + +static void +add_weight_vector(grn_ctx *ctx, + grn_obj *column, + grn_obj *value, + grn_obj *vector) +{ + unsigned int i, n; + grn_obj weight_buffer; + + n = GRN_UINT32_VALUE(value); + GRN_UINT32_INIT(&weight_buffer, 0); + for (i = 0; i < n; i += 2) { + grn_rc rc; + grn_obj *key, *weight; + + key = value + 1 + i; + weight = key + 1; + + GRN_BULK_REWIND(&weight_buffer); + rc = grn_obj_cast(ctx, weight, &weight_buffer, GRN_TRUE); + if (rc != GRN_SUCCESS) { + grn_obj *range; + range = grn_ctx_at(ctx, weight_buffer.header.domain); + ERR_CAST(column, range, weight); + grn_obj_unlink(ctx, range); + break; + } + grn_vector_add_element(ctx, + vector, + GRN_BULK_HEAD(key), + GRN_BULK_VSIZE(key), + GRN_UINT32_VALUE(&weight_buffer), + key->header.domain); + } + GRN_OBJ_FIN(ctx, &weight_buffer); +} + +static void +set_vector(grn_ctx *ctx, grn_obj *column, grn_id id, grn_obj *vector) +{ + int n = GRN_UINT32_VALUE(vector); + grn_obj buf, *v = vector + 1; + grn_id range_id; + grn_obj *range; + + range_id = DB_OBJ(column)->range; + range = grn_ctx_at(ctx, range_id); + if (grn_obj_is_table(ctx, range)) { + GRN_RECORD_INIT(&buf, GRN_OBJ_VECTOR, range_id); + while (n--) { + grn_bool cast_failed = GRN_FALSE; + grn_obj record, *element = v; + if (range_id != element->header.domain) { + GRN_RECORD_INIT(&record, 0, range_id); + if (grn_obj_cast(ctx, element, &record, GRN_TRUE)) { + cast_failed = GRN_TRUE; + ERR_CAST(column, range, element); + } + element = &record; + } + if (!cast_failed) { + GRN_UINT32_PUT(ctx, &buf, GRN_RECORD_VALUE(element)); + } + if (element == &record) { GRN_OBJ_FIN(ctx, element); } + v = values_next(ctx, v); + } + } else { + if (((struct _grn_type *)range)->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) { + GRN_TEXT_INIT(&buf, GRN_OBJ_VECTOR); + while (n--) { + switch (v->header.domain) { + case GRN_DB_TEXT : + { + grn_bool cast_failed = GRN_FALSE; + grn_obj casted_element, *element = v; + if (range_id != element->header.domain) { + GRN_OBJ_INIT(&casted_element, GRN_BULK, 0, range_id); + if (grn_obj_cast(ctx, element, &casted_element, GRN_TRUE)) { + cast_failed = GRN_TRUE; + ERR_CAST(column, range, element); + } + element = &casted_element; + } + if (!cast_failed) { + grn_vector_add_element(ctx, &buf, + GRN_TEXT_VALUE(element), + GRN_TEXT_LEN(element), + 0, + element->header.domain); + } + if (element == &casted_element) { GRN_OBJ_FIN(ctx, element); } + break; + } + case GRN_JSON_LOAD_OPEN_BRACE : + add_weight_vector(ctx, column, v, &buf); + n -= GRN_UINT32_VALUE(v); + break; + default : + ERR(GRN_INVALID_ARGUMENT, "array must contain string or object"); + break; + } + v = values_next(ctx, v); + } + } else { + grn_id value_size = ((grn_db_obj *)range)->range; + GRN_VALUE_FIX_SIZE_INIT(&buf, GRN_OBJ_VECTOR, range_id); + while (n--) { + grn_bool cast_failed = GRN_FALSE; + grn_obj casted_element, *element = v; + if (range_id != element->header.domain) { + GRN_OBJ_INIT(&casted_element, GRN_BULK, 0, range_id); + if (grn_obj_cast(ctx, element, &casted_element, GRN_TRUE)) { + cast_failed = GRN_TRUE; + ERR_CAST(column, range, element); + } + element = &casted_element; + } + if (!cast_failed) { + grn_bulk_write(ctx, &buf, GRN_TEXT_VALUE(element), value_size); + } + if (element == &casted_element) { GRN_OBJ_FIN(ctx, element); } + v = values_next(ctx, v); + } + } + } + grn_obj_set_value(ctx, column, id, &buf, GRN_OBJ_SET); + GRN_OBJ_FIN(ctx, &buf); +} + +static void +set_weight_vector(grn_ctx *ctx, grn_obj *column, grn_id id, grn_obj *value) +{ + if (!grn_obj_is_weight_vector_column(ctx, column)) { + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + column_name_size = grn_obj_name(ctx, column, column_name, + GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_INVALID_ARGUMENT, + "<%.*s>: columns except weight vector column don't support object value", + column_name_size, column_name); + return; + } + + { + grn_obj vector; + + GRN_TEXT_INIT(&vector, GRN_OBJ_VECTOR); + add_weight_vector(ctx, column, value, &vector); + grn_obj_set_value(ctx, column, id, &vector, GRN_OBJ_SET); + GRN_OBJ_FIN(ctx, &vector); + } +} + +static inline int +name_equal(const char *p, unsigned int size, const char *name) +{ + if (strlen(name) != size) { return 0; } + if (*p != GRN_DB_PSEUDO_COLUMN_PREFIX) { return 0; } + return !memcmp(p + 1, name + 1, size - 1); +} + +static void +report_set_column_value_failure(grn_ctx *ctx, + grn_obj *key, + const char *column_name, + unsigned int column_name_size, + grn_obj *column_value) +{ + grn_obj key_inspected, column_value_inspected; + + GRN_TEXT_INIT(&key_inspected, 0); + GRN_TEXT_INIT(&column_value_inspected, 0); + grn_inspect_limited(ctx, &key_inspected, key); + grn_inspect_limited(ctx, &column_value_inspected, column_value); + GRN_LOG(ctx, GRN_LOG_ERROR, + "[table][load] failed to set column value: %s: " + "key: <%.*s>, column: <%.*s>, value: <%.*s>", + ctx->errbuf, + (int)GRN_TEXT_LEN(&key_inspected), + GRN_TEXT_VALUE(&key_inspected), + column_name_size, + column_name, + (int)GRN_TEXT_LEN(&column_value_inspected), + GRN_TEXT_VALUE(&column_value_inspected)); + GRN_OBJ_FIN(ctx, &key_inspected); + GRN_OBJ_FIN(ctx, &column_value_inspected); +} + +static grn_id +parse_id_value(grn_ctx *ctx, grn_obj *value) +{ + switch (value->header.type) { + case GRN_DB_UINT32 : + return GRN_UINT32_VALUE(value); + case GRN_DB_INT32 : + return GRN_INT32_VALUE(value); + default : + { + grn_id id = GRN_ID_NIL; + grn_obj casted_value; + GRN_UINT32_INIT(&casted_value, 0); + if (grn_obj_cast(ctx, value, &casted_value, GRN_FALSE) != GRN_SUCCESS) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, value); + ERR(GRN_INVALID_ARGUMENT, + "<%s>: failed to cast to : <%.*s>", + GRN_COLUMN_NAME_ID, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + } else { + id = GRN_UINT32_VALUE(&casted_value); + } + GRN_OBJ_FIN(ctx, &casted_value); + return id; + } + } +} + +static void +bracket_close(grn_ctx *ctx, grn_loader *loader) +{ + grn_id id = GRN_ID_NIL; + grn_obj *value, *value_end, *id_value = NULL, *key_value = NULL; + grn_obj *col, **cols; /* Columns except _id and _key. */ + uint32_t i, begin; + uint32_t ncols; /* Number of columns except _id and _key. */ + uint32_t nvalues; /* Number of values in brackets. */ + uint32_t depth; + grn_bool is_record_load = GRN_FALSE; + + cols = (grn_obj **)GRN_BULK_HEAD(&loader->columns); + ncols = GRN_BULK_VSIZE(&loader->columns) / sizeof(grn_obj *); + GRN_UINT32_POP(&loader->level, begin); + value = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + begin; + value_end = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + loader->values_size; + GRN_ASSERT(value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET); + GRN_UINT32_SET(ctx, value, loader->values_size - begin - 1); + value++; + depth = GRN_BULK_VSIZE(&loader->level); + if (depth > sizeof(uint32_t) * loader->emit_level) { + return; + } + if (depth == 0 || !loader->table || + loader->columns_status == GRN_LOADER_COLUMNS_BROKEN) { + goto exit; + } + nvalues = values_len(ctx, value, value_end); + + if (loader->columns_status == GRN_LOADER_COLUMNS_UNSET) { + /* + * Target columns and _id or _key are not specified yet and values are + * handled as column names and "_id" or "_key". + */ + for (i = 0; i < nvalues; i++) { + const char *col_name; + unsigned int col_name_size; + if (value->header.domain != GRN_DB_TEXT) { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_inspect(ctx, &buffer, value); + ERR(GRN_INVALID_ARGUMENT, + "column name must be string: <%.*s>", + (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + grn_loader_save_error(ctx, loader); + GRN_OBJ_FIN(ctx, &buffer); + loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; + goto exit; + } + col_name = GRN_TEXT_VALUE(value); + col_name_size = GRN_TEXT_LEN(value); + col = grn_obj_column(ctx, loader->table, col_name, col_name_size); + if (!col) { + ERR(GRN_INVALID_ARGUMENT, "nonexistent column: <%.*s>", + col_name_size, col_name); + grn_loader_save_error(ctx, loader); + loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; + goto exit; + } + if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_ID)) { + grn_obj_unlink(ctx, col); + if (loader->id_offset != -1 || loader->key_offset != -1) { + /* _id and _key must not appear more than once. */ + if (loader->id_offset != -1) { + ERR(GRN_INVALID_ARGUMENT, + "duplicated id and key columns: <%s> at %d and <%s> at %d", + GRN_COLUMN_NAME_ID, i, + GRN_COLUMN_NAME_ID, loader->id_offset); + } else { + ERR(GRN_INVALID_ARGUMENT, + "duplicated id and key columns: <%s> at %d and <%s> at %d", + GRN_COLUMN_NAME_ID, i, + GRN_COLUMN_NAME_KEY, loader->key_offset); + } + grn_loader_save_error(ctx, loader); + loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; + goto exit; + } + loader->id_offset = i; + } else if (name_equal(col_name, col_name_size, GRN_COLUMN_NAME_KEY)) { + grn_obj_unlink(ctx, col); + if (loader->id_offset != -1 || loader->key_offset != -1) { + /* _id and _key must not appear more than once. */ + if (loader->id_offset != -1) { + ERR(GRN_INVALID_ARGUMENT, + "duplicated id and key columns: <%s> at %d and <%s> at %d", + GRN_COLUMN_NAME_KEY, i, + GRN_COLUMN_NAME_ID, loader->id_offset); + } else { + ERR(GRN_INVALID_ARGUMENT, + "duplicated id and key columns: <%s> at %d and <%s> at %d", + GRN_COLUMN_NAME_KEY, i, + GRN_COLUMN_NAME_KEY, loader->key_offset); + } + grn_loader_save_error(ctx, loader); + loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; + goto exit; + } + loader->key_offset = i; + } else { + GRN_PTR_PUT(ctx, &loader->columns, col); + } + value++; + } + switch (loader->table->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + if (loader->id_offset == -1 && loader->key_offset == -1) { + ERR(GRN_INVALID_ARGUMENT, "missing id or key column"); + grn_loader_save_error(ctx, loader); + loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; + goto exit; + } + break; + } + loader->columns_status = GRN_LOADER_COLUMNS_SET; + goto exit; + } + + is_record_load = GRN_TRUE; + + /* Target columns and _id or _key are already specified. */ + if (!nvalues) { + /* + * Accept empty arrays because a dump command may output a load command + * which contains empty arrays for a table with deleted records. + */ + id = grn_table_add(ctx, loader->table, NULL, 0, NULL); + } else { + uint32_t expected_nvalues = ncols; + if (loader->id_offset != -1 || loader->key_offset != -1) { + expected_nvalues++; + } + if (nvalues != expected_nvalues) { + ERR(GRN_INVALID_ARGUMENT, + "unexpected #values: expected:%u, actual:%u", + expected_nvalues, nvalues); + grn_loader_save_error(ctx, loader); + goto exit; + } + if (loader->id_offset != -1) { + id_value = value + loader->id_offset; + id = parse_id_value(ctx, id_value); + if (grn_table_at(ctx, loader->table, id) == GRN_ID_NIL) { + id = grn_table_add(ctx, loader->table, NULL, 0, NULL); + } + } else if (loader->key_offset != -1) { + key_value = value + loader->key_offset; + id = loader_add(ctx, key_value); + } else { + id = grn_table_add(ctx, loader->table, NULL, 0, NULL); + } + } + if (id == GRN_ID_NIL) { + /* Target record is not available. */ + goto exit; + } + + for (i = 0; i < nvalues; i++, value = values_next(ctx, value)) { + if (i == loader->id_offset || i == loader->key_offset) { + /* Skip _id and _key, because it's already used to get id. */ + continue; + } + col = *cols; + if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) { + set_vector(ctx, col, id, value); + } else if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) { + set_weight_vector(ctx, col, id, value); + } else { + grn_obj_set_value(ctx, col, id, value, GRN_OBJ_SET); + } + if (ctx->rc != GRN_SUCCESS) { + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int column_name_size; + grn_loader_save_error(ctx, loader); + column_name_size = grn_obj_name(ctx, col, column_name, + GRN_TABLE_MAX_KEY_SIZE); + report_set_column_value_failure(ctx, key_value, + column_name, column_name_size, + value); + ERRCLR(ctx); + } + cols++; + } + if (loader->each) { + grn_obj *v = grn_expr_get_var_by_offset(ctx, loader->each, 0); + GRN_RECORD_SET(ctx, v, id); + grn_expr_exec(ctx, loader->each, 0); + } + loader->nrecords++; +exit: + if (is_record_load) { + if (loader->output_ids) { + GRN_UINT32_PUT(ctx, &(loader->ids), id); + } + if (loader->output_errors) { + GRN_INT32_PUT(ctx, &(loader->return_codes), ctx->rc); + grn_vector_add_element(ctx, + &(loader->error_messages), + ctx->errbuf, + strlen(ctx->errbuf), + 0, + GRN_DB_TEXT); + } + } + loader->values_size = begin; + ERRCLR(ctx); +} + +static void +brace_close(grn_ctx *ctx, grn_loader *loader) +{ + grn_id id = GRN_ID_NIL; + grn_obj *value, *value_begin, *value_end; + grn_obj *id_value = NULL, *key_value = NULL; + uint32_t begin; + + GRN_UINT32_POP(&loader->level, begin); + value_begin = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + begin; + value_end = (grn_obj *)GRN_TEXT_VALUE(&loader->values) + loader->values_size; + GRN_ASSERT(value->header.domain == GRN_JSON_LOAD_OPEN_BRACE); + GRN_UINT32_SET(ctx, value_begin, loader->values_size - begin - 1); + value_begin++; + if (GRN_BULK_VSIZE(&loader->level) > sizeof(uint32_t) * loader->emit_level) { + return; + } + if (!loader->table) { + goto exit; + } + + /* Scan values to find _id or _key. */ + for (value = value_begin; value + 1 < value_end; + value = values_next(ctx, value)) { + const char *name = GRN_TEXT_VALUE(value); + unsigned int name_size = GRN_TEXT_LEN(value); + if (value->header.domain != GRN_DB_TEXT) { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_inspect(ctx, &buffer, value); + GRN_LOG(ctx, GRN_LOG_ERROR, + "column name must be string: <%.*s>", + (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + goto exit; + } + value++; + if (name_equal(name, name_size, GRN_COLUMN_NAME_ID)) { + if (id_value || key_value) { + if (loader->table->header.type == GRN_TABLE_NO_KEY) { + GRN_LOG(ctx, GRN_LOG_ERROR, "duplicated '_id' column"); + goto exit; + } else { + GRN_LOG(ctx, GRN_LOG_ERROR, + "duplicated key columns: %s and %s", + id_value ? GRN_COLUMN_NAME_ID : GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_ID); + goto exit; + } + } + id_value = value; + } else if (name_equal(name, name_size, GRN_COLUMN_NAME_KEY)) { + if (id_value || key_value) { + GRN_LOG(ctx, GRN_LOG_ERROR, + "duplicated key columns: %s and %s", + id_value ? GRN_COLUMN_NAME_ID : GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY); + goto exit; + } + key_value = value; + } + } + + switch (loader->table->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + /* The target table requires _id or _key. */ + if (!id_value && !key_value) { + GRN_LOG(ctx, GRN_LOG_ERROR, "neither _key nor _id is assigned"); + goto exit; + } + break; + default : + /* The target table does not have _key. */ + if (key_value) { + GRN_LOG(ctx, GRN_LOG_ERROR, "nonexistent key value"); + goto exit; + } + break; + } + + if (id_value) { + id = parse_id_value(ctx, id_value); + if (grn_table_at(ctx, loader->table, id) == GRN_ID_NIL) { + if (ctx->rc == GRN_SUCCESS) { + id = grn_table_add(ctx, loader->table, NULL, 0, NULL); + } + } + } else if (key_value) { + id = loader_add(ctx, key_value); + } else { + id = grn_table_add(ctx, loader->table, NULL, 0, NULL); + } + if (id == GRN_ID_NIL) { + /* Target record is not available. */ + goto exit; + } + + for (value = value_begin; value + 1 < value_end; + value = values_next(ctx, value)) { + grn_obj *col; + const char *name = GRN_TEXT_VALUE(value); + unsigned int name_size = GRN_TEXT_LEN(value); + value++; + if (value == id_value || value == key_value) { + /* Skip _id and _key, because it's already used to get id. */ + continue; + } + col = grn_obj_column(ctx, loader->table, name, name_size); + if (!col) { + GRN_LOG(ctx, GRN_LOG_ERROR, "invalid column('%.*s')", + (int)name_size, name); + /* Automatic column creation is disabled. */ + /* + if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) { + grn_obj *v = value + 1; + col = grn_column_create(ctx, loader->table, name, name_size, + NULL, GRN_OBJ_PERSISTENT|GRN_OBJ_COLUMN_VECTOR, + grn_ctx_at(ctx, v->header.domain)); + } else { + col = grn_column_create(ctx, loader->table, name, name_size, + NULL, GRN_OBJ_PERSISTENT, + grn_ctx_at(ctx, value->header.domain)); + } + */ + } else { + if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACKET) { + set_vector(ctx, col, id, value); + } else if (value->header.domain == GRN_JSON_LOAD_OPEN_BRACE) { + set_weight_vector(ctx, col, id, value); + } else { + grn_obj_set_value(ctx, col, id, value, GRN_OBJ_SET); + } + if (ctx->rc != GRN_SUCCESS) { + grn_loader_save_error(ctx, loader); + report_set_column_value_failure(ctx, key_value, + name, name_size, value); + ERRCLR(ctx); + } + grn_obj_unlink(ctx, col); + } + } + if (loader->each) { + value = grn_expr_get_var_by_offset(ctx, loader->each, 0); + GRN_RECORD_SET(ctx, value, id); + grn_expr_exec(ctx, loader->each, 0); + } + loader->nrecords++; +exit: + if (loader->output_ids) { + GRN_UINT32_PUT(ctx, &(loader->ids), id); + } + if (loader->output_errors) { + GRN_INT32_PUT(ctx, &(loader->return_codes), ctx->rc); + grn_vector_add_element(ctx, + &(loader->error_messages), + ctx->errbuf, + strlen(ctx->errbuf), + 0, + GRN_DB_TEXT); + } + loader->values_size = begin; + ERRCLR(ctx); +} + +#define JSON_READ_OPEN_BRACKET() do {\ + GRN_UINT32_PUT(ctx, &loader->level, loader->values_size);\ + values_add(ctx, loader);\ + loader->last->header.domain = GRN_JSON_LOAD_OPEN_BRACKET;\ + loader->stat = GRN_LOADER_TOKEN;\ + str++;\ +} while (0) + +#define JSON_READ_OPEN_BRACE() do {\ + GRN_UINT32_PUT(ctx, &loader->level, loader->values_size);\ + values_add(ctx, loader);\ + loader->last->header.domain = GRN_JSON_LOAD_OPEN_BRACE;\ + loader->stat = GRN_LOADER_TOKEN;\ + str++;\ +} while (0) + +static void +json_read(grn_ctx *ctx, grn_loader *loader, const char *str, unsigned int str_len) +{ + const char *const beg = str; + char c; + int len; + const char *se = str + str_len; + while (str < se) { + c = *str; + switch (loader->stat) { + case GRN_LOADER_BEGIN : + if ((len = grn_isspace(str, ctx->encoding))) { + str += len; + continue; + } + switch (c) { + case '[' : + JSON_READ_OPEN_BRACKET(); + break; + case '{' : + JSON_READ_OPEN_BRACE(); + break; + default : + ERR(GRN_INVALID_ARGUMENT, + "JSON must start with '[' or '{': <%.*s>", str_len, beg); + loader->stat = GRN_LOADER_END; + break; + } + break; + case GRN_LOADER_TOKEN : + if ((len = grn_isspace(str, ctx->encoding))) { + str += len; + continue; + } + switch (c) { + case '"' : + loader->stat = GRN_LOADER_STRING; + values_add(ctx, loader); + str++; + break; + case '[' : + JSON_READ_OPEN_BRACKET(); + break; + case '{' : + JSON_READ_OPEN_BRACE(); + break; + case ':' : + str++; + break; + case ',' : + str++; + break; + case ']' : + bracket_close(ctx, loader); + loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END; + if (ctx->rc == GRN_CANCEL) { + loader->stat = GRN_LOADER_END; + } + str++; + break; + case '}' : + brace_close(ctx, loader); + loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END; + if (ctx->rc == GRN_CANCEL) { + loader->stat = GRN_LOADER_END; + } + str++; + break; + case '+' : case '-' : case '0' : case '1' : case '2' : case '3' : + case '4' : case '5' : case '6' : case '7' : case '8' : case '9' : + loader->stat = GRN_LOADER_NUMBER; + values_add(ctx, loader); + break; + default : + if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || ('_' == c)) { + loader->stat = GRN_LOADER_SYMBOL; + values_add(ctx, loader); + } else { + if ((len = grn_charlen(ctx, str, se))) { + GRN_LOG(ctx, GRN_LOG_ERROR, "ignored invalid char('%c') at", c); + GRN_LOG(ctx, GRN_LOG_ERROR, "%.*s", (int)(str - beg) + len, beg); + GRN_LOG(ctx, GRN_LOG_ERROR, "%*s", (int)(str - beg) + 1, "^"); + str += len; + } else { + GRN_LOG(ctx, GRN_LOG_ERROR, "ignored invalid char(\\x%.2x) after", c); + GRN_LOG(ctx, GRN_LOG_ERROR, "%.*s", (int)(str - beg), beg); + str = se; + } + } + break; + } + break; + case GRN_LOADER_SYMBOL : + if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z') || + ('0' <= c && c <= '9') || ('_' == c)) { + GRN_TEXT_PUTC(ctx, loader->last, c); + str++; + } else { + char *v = GRN_TEXT_VALUE(loader->last); + switch (*v) { + case 'n' : + if (GRN_TEXT_LEN(loader->last) == 4 && !memcmp(v, "null", 4)) { + loader->last->header.domain = GRN_DB_VOID; + GRN_BULK_REWIND(loader->last); + } + break; + case 't' : + if (GRN_TEXT_LEN(loader->last) == 4 && !memcmp(v, "true", 4)) { + loader->last->header.domain = GRN_DB_BOOL; + GRN_BOOL_SET(ctx, loader->last, GRN_TRUE); + } + break; + case 'f' : + if (GRN_TEXT_LEN(loader->last) == 5 && !memcmp(v, "false", 5)) { + loader->last->header.domain = GRN_DB_BOOL; + GRN_BOOL_SET(ctx, loader->last, GRN_FALSE); + } + break; + default : + break; + } + loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END; + } + break; + case GRN_LOADER_NUMBER : + switch (c) { + case '+' : case '-' : case '.' : case 'e' : case 'E' : + case '0' : case '1' : case '2' : case '3' : case '4' : + case '5' : case '6' : case '7' : case '8' : case '9' : + GRN_TEXT_PUTC(ctx, loader->last, c); + str++; + break; + default : + { + const char *cur, *str = GRN_BULK_HEAD(loader->last); + const char *str_end = GRN_BULK_CURR(loader->last); + int64_t i = grn_atoll(str, str_end, &cur); + if (cur == str_end) { + loader->last->header.domain = GRN_DB_INT64; + GRN_INT64_SET(ctx, loader->last, i); + } else if (cur != str) { + uint64_t i = grn_atoull(str, str_end, &cur); + if (cur == str_end) { + loader->last->header.domain = GRN_DB_UINT64; + GRN_UINT64_SET(ctx, loader->last, i); + } else if (cur != str) { + double d; + char *end; + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_PUT(ctx, &buf, str, GRN_BULK_VSIZE(loader->last)); + GRN_TEXT_PUTC(ctx, &buf, '\0'); + errno = 0; + d = strtod(GRN_TEXT_VALUE(&buf), &end); + if (!errno && end + 1 == GRN_BULK_CURR(&buf)) { + loader->last->header.domain = GRN_DB_FLOAT; + GRN_FLOAT_SET(ctx, loader->last, d); + } + GRN_OBJ_FIN(ctx, &buf); + } + } + } + loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END; + break; + } + break; + case GRN_LOADER_STRING : + switch (c) { + case '\\' : + loader->stat = GRN_LOADER_STRING_ESC; + str++; + break; + case '"' : + str++; + loader->stat = GRN_BULK_VSIZE(&loader->level) ? GRN_LOADER_TOKEN : GRN_LOADER_END; + /* + *(GRN_BULK_CURR(loader->last)) = '\0'; + GRN_LOG(ctx, GRN_LOG_ALERT, "read str(%s)", GRN_TEXT_VALUE(loader->last)); + */ + break; + default : + if ((len = grn_charlen(ctx, str, se))) { + GRN_TEXT_PUT(ctx, loader->last, str, len); + str += len; + } else { + GRN_LOG(ctx, GRN_LOG_ERROR, "ignored invalid char(\\x%.2x) after", c); + GRN_LOG(ctx, GRN_LOG_ERROR, "%.*s", (int)(str - beg), beg); + str = se; + } + break; + } + break; + case GRN_LOADER_STRING_ESC : + switch (c) { + case 'b' : + GRN_TEXT_PUTC(ctx, loader->last, '\b'); + loader->stat = GRN_LOADER_STRING; + break; + case 'f' : + GRN_TEXT_PUTC(ctx, loader->last, '\f'); + loader->stat = GRN_LOADER_STRING; + break; + case 'n' : + GRN_TEXT_PUTC(ctx, loader->last, '\n'); + loader->stat = GRN_LOADER_STRING; + break; + case 'r' : + GRN_TEXT_PUTC(ctx, loader->last, '\r'); + loader->stat = GRN_LOADER_STRING; + break; + case 't' : + GRN_TEXT_PUTC(ctx, loader->last, '\t'); + loader->stat = GRN_LOADER_STRING; + break; + case 'u' : + loader->stat = GRN_LOADER_UNICODE0; + break; + default : + GRN_TEXT_PUTC(ctx, loader->last, c); + loader->stat = GRN_LOADER_STRING; + break; + } + str++; + break; + case GRN_LOADER_UNICODE0 : + switch (c) { + case '0' : case '1' : case '2' : case '3' : case '4' : + case '5' : case '6' : case '7' : case '8' : case '9' : + loader->unichar = (c - '0') * 0x1000; + break; + case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' : + loader->unichar = (c - 'a' + 10) * 0x1000; + break; + case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' : + loader->unichar = (c - 'A' + 10) * 0x1000; + break; + default : + ;// todo : error + } + loader->stat = GRN_LOADER_UNICODE1; + str++; + break; + case GRN_LOADER_UNICODE1 : + switch (c) { + case '0' : case '1' : case '2' : case '3' : case '4' : + case '5' : case '6' : case '7' : case '8' : case '9' : + loader->unichar += (c - '0') * 0x100; + break; + case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' : + loader->unichar += (c - 'a' + 10) * 0x100; + break; + case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' : + loader->unichar += (c - 'A' + 10) * 0x100; + break; + default : + ;// todo : error + } + loader->stat = GRN_LOADER_UNICODE2; + str++; + break; + case GRN_LOADER_UNICODE2 : + switch (c) { + case '0' : case '1' : case '2' : case '3' : case '4' : + case '5' : case '6' : case '7' : case '8' : case '9' : + loader->unichar += (c - '0') * 0x10; + break; + case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' : + loader->unichar += (c - 'a' + 10) * 0x10; + break; + case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' : + loader->unichar += (c - 'A' + 10) * 0x10; + break; + default : + ;// todo : error + } + loader->stat = GRN_LOADER_UNICODE3; + str++; + break; + case GRN_LOADER_UNICODE3 : + switch (c) { + case '0' : case '1' : case '2' : case '3' : case '4' : + case '5' : case '6' : case '7' : case '8' : case '9' : + loader->unichar += (c - '0'); + break; + case 'a' : case 'b' : case 'c' : case 'd' : case 'e' : case 'f' : + loader->unichar += (c - 'a' + 10); + break; + case 'A' : case 'B' : case 'C' : case 'D' : case 'E' : case 'F' : + loader->unichar += (c - 'A' + 10); + break; + default : + ;// todo : error + } + { + uint32_t u = loader->unichar; + if (u < 0x80) { + GRN_TEXT_PUTC(ctx, loader->last, u); + } else { + if (u < 0x800) { + GRN_TEXT_PUTC(ctx, loader->last, ((u >> 6) & 0x1f) | 0xc0); + } else { + GRN_TEXT_PUTC(ctx, loader->last, (u >> 12) | 0xe0); + GRN_TEXT_PUTC(ctx, loader->last, ((u >> 6) & 0x3f) | 0x80); + } + GRN_TEXT_PUTC(ctx, loader->last, (u & 0x3f) | 0x80); + } + } + loader->stat = GRN_LOADER_STRING; + str++; + break; + case GRN_LOADER_END : + str = se; + break; + } + } +} + +#undef JSON_READ_OPEN_BRACKET +#undef JSON_READ_OPEN_BRACE + +/* + * grn_loader_parse_columns parses a columns parameter. + * Columns except _id and _key are appended to loader->columns. + * If it contains _id or _key, loader->id_offset or loader->key_offset is set. + */ +static grn_rc +grn_loader_parse_columns(grn_ctx *ctx, grn_loader *loader, + const char *str, unsigned int str_size) +{ + const char *ptr = str, *ptr_end = ptr + str_size, *rest; + const char *tokens[256], *token_end; + while (ptr < ptr_end) { + int i, n = grn_tokenize(ptr, ptr_end - ptr, tokens, 256, &rest); + for (i = 0; i < n; i++) { + grn_obj *column; + token_end = tokens[i]; + while (ptr < token_end && (' ' == *ptr || ',' == *ptr)) { + ptr++; + } + column = grn_obj_column(ctx, loader->table, ptr, token_end - ptr); + if (!column) { + ERR(GRN_INVALID_ARGUMENT, "nonexistent column: <%.*s>", + (int)(token_end - ptr), ptr); + return ctx->rc; + } + if (name_equal(ptr, token_end - ptr, GRN_COLUMN_NAME_ID)) { + grn_obj_unlink(ctx, column); + if (loader->id_offset != -1 || loader->key_offset != -1) { + /* _id and _key must not appear more than once. */ + if (loader->id_offset != -1) { + ERR(GRN_INVALID_ARGUMENT, + "duplicated id and key columns: <%s> at %d and <%s> at %d", + GRN_COLUMN_NAME_ID, i, + GRN_COLUMN_NAME_ID, loader->id_offset); + } else { + ERR(GRN_INVALID_ARGUMENT, + "duplicated id and key columns: <%s> at %d and <%s> at %d", + GRN_COLUMN_NAME_ID, i, + GRN_COLUMN_NAME_KEY, loader->key_offset); + } + return ctx->rc; + } + loader->id_offset = i; + } else if (name_equal(ptr, token_end - ptr, GRN_COLUMN_NAME_KEY)) { + grn_obj_unlink(ctx, column); + if (loader->id_offset != -1 || loader->key_offset != -1) { + /* _id and _key must not appear more than once. */ + if (loader->id_offset != -1) { + ERR(GRN_INVALID_ARGUMENT, + "duplicated id and key columns: <%s> at %d and <%s> at %d", + GRN_COLUMN_NAME_KEY, i, + GRN_COLUMN_NAME_ID, loader->id_offset); + } else { + ERR(GRN_INVALID_ARGUMENT, + "duplicated id and key columns: <%s> at %d and <%s> at %d", + GRN_COLUMN_NAME_KEY, i, + GRN_COLUMN_NAME_KEY, loader->key_offset); + } + return ctx->rc; + } + loader->key_offset = i; + } else { + GRN_PTR_PUT(ctx, &loader->columns, column); + } + ptr = token_end; + } + ptr = rest; + } + switch (loader->table->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + if (loader->id_offset == -1 && loader->key_offset == -1) { + ERR(GRN_INVALID_ARGUMENT, "missing id or key column"); + return ctx->rc; + } + break; + } + return ctx->rc; +} + +static grn_com_addr *addr; + +void +grn_load_internal(grn_ctx *ctx, grn_load_input *input) +{ + grn_loader *loader = &ctx->impl->loader; + + loader->emit_level = input->emit_level; + if (ctx->impl->edge) { + grn_edge *edge = grn_edges_add_communicator(ctx, addr); + grn_obj *msg = grn_msg_open(ctx, edge->com, &ctx->impl->edge->send_old); + /* build msg */ + grn_edge_dispatch(ctx, edge, msg); + } + if (input->table.length > 0) { + grn_ctx_loader_clear(ctx); + loader->input_type = input->type; + if (grn_db_check_name(ctx, input->table.value, input->table.length)) { + GRN_DB_CHECK_NAME_ERR("[table][load]", + input->table.value, + (int)(input->table.length)); + loader->stat = GRN_LOADER_END; + return; + } + loader->table = grn_ctx_get(ctx, input->table.value, input->table.length); + if (!loader->table) { + ERR(GRN_INVALID_ARGUMENT, + "nonexistent table: <%.*s>", + (int)(input->table.length), + input->table.value); + loader->stat = GRN_LOADER_END; + return; + } + if (input->columns.length > 0) { + grn_rc rc = grn_loader_parse_columns(ctx, + loader, + input->columns.value, + input->columns.length); + if (rc != GRN_SUCCESS) { + loader->columns_status = GRN_LOADER_COLUMNS_BROKEN; + loader->stat = GRN_LOADER_END; + return; + } + loader->columns_status = GRN_LOADER_COLUMNS_SET; + } + if (input->if_exists.length > 0) { + grn_obj *v; + GRN_EXPR_CREATE_FOR_QUERY(ctx, loader->table, loader->ifexists, v); + if (loader->ifexists && v) { + grn_expr_parse(ctx, + loader->ifexists, + input->if_exists.value, + input->if_exists.length, + NULL, GRN_OP_EQUAL, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE); + } + } + if (input->each.length > 0) { + grn_obj *v; + GRN_EXPR_CREATE_FOR_QUERY(ctx, loader->table, loader->each, v); + if (loader->each && v) { + grn_expr_parse(ctx, loader->each, + input->each.value, + input->each.length, + NULL, GRN_OP_EQUAL, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE); + } + } + loader->output_ids = input->output_ids; + loader->output_errors = input->output_errors; + } else { + if (!loader->table) { + ERR(GRN_INVALID_ARGUMENT, "mandatory \"table\" parameter is absent"); + loader->stat = GRN_LOADER_END; + return; + } + } + switch (loader->input_type) { + case GRN_CONTENT_JSON : + json_read(ctx, loader, input->values.value, input->values.length); + break; + case GRN_CONTENT_NONE : + case GRN_CONTENT_TSV : + case GRN_CONTENT_XML : + case GRN_CONTENT_MSGPACK : + case GRN_CONTENT_GROONGA_COMMAND_LIST : + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "unsupported input_type"); + loader->stat = GRN_LOADER_END; + // todo + break; + } +} + +grn_rc +grn_load(grn_ctx *ctx, grn_content_type input_type, + const char *table, unsigned int table_len, + const char *columns, unsigned int columns_len, + const char *values, unsigned int values_len, + const char *ifexists, unsigned int ifexists_len, + const char *each, unsigned int each_len) +{ + if (!ctx || !ctx->impl) { + ERR(GRN_INVALID_ARGUMENT, "db not initialized"); + return ctx->rc; + } + GRN_API_ENTER; + { + grn_load_input input; + input.type = input_type; + input.table.value = table; + input.table.length = table_len; + input.columns.value = columns; + input.columns.length = columns_len; + input.values.value = values; + input.values.length = values_len; + input.if_exists.value = ifexists; + input.if_exists.length = ifexists_len; + input.each.value = each; + input.each.length = each_len; + input.output_ids = GRN_FALSE; + input.output_errors = GRN_FALSE; + input.emit_level = 1; + grn_load_internal(ctx, &input); + } + GRN_API_RETURN(ctx->rc); +} diff --git a/storage/mroonga/vendor/groonga/lib/logger.c b/storage/mroonga/vendor/groonga/lib/logger.c new file mode 100644 index 00000000..9c1a2dbd --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/logger.c @@ -0,0 +1,810 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_logger.h" +#include "grn_ctx.h" +#include "grn_ctx_impl.h" + +#include +#include +#include + +#ifdef WIN32 +# include +#endif /* WIN32 */ + +static const char *log_level_names[] = { + "none", + "emergency", + "alert", + "critical", + "error", + "warning", + "notice", + "info", + "debug", + "dump" +}; + +#define GRN_LOG_LAST GRN_LOG_DUMP + +const char * +grn_log_level_to_string(grn_log_level level) +{ + if (level <= GRN_LOG_LAST) { + return log_level_names[level]; + } else { + return "unknown"; + } +} + +grn_bool +grn_log_level_parse(const char *string, grn_log_level *level) +{ + if (strcmp(string, " ") == 0 || + grn_strcasecmp(string, "none") == 0) { + *level = GRN_LOG_NONE; + return GRN_TRUE; + } else if (strcmp(string, "E") == 0 || + grn_strcasecmp(string, "emerg") == 0 || + grn_strcasecmp(string, "emergency") == 0) { + *level = GRN_LOG_EMERG; + return GRN_TRUE; + } else if (strcmp(string, "A") == 0 || + grn_strcasecmp(string, "alert") == 0) { + *level = GRN_LOG_ALERT; + return GRN_TRUE; + } else if (strcmp(string, "C") == 0 || + grn_strcasecmp(string, "crit") == 0 || + grn_strcasecmp(string, "critical") == 0) { + *level = GRN_LOG_CRIT; + return GRN_TRUE; + } else if (strcmp(string, "e") == 0 || + grn_strcasecmp(string, "error") == 0) { + *level = GRN_LOG_ERROR; + return GRN_TRUE; + } else if (strcmp(string, "w") == 0 || + grn_strcasecmp(string, "warn") == 0 || + grn_strcasecmp(string, "warning") == 0) { + *level = GRN_LOG_WARNING; + return GRN_TRUE; + } else if (strcmp(string, "n") == 0 || + grn_strcasecmp(string, "notice") == 0) { + *level = GRN_LOG_NOTICE; + return GRN_TRUE; + } else if (strcmp(string, "i") == 0 || + grn_strcasecmp(string, "info") == 0) { + *level = GRN_LOG_INFO; + return GRN_TRUE; + } else if (strcmp(string, "d") == 0 || + grn_strcasecmp(string, "debug") == 0) { + *level = GRN_LOG_DEBUG; + return GRN_TRUE; + } else if (strcmp(string, "-") == 0 || + grn_strcasecmp(string, "dump") == 0) { + *level = GRN_LOG_DUMP; + return GRN_TRUE; + } else { + return GRN_FALSE; + } +} + +static void +rotate_log_file(grn_ctx *ctx, const char *current_path) +{ + char rotated_path[PATH_MAX]; + grn_timeval now; + struct tm tm_buffer; + struct tm *tm; + + grn_timeval_now(ctx, &now); + tm = grn_timeval2tm(ctx, &now, &tm_buffer); + grn_snprintf(rotated_path, PATH_MAX, PATH_MAX, + "%s.%04d-%02d-%02d-%02d-%02d-%02d-%06d", + current_path, + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec, + (int)(GRN_TIME_NSEC_TO_USEC(now.tv_nsec))); + rename(current_path, rotated_path); +} + +static grn_bool logger_inited = GRN_FALSE; +static char *default_logger_path = NULL; +static FILE *default_logger_file = NULL; +static grn_critical_section default_logger_lock; +static off_t default_logger_size = 0; +static off_t default_logger_rotate_threshold_size = 0; + +#define LOGGER_NEED_ROTATE(size, threshold) \ + ((threshold) > 0 && (size) >= (threshold)) + +static void +default_logger_log(grn_ctx *ctx, grn_log_level level, + const char *timestamp, const char *title, + const char *message, const char *location, void *user_data) +{ + const char slev[] = " EACewnid-"; + if (default_logger_path) { + CRITICAL_SECTION_ENTER(default_logger_lock); + if (!default_logger_file) { + default_logger_file = grn_fopen(default_logger_path, "a"); + default_logger_size = 0; + if (default_logger_file) { + struct stat stat; + if (fstat(grn_fileno(default_logger_file), &stat) != -1) { + default_logger_size = stat.st_size; + } + } + } + if (default_logger_file) { + char label = *(slev + level); + int written; + if (location && *location) { + if (title && *title) { + written = fprintf(default_logger_file, "%s|%c|%s: %s %s\n", + timestamp, label, location, title, message); + } else { + written = fprintf(default_logger_file, "%s|%c|%s: %s\n", + timestamp, label, location, message); + } + } else { + written = fprintf(default_logger_file, "%s|%c|%s %s\n", + timestamp, label, title, message); + } + if (written > 0) { + default_logger_size += written; + if (LOGGER_NEED_ROTATE(default_logger_size, + default_logger_rotate_threshold_size)) { + fclose(default_logger_file); + default_logger_file = NULL; + rotate_log_file(ctx, default_logger_path); + } else { + fflush(default_logger_file); + } + } + } + CRITICAL_SECTION_LEAVE(default_logger_lock); + } +} + +static void +default_logger_reopen(grn_ctx *ctx, void *user_data) +{ + GRN_LOG(ctx, GRN_LOG_NOTICE, "log will be closed."); + CRITICAL_SECTION_ENTER(default_logger_lock); + if (default_logger_file) { + fclose(default_logger_file); + default_logger_file = NULL; + } + CRITICAL_SECTION_LEAVE(default_logger_lock); + GRN_LOG(ctx, GRN_LOG_NOTICE, "log opened."); +} + +static void +default_logger_fin(grn_ctx *ctx, void *user_data) +{ + CRITICAL_SECTION_ENTER(default_logger_lock); + if (default_logger_file) { + fclose(default_logger_file); + default_logger_file = NULL; + } + CRITICAL_SECTION_LEAVE(default_logger_lock); +} + +static grn_logger default_logger = { + GRN_LOG_DEFAULT_LEVEL, + GRN_LOG_TIME|GRN_LOG_MESSAGE, + NULL, + default_logger_log, + default_logger_reopen, + default_logger_fin +}; + +#define INITIAL_LOGGER { \ + GRN_LOG_DEFAULT_LEVEL, \ + GRN_LOG_TIME|GRN_LOG_MESSAGE, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ +} + +static grn_logger current_logger = INITIAL_LOGGER; + +void +grn_default_logger_set_max_level(grn_log_level max_level) +{ + default_logger.max_level = max_level; + if (current_logger.log == default_logger_log) { + current_logger.max_level = max_level; + } +} + +grn_log_level +grn_default_logger_get_max_level(void) +{ + return default_logger.max_level; +} + +void +grn_default_logger_set_flags(int flags) +{ + default_logger.flags = flags; + if (current_logger.log == default_logger_log) { + current_logger.flags = flags; + } +} + +int +grn_default_logger_get_flags(void) +{ + return default_logger.flags; +} + +void +grn_default_logger_set_path(const char *path) +{ + if (logger_inited) { + CRITICAL_SECTION_ENTER(default_logger_lock); + } + + if (default_logger_path) { + free(default_logger_path); + } + + if (path) { + default_logger_path = grn_strdup_raw(path); + } else { + default_logger_path = NULL; + } + + if (logger_inited) { + CRITICAL_SECTION_LEAVE(default_logger_lock); + } +} + +const char * +grn_default_logger_get_path(void) +{ + return default_logger_path; +} + +void +grn_default_logger_set_rotate_threshold_size(off_t threshold) +{ + default_logger_rotate_threshold_size = threshold; +} + +off_t +grn_default_logger_get_rotate_threshold_size(void) +{ + return default_logger_rotate_threshold_size; +} + +void +grn_logger_reopen(grn_ctx *ctx) +{ + if (current_logger.reopen) { + current_logger.reopen(ctx, current_logger.user_data); + } +} + +static void +current_logger_fin(grn_ctx *ctx) +{ + if (current_logger.fin) { + current_logger.fin(ctx, current_logger.user_data); + } + { + grn_logger initial_logger = INITIAL_LOGGER; + current_logger = initial_logger; + } +} + +static void +logger_info_func_wrapper(grn_ctx *ctx, grn_log_level level, + const char *timestamp, const char *title, + const char *message, const char *location, + void *user_data) +{ + grn_logger_info *info = user_data; + info->func(level, timestamp, title, message, location, info->func_arg); +} + +/* Deprecated since 2.1.2. */ +grn_rc +grn_logger_info_set(grn_ctx *ctx, const grn_logger_info *info) +{ + if (info) { + grn_logger logger; + + memset(&logger, 0, sizeof(grn_logger)); + logger.max_level = info->max_level; + logger.flags = info->flags; + if (info->func) { + logger.log = logger_info_func_wrapper; + logger.user_data = (grn_logger_info *)info; + } else { + logger.log = default_logger_log; + logger.reopen = default_logger_reopen; + logger.fin = default_logger_fin; + } + return grn_logger_set(ctx, &logger); + } else { + return grn_logger_set(ctx, NULL); + } +} + +grn_rc +grn_logger_set(grn_ctx *ctx, const grn_logger *logger) +{ + current_logger_fin(ctx); + if (logger) { + current_logger = *logger; + } else { + current_logger = default_logger; + } + return GRN_SUCCESS; +} + +void +grn_logger_set_max_level(grn_ctx *ctx, grn_log_level max_level) +{ + current_logger.max_level = max_level; +} + +grn_log_level +grn_logger_get_max_level(grn_ctx *ctx) +{ + return current_logger.max_level; +} + +grn_bool +grn_logger_pass(grn_ctx *ctx, grn_log_level level) +{ + return level <= current_logger.max_level; +} + +#define TBUFSIZE GRN_TIMEVAL_STR_SIZE +#define MBUFSIZE 0x1000 +#define LBUFSIZE 0x400 + +void +grn_logger_put(grn_ctx *ctx, + grn_log_level level, + const char *file, + int line, + const char *func, + const char *fmt, + ...) +{ + va_list ap; + va_start(ap, fmt); + grn_logger_putv(ctx, level, file, line, func, fmt, ap); + va_end(ap); +} + +void +grn_logger_putv(grn_ctx *ctx, + grn_log_level level, + const char *file, + int line, + const char *func, + const char *fmt, + va_list ap) +{ + if (level <= current_logger.max_level && current_logger.log) { + char tbuf[TBUFSIZE]; + char mbuf[MBUFSIZE]; + char lbuf[LBUFSIZE]; + tbuf[0] = '\0'; + if (current_logger.flags & GRN_LOG_TIME) { + grn_timeval tv; + grn_timeval_now(ctx, &tv); + grn_timeval2str(ctx, &tv, tbuf, TBUFSIZE); + } + if (current_logger.flags & GRN_LOG_MESSAGE) { + grn_vsnprintf(mbuf, MBUFSIZE, fmt, ap); + } else { + mbuf[0] = '\0'; + } + if (current_logger.flags & GRN_LOG_LOCATION) { + grn_snprintf(lbuf, LBUFSIZE, LBUFSIZE, + "%d %s:%d %s()", grn_getpid(), file, line, func); + } else if (current_logger.flags & GRN_LOG_PID) { + grn_snprintf(lbuf, LBUFSIZE, LBUFSIZE, + "%d", grn_getpid()); + } else { + lbuf[0] = '\0'; + } + current_logger.log(ctx, level, tbuf, "", mbuf, lbuf, + current_logger.user_data); + } +} + +void +grn_logger_init(void) +{ + CRITICAL_SECTION_INIT(default_logger_lock); + if (!current_logger.log) { + current_logger = default_logger; + } + + logger_inited = GRN_TRUE; +} + +void +grn_logger_fin(grn_ctx *ctx) +{ + current_logger_fin(ctx); + if (default_logger_path) { + free(default_logger_path); + default_logger_path = NULL; + } + CRITICAL_SECTION_FIN(default_logger_lock); + + logger_inited = GRN_FALSE; +} + + +static grn_bool query_logger_inited = GRN_FALSE; +static char *default_query_logger_path = NULL; +static FILE *default_query_logger_file = NULL; +static grn_critical_section default_query_logger_lock; +static off_t default_query_logger_size = 0; +static off_t default_query_logger_rotate_threshold_size = 0; + +grn_bool +grn_query_log_flags_parse(const char *string, + int string_size, + unsigned int *flags) +{ + const char *string_end; + + *flags = GRN_QUERY_LOG_NONE; + + if (!string) { + return GRN_TRUE; + } + + if (string_size < 0) { + string_size = strlen(string); + } + + string_end = string + string_size; + + while (string < string_end) { + if (*string == '|' || *string == ' ') { + string += 1; + continue; + } + +#define CHECK_FLAG(name) \ + if (((string_end - string) >= (sizeof(#name) - 1)) && \ + (memcmp(string, #name, sizeof(#name) - 1) == 0) && \ + (((string_end - string) == (sizeof(#name) - 1)) || \ + (string[sizeof(#name) - 1] == '|') || \ + (string[sizeof(#name) - 1] == ' '))) { \ + *flags |= GRN_QUERY_LOG_ ## name; \ + string += sizeof(#name) - 1; \ + continue; \ + } + + CHECK_FLAG(NONE); + CHECK_FLAG(COMMAND); + CHECK_FLAG(RESULT_CODE); + CHECK_FLAG(DESTINATION); + CHECK_FLAG(CACHE); + CHECK_FLAG(SIZE); + CHECK_FLAG(SCORE); + CHECK_FLAG(ALL); + CHECK_FLAG(DEFAULT); + +#undef CHECK_FLAG + + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static void +default_query_logger_log(grn_ctx *ctx, unsigned int flag, + const char *timestamp, const char *info, + const char *message, void *user_data) +{ + if (default_query_logger_path) { + CRITICAL_SECTION_ENTER(default_query_logger_lock); + if (!default_query_logger_file) { + default_query_logger_file = grn_fopen(default_query_logger_path, "a"); + default_query_logger_size = 0; + if (default_query_logger_file) { + struct stat stat; + if (fstat(grn_fileno(default_query_logger_file), &stat) != -1) { + default_query_logger_size = stat.st_size; + } + } + } + if (default_query_logger_file) { + int written; + written = fprintf(default_query_logger_file, "%s|%s%s\n", + timestamp, info, message); + if (written > 0) { + default_query_logger_size += written; + if (LOGGER_NEED_ROTATE(default_query_logger_size, + default_query_logger_rotate_threshold_size)) { + fclose(default_query_logger_file); + default_query_logger_file = NULL; + rotate_log_file(ctx, default_query_logger_path); + } else { + fflush(default_query_logger_file); + } + } + } + CRITICAL_SECTION_LEAVE(default_query_logger_lock); + } +} + +static void +default_query_logger_close(grn_ctx *ctx, void *user_data) +{ + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_DESTINATION, " ", + "query log will be closed: <%s>", default_query_logger_path); + CRITICAL_SECTION_ENTER(default_query_logger_lock); + if (default_query_logger_file) { + fclose(default_query_logger_file); + default_query_logger_file = NULL; + } + CRITICAL_SECTION_LEAVE(default_query_logger_lock); +} + +static void +default_query_logger_reopen(grn_ctx *ctx, void *user_data) +{ + default_query_logger_close(ctx, user_data); + if (default_query_logger_path) { + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_DESTINATION, " ", + "query log is opened: <%s>", default_query_logger_path); + } +} + +static void +default_query_logger_fin(grn_ctx *ctx, void *user_data) +{ + if (default_query_logger_file) { + default_query_logger_close(ctx, user_data); + } +} + +static grn_query_logger default_query_logger = { + GRN_QUERY_LOG_DEFAULT, + NULL, + default_query_logger_log, + default_query_logger_reopen, + default_query_logger_fin +}; + +#define INITIAL_QUERY_LOGGER { \ + GRN_QUERY_LOG_DEFAULT, \ + NULL, \ + NULL, \ + NULL, \ + NULL \ +} + +static grn_query_logger current_query_logger = INITIAL_QUERY_LOGGER; + +void +grn_default_query_logger_set_flags(unsigned int flags) +{ + default_query_logger.flags = flags; + if (current_query_logger.log == default_query_logger_log) { + current_query_logger.flags = flags; + } +} + +unsigned int +grn_default_query_logger_get_flags(void) +{ + return default_query_logger.flags; +} + +void +grn_default_query_logger_set_path(const char *path) +{ + if (query_logger_inited) { + CRITICAL_SECTION_ENTER(default_query_logger_lock); + } + + if (default_query_logger_path) { + free(default_query_logger_path); + } + + if (path) { + default_query_logger_path = grn_strdup_raw(path); + } else { + default_query_logger_path = NULL; + } + + if (query_logger_inited) { + CRITICAL_SECTION_LEAVE(default_query_logger_lock); + } +} + +const char * +grn_default_query_logger_get_path(void) +{ + return default_query_logger_path; +} + +void +grn_default_query_logger_set_rotate_threshold_size(off_t threshold) +{ + default_query_logger_rotate_threshold_size = threshold; +} + +off_t +grn_default_query_logger_get_rotate_threshold_size(void) +{ + return default_query_logger_rotate_threshold_size; +} + +void +grn_query_logger_reopen(grn_ctx *ctx) +{ + if (current_query_logger.reopen) { + current_query_logger.reopen(ctx, current_query_logger.user_data); + } +} + +static void +current_query_logger_fin(grn_ctx *ctx) +{ + if (current_query_logger.fin) { + current_query_logger.fin(ctx, current_query_logger.user_data); + } + { + grn_query_logger initial_query_logger = INITIAL_QUERY_LOGGER; + current_query_logger = initial_query_logger; + } +} + +grn_rc +grn_query_logger_set(grn_ctx *ctx, const grn_query_logger *logger) +{ + current_query_logger_fin(ctx); + if (logger) { + current_query_logger = *logger; + } else { + current_query_logger = default_query_logger; + } + return GRN_SUCCESS; +} + +void +grn_query_logger_set_flags(grn_ctx *ctx, unsigned int flags) +{ + current_query_logger.flags = flags; +} + +void +grn_query_logger_add_flags(grn_ctx *ctx, unsigned int flags) +{ + current_query_logger.flags |= flags; +} + +void +grn_query_logger_remove_flags(grn_ctx *ctx, unsigned int flags) +{ + current_query_logger.flags &= ~flags; +} + +unsigned int +grn_query_logger_get_flags(grn_ctx *ctx) +{ + return current_query_logger.flags; +} + +grn_bool +grn_query_logger_pass(grn_ctx *ctx, unsigned int flag) +{ + return current_query_logger.flags & flag; +} + +#define TIMESTAMP_BUFFER_SIZE TBUFSIZE +/* 8+a(%p) + 1(|) + 1(mark) + 15(elapsed time) = 25+a */ +#define INFO_BUFFER_SIZE 40 + +void +grn_query_logger_put(grn_ctx *ctx, unsigned int flag, const char *mark, + const char *format, ...) +{ + char timestamp[TIMESTAMP_BUFFER_SIZE]; + char info[INFO_BUFFER_SIZE]; + grn_obj *message = &ctx->impl->query_log_buf; + + if (!current_query_logger.log) { + return; + } + + { + grn_timeval tv; + timestamp[0] = '\0'; + grn_timeval_now(ctx, &tv); + grn_timeval2str(ctx, &tv, timestamp, TIMESTAMP_BUFFER_SIZE); + } + + if (flag & (GRN_QUERY_LOG_COMMAND | GRN_QUERY_LOG_DESTINATION)) { + grn_snprintf(info, INFO_BUFFER_SIZE, INFO_BUFFER_SIZE, + "%p|%s", ctx, mark); + info[INFO_BUFFER_SIZE - 1] = '\0'; + } else { + grn_timeval tv; + uint64_t elapsed_time; + grn_timeval_now(ctx, &tv); + elapsed_time = + (uint64_t)(tv.tv_sec - ctx->impl->tv.tv_sec) * GRN_TIME_NSEC_PER_SEC + + (tv.tv_nsec - ctx->impl->tv.tv_nsec); + + grn_snprintf(info, INFO_BUFFER_SIZE, INFO_BUFFER_SIZE, + "%p|%s%015" GRN_FMT_INT64U " ", ctx, mark, elapsed_time); + info[INFO_BUFFER_SIZE - 1] = '\0'; + } + + { + va_list args; + + va_start(args, format); + GRN_BULK_REWIND(message); + grn_text_vprintf(ctx, message, format, args); + va_end(args); + GRN_TEXT_PUTC(ctx, message, '\0'); + } + + current_query_logger.log(ctx, flag, timestamp, info, GRN_TEXT_VALUE(message), + current_query_logger.user_data); +} + +void +grn_query_logger_init(void) +{ + current_query_logger = default_query_logger; + CRITICAL_SECTION_INIT(default_query_logger_lock); + + query_logger_inited = GRN_TRUE; +} + +void +grn_query_logger_fin(grn_ctx *ctx) +{ + current_query_logger_fin(ctx); + if (default_query_logger_path) { + free(default_query_logger_path); + default_query_logger_path = NULL; + } + CRITICAL_SECTION_FIN(default_query_logger_lock); + + query_logger_inited = GRN_FALSE; +} + +void +grn_log_reopen(grn_ctx *ctx) +{ + grn_logger_reopen(ctx); + grn_query_logger_reopen(ctx); +} diff --git a/storage/mroonga/vendor/groonga/lib/metadata.rc.in b/storage/mroonga/vendor/groonga/lib/metadata.rc.in new file mode 100644 index 00000000..0c43cd7d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/metadata.rc.in @@ -0,0 +1,28 @@ +#include + +#define LANG_CODE_US_ENGLISH 0x0409 +#define CHARSET_UNICODE 0x04b0 +#define US_ENGLISH_UNICODE "040904b0" + +VS_VERSION_INFO VERSIONINFO +FILEVERSION 0,@GRN_VERSION_RC@ +PRODUCTVERSION 0,@GRN_VERSION_RC@ +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK US_ENGLISH_UNICODE + BEGIN + VALUE "CompanyName", "Groonga project" + VALUE "FileDescription", "Full text search engine library" + VALUE "FileVersion", "@GRN_VERSION@" + VALUE "InternalName", "libgroonga" + VALUE "OriginalFilename", "@GRN_DLL_FILENAME@" + VALUE "ProductName", "libgroonga" + VALUE "ProductVersion", "@GRN_VERSION@" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", LANG_CODE_US_ENGLISH, CHARSET_UNICODE + END +END diff --git a/storage/mroonga/vendor/groonga/lib/mrb.c b/storage/mroonga/vendor/groonga/lib/mrb.c new file mode 100644 index 00000000..f5bb49fb --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb.c @@ -0,0 +1,220 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_mrb.h" +#include "grn_ctx_impl.h" +#include "grn_util.h" + +#include + +#ifdef GRN_WITH_MRUBY +# include +# include +# include +#endif + +#include + +#ifdef WIN32 +# include +#endif /* WIN32 */ + +#define BUFFER_SIZE 2048 +#define E_LOAD_ERROR (mrb_class_get(mrb, "LoadError")) + +static char grn_mrb_ruby_scripts_dir[GRN_ENV_BUFFER_SIZE]; +static grn_bool grn_mrb_order_by_estimated_size_enable = GRN_FALSE; + +void +grn_mrb_init_from_env(void) +{ + grn_getenv("GRN_RUBY_SCRIPTS_DIR", + grn_mrb_ruby_scripts_dir, + GRN_ENV_BUFFER_SIZE); + { + char grn_order_by_estimated_size_enable_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_ORDER_BY_ESTIMATED_SIZE_ENABLE", + grn_order_by_estimated_size_enable_env, + GRN_ENV_BUFFER_SIZE); + if (strcmp(grn_order_by_estimated_size_enable_env, "yes") == 0) { + grn_mrb_order_by_estimated_size_enable = GRN_TRUE; + } else { + grn_mrb_order_by_estimated_size_enable = GRN_FALSE; + } + } +} + +grn_bool +grn_mrb_is_order_by_estimated_size_enabled(void) +{ + return grn_mrb_order_by_estimated_size_enable; +} + +#ifdef GRN_WITH_MRUBY +# ifdef WIN32 +static char *windows_ruby_scripts_dir = NULL; +static char windows_ruby_scripts_dir_buffer[PATH_MAX]; +static const char * +grn_mrb_get_default_system_ruby_scripts_dir(void) +{ + if (!windows_ruby_scripts_dir) { + const char *base_dir; + const char *relative_path = GRN_RELATIVE_RUBY_SCRIPTS_DIR; + size_t base_dir_length; + + base_dir = grn_windows_base_dir(); + base_dir_length = strlen(base_dir); + grn_strcpy(windows_ruby_scripts_dir_buffer, PATH_MAX, base_dir); + grn_strcat(windows_ruby_scripts_dir_buffer, PATH_MAX, "/"); + grn_strcat(windows_ruby_scripts_dir_buffer, PATH_MAX, relative_path); + windows_ruby_scripts_dir = windows_ruby_scripts_dir_buffer; + } + return windows_ruby_scripts_dir; +} + +# else /* WIN32 */ +static const char * +grn_mrb_get_default_system_ruby_scripts_dir(void) +{ + return GRN_RUBY_SCRIPTS_DIR; +} +# endif /* WIN32 */ + +const char * +grn_mrb_get_system_ruby_scripts_dir(grn_ctx *ctx) +{ + if (grn_mrb_ruby_scripts_dir[0]) { + return grn_mrb_ruby_scripts_dir; + } else { + return grn_mrb_get_default_system_ruby_scripts_dir(); + } +} + +static grn_bool +grn_mrb_is_absolute_path(const char *path) +{ + if (path[0] == '/') { + return GRN_TRUE; + } + + if (isalpha((unsigned char)path[0]) && path[1] == ':' && path[2] == '/') { + return GRN_TRUE; + } + + return GRN_FALSE; +} + +static grn_bool +grn_mrb_expand_script_path(grn_ctx *ctx, const char *path, + char *expanded_path, size_t expanded_path_size) +{ + const char *ruby_scripts_dir; + char dir_last_char; + int path_length, max_path_length; + + if (grn_mrb_is_absolute_path(path)) { + expanded_path[0] = '\0'; + } else if (path[0] == '.' && path[1] == '/') { + grn_strcpy(expanded_path, expanded_path_size, ctx->impl->mrb.base_directory); + grn_strcat(expanded_path, expanded_path_size, "/"); + } else { + ruby_scripts_dir = grn_mrb_get_system_ruby_scripts_dir(ctx); + grn_strcpy(expanded_path, expanded_path_size, ruby_scripts_dir); + + dir_last_char = ruby_scripts_dir[strlen(expanded_path) - 1]; + if (dir_last_char != '/') { + grn_strcat(expanded_path, expanded_path_size, "/"); + } + } + + path_length = strlen(path); + max_path_length = PATH_MAX - strlen(expanded_path) - 1; + if (path_length > max_path_length) { + ERR(GRN_INVALID_ARGUMENT, + "script path is too long: %d (max: %d) <%s%s>", + path_length, max_path_length, + expanded_path, path); + return GRN_FALSE; + } + + grn_strcat(expanded_path, expanded_path_size, path); + + return GRN_TRUE; +} + +mrb_value +grn_mrb_load(grn_ctx *ctx, const char *path) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + char expanded_path[PATH_MAX]; + FILE *file; + mrb_value result; + struct mrb_parser_state *parser; + + if (!mrb) { + return mrb_nil_value(); + } + + if (!grn_mrb_expand_script_path(ctx, path, expanded_path, PATH_MAX)) { + return mrb_nil_value(); + } + + file = grn_fopen(expanded_path, "r"); + if (!file) { + mrb_value exception; + SERR("fopen: failed to open mruby script file: <%s>", + expanded_path); + exception = mrb_exc_new(mrb, E_LOAD_ERROR, + ctx->errbuf, strlen(ctx->errbuf)); + mrb->exc = mrb_obj_ptr(exception); + return mrb_nil_value(); + } + + { + char current_base_directory[PATH_MAX]; + char *last_directory; + + grn_strcpy(current_base_directory, PATH_MAX, data->base_directory); + grn_strcpy(data->base_directory, PATH_MAX, expanded_path); + last_directory = strrchr(data->base_directory, '/'); + if (last_directory) { + last_directory[0] = '\0'; + } + + parser = mrb_parser_new(mrb); + mrb_parser_set_filename(parser, expanded_path); + parser->s = parser->send = NULL; + parser->f = file; + mrb_parser_parse(parser, NULL); + fclose(file); + + { + struct RProc *proc; + proc = mrb_generate_code(mrb, parser); + proc->target_class = mrb->object_class; + result = mrb_toplevel_run(mrb, proc); + } + mrb_parser_free(parser); + + grn_strcpy(data->base_directory, PATH_MAX, current_base_directory); + } + + return result; +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/Makefile.am new file mode 100644 index 00000000..0e4db634 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/Makefile.am @@ -0,0 +1,21 @@ +SUBDIRS = \ + scripts + +AM_CPPFLAGS = \ + -I$(top_builddir) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib \ + $(MRUBY_CPPFLAGS) + +AM_CFLAGS = \ + $(NO_STRICT_ALIASING_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(GRN_CFLAGS) \ + $(MESSAGE_PACK_CFLAGS) \ + $(MRUBY_CFLAGS) + +noinst_LTLIBRARIES = libgrnmrb.la + +include sources.am + +CLEANFILES = *.gcno *.gcda diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c new file mode 100644 index 00000000..ef341d3a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.c @@ -0,0 +1,121 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "../grn_db.h" +#include "mrb_ctx.h" +#include "mrb_accessor.h" +#include "mrb_converter.h" + +static struct mrb_data_type mrb_grn_accessor_type = { + "Groonga::Accessor", + NULL +}; + +static mrb_value +mrb_grn_accessor_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_accessor_ptr; + + mrb_get_args(mrb, "o", &mrb_accessor_ptr); + DATA_TYPE(self) = &mrb_grn_accessor_type; + DATA_PTR(self) = mrb_cptr(mrb_accessor_ptr); + return self; +} + +static mrb_value +mrb_grn_accessor_next(mrb_state *mrb, mrb_value self) +{ + grn_accessor *accessor; + + accessor = DATA_PTR(self); + return grn_mrb_value_from_grn_obj(mrb, (grn_obj *)(accessor->next)); +} + +static mrb_value +mrb_grn_accessor_have_next_p(mrb_state *mrb, mrb_value self) +{ + grn_accessor *accessor; + + accessor = DATA_PTR(self); + return mrb_bool_value(accessor->next != NULL); +} + +static mrb_value +mrb_grn_accessor_object(mrb_state *mrb, mrb_value self) +{ + grn_accessor *accessor; + + accessor = DATA_PTR(self); + return grn_mrb_value_from_grn_obj(mrb, accessor->obj); +} + +static mrb_value +mrb_grn_accessor_name(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_rc rc; + grn_obj *accessor; + grn_obj name; + mrb_value mrb_name; + + accessor = DATA_PTR(self); + GRN_TEXT_INIT(&name, 0); + rc = grn_column_name_(ctx, accessor, &name); + if (rc == GRN_SUCCESS) { + mrb_name = mrb_str_new(mrb, GRN_TEXT_VALUE(&name), GRN_TEXT_LEN(&name)); + GRN_OBJ_FIN(ctx, &name); + } else { + mrb_name = mrb_nil_value(); + GRN_OBJ_FIN(ctx, &name); + grn_mrb_ctx_check(mrb); + } + + return mrb_name; +} + +void +grn_mrb_accessor_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Accessor", data->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_accessor_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "next", + mrb_grn_accessor_next, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "have_next?", + mrb_grn_accessor_have_next_p, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "object", + mrb_grn_accessor_object, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "name", + mrb_grn_accessor_name, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h new file mode 100644 index 00000000..4443f7d5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_accessor.h @@ -0,0 +1,33 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" +#include "../grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_accessor_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c new file mode 100644 index 00000000..2d1e84cc --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.c @@ -0,0 +1,92 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_array.h" + +static struct mrb_data_type mrb_grn_array_type = { + "Groonga::Array", + NULL +}; + +static mrb_value +mrb_grn_array_class_create(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *name; + mrb_int name_length; + const char *path = NULL; + mrb_value mrb_value_type; + grn_obj *value_type = NULL; + grn_obj *array; + + mrb_get_args(mrb, "so", &name, &name_length, &mrb_value_type); + if (!mrb_nil_p(mrb_value_type)) { + value_type = DATA_PTR(mrb_value_type); + } + + array = grn_table_create(ctx, + name, name_length, + path, + GRN_TABLE_NO_KEY, + NULL, + value_type); + grn_mrb_ctx_check(mrb); + + return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, array)); +} + +static mrb_value +mrb_grn_array_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_array_ptr; + + mrb_get_args(mrb, "o", &mrb_array_ptr); + DATA_TYPE(self) = &mrb_grn_array_type; + DATA_PTR(self) = mrb_cptr(mrb_array_ptr); + return self; +} + +void +grn_mrb_array_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *table_class; + struct RClass *klass; + + table_class = mrb_class_get_under(mrb, module, "Table"); + klass = mrb_define_class_under(mrb, module, "Array", table_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_class_method(mrb, klass, "create", + mrb_grn_array_class_create, + MRB_ARGS_REQ(2)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_array_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h new file mode 100644 index 00000000..77ef94d5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_array.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_array_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c new file mode 100644 index 00000000..b3c47795 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.c @@ -0,0 +1,373 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include +#include + +#include "../grn_db.h" +#include "mrb_bulk.h" +#include "mrb_object.h" + +static struct mrb_data_type mrb_grn_bulk_type = { + "Groonga::Bulk", + NULL +}; + +grn_obj * +grn_mrb_value_to_bulk(mrb_state *mrb, mrb_value mrb_value_, grn_obj *bulk) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + switch (mrb_type(mrb_value_)) { + case MRB_TT_FALSE : + if (mrb_nil_p(mrb_value_)) { + grn_obj_reinit(ctx, bulk, GRN_DB_VOID, 0); + } else { + grn_obj_reinit(ctx, bulk, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, bulk, GRN_FALSE); + } + break; + case MRB_TT_TRUE : + grn_obj_reinit(ctx, bulk, GRN_DB_BOOL, 0); + GRN_BOOL_SET(ctx, bulk, GRN_TRUE); + break; + case MRB_TT_FIXNUM : + grn_obj_reinit(ctx, bulk, GRN_DB_INT64, 0); + GRN_INT64_SET(ctx, bulk, mrb_fixnum(mrb_value_)); + break; + case MRB_TT_SYMBOL : + { + const char *name; + mrb_int name_length; + + grn_obj_reinit(ctx, bulk, GRN_DB_TEXT, 0); + name = mrb_sym2name_len(mrb, mrb_symbol(mrb_value_), &name_length); + GRN_TEXT_SET(ctx, bulk, name, name_length); + } + break; + case MRB_TT_FLOAT : + grn_obj_reinit(ctx, bulk, GRN_DB_FLOAT, 0); + GRN_FLOAT_SET(ctx, bulk, mrb_float(mrb_value_)); + break; + case MRB_TT_STRING : + grn_obj_reinit(ctx, bulk, GRN_DB_TEXT, + bulk->header.impl_flags & GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET(ctx, bulk, RSTRING_PTR(mrb_value_), RSTRING_LEN(mrb_value_)); + break; + default : + { + struct RClass *klass; + + klass = mrb_class(mrb, mrb_value_); + if (klass == ctx->impl->mrb.builtin.time_class) { + mrb_value mrb_sec; + mrb_value mrb_usec; + + mrb_sec = mrb_funcall(mrb, mrb_value_, "to_i", 0); + mrb_usec = mrb_funcall(mrb, mrb_value_, "usec", 0); + grn_obj_reinit(ctx, bulk, GRN_DB_TIME, 0); + GRN_TIME_SET(ctx, bulk, + GRN_TIME_PACK(mrb_fixnum(mrb_sec), mrb_fixnum(mrb_usec))); + } else { + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "unsupported object to convert to bulk: %S", + mrb_value_); + } + } + break; + } + + return bulk; +} + +mrb_value +grn_mrb_value_from_bulk(mrb_state *mrb, grn_obj *bulk) +{ + mrb_value mrb_value_; + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + if (!bulk) { + return mrb_nil_value(); + } + + switch (bulk->header.domain) { + case GRN_DB_BOOL : + { + grn_bool value; + value = GRN_BOOL_VALUE(bulk); + mrb_value_ = mrb_bool_value(value); + } + break; + case GRN_DB_INT8 : + { + int8_t value; + value = GRN_INT8_VALUE(bulk); + mrb_value_ = mrb_fixnum_value(value); + } + break; + case GRN_DB_UINT8 : + { + uint8_t value; + value = GRN_UINT8_VALUE(bulk); + mrb_value_ = mrb_fixnum_value(value); + } + break; + case GRN_DB_INT16 : + { + int16_t value; + value = GRN_INT16_VALUE(bulk); + mrb_value_ = mrb_fixnum_value(value); + } + break; + case GRN_DB_UINT16 : + { + uint16_t value; + value = GRN_UINT16_VALUE(bulk); + mrb_value_ = mrb_fixnum_value(value); + } + break; + case GRN_DB_INT32 : + { + int32_t value; + value = GRN_INT32_VALUE(bulk); + mrb_value_ = mrb_fixnum_value(value); + } + break; + case GRN_DB_UINT32 : + { + int64_t value; + value = GRN_UINT32_VALUE(bulk); + if (FIXABLE(value)) { + mrb_value_ = mrb_fixnum_value(value); + } else { + mrb_value_ = mrb_float_value(mrb, value); + } + } + break; + case GRN_DB_INT64 : + { + int64_t value; + value = GRN_INT64_VALUE(bulk); + if (FIXABLE(value)) { + mrb_value_ = mrb_fixnum_value(value); + } else { + mrb_value_ = mrb_float_value(mrb, value); + } + } + break; + case GRN_DB_UINT64 : + { + uint64_t value; + value = GRN_UINT64_VALUE(bulk); + if (FIXABLE(value)) { + mrb_value_ = mrb_fixnum_value(value); + } else { + mrb_value_ = mrb_float_value(mrb, value); + } + } + break; + case GRN_DB_FLOAT : + { + double value; + value = GRN_FLOAT_VALUE(bulk); + mrb_value_ = mrb_float_value(mrb, value); + } + break; + case GRN_DB_TIME : + { + int64_t value; + int64_t sec; + int32_t usec; + mrb_value mrb_sec; + + value = GRN_TIME_VALUE(bulk); + GRN_TIME_UNPACK(value, sec, usec); + if (sec > MRB_INT_MAX) { + mrb_sec = mrb_float_value(mrb, sec); + } else { + mrb_sec = mrb_fixnum_value(sec); + } + mrb_value_ = mrb_funcall(mrb, + mrb_obj_value(ctx->impl->mrb.builtin.time_class), + "at", + 2, + mrb_sec, + mrb_fixnum_value(usec)); + } + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + mrb_value_ = mrb_str_new(mrb, + GRN_TEXT_VALUE(bulk), + GRN_TEXT_LEN(bulk)); + break; + default : + { + grn_obj *domain; + grn_bool is_record = GRN_FALSE; + + domain = grn_ctx_at(ctx, bulk->header.domain); + if (domain) { + switch (domain->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + is_record = GRN_TRUE; + break; + default : + break; + } + } + + if (is_record) { + mrb_value_ = mrb_fixnum_value(GRN_RECORD_VALUE(bulk)); + grn_obj_unlink(ctx, domain); + } else { +#define MESSAGE_SIZE 4096 + char message[MESSAGE_SIZE]; + char domain_name[GRN_TABLE_MAX_KEY_SIZE]; + int domain_name_size; + + if (domain) { + domain_name_size = grn_obj_name(ctx, domain, + domain_name, GRN_TABLE_MAX_KEY_SIZE); + grn_obj_unlink(ctx, domain); + } else { + grn_strcpy(domain_name, GRN_TABLE_MAX_KEY_SIZE, "unknown"); + domain_name_size = strlen(domain_name); + } + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "unsupported bulk value type: <%d>(%.*s)", + bulk->header.domain, + domain_name_size, + domain_name); + mrb_raise(mrb, E_RANGE_ERROR, message); + } +#undef MESSAGE_SIZE + } + break; + } + + return mrb_value_; +} + +grn_bool +grn_mrb_bulk_cast(mrb_state *mrb, grn_obj *from, grn_obj *to, grn_id domain_id) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_rc rc; + + grn_obj_reinit(ctx, to, domain_id, 0); + rc = grn_obj_cast(ctx, from, to, GRN_FALSE); + return rc == GRN_SUCCESS; +} + +static mrb_value +mrb_grn_bulk_s_is_true(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_value_; + grn_obj bulk; + grn_bool is_true; + + mrb_get_args(mrb, "o", &mrb_value_); + + GRN_TEXT_INIT(&bulk, GRN_OBJ_DO_SHALLOW_COPY); + grn_mrb_value_to_bulk(mrb, mrb_value_, &bulk); + is_true = grn_obj_is_true(ctx, &bulk); + GRN_OBJ_FIN(ctx, &bulk); + + return mrb_bool_value(is_true); +} + +static mrb_value +mrb_grn_bulk_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_bulk_ptr; + + mrb_get_args(mrb, "o", &mrb_bulk_ptr); + DATA_TYPE(self) = &mrb_grn_bulk_type; + DATA_PTR(self) = mrb_cptr(mrb_bulk_ptr); + return self; +} + +static mrb_value +mrb_grn_bulk_get_domain(mrb_state *mrb, mrb_value self) +{ + grn_obj *bulk; + + bulk = DATA_PTR(self); + return mrb_fixnum_value(bulk->header.domain); +} + +static mrb_value +mrb_grn_bulk_get_value(mrb_state *mrb, mrb_value self) +{ + return grn_mrb_value_from_bulk(mrb, DATA_PTR(self)); +} + +static mrb_value +mrb_grn_bulk_equal(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_other; + + mrb_get_args(mrb, "o", &mrb_other); + + if (!mrb_obj_is_kind_of(mrb, mrb_other, mrb_class(mrb, self))) { + return mrb_false_value(); + } + + return mrb_bool_value(DATA_PTR(self) == DATA_PTR(mrb_other)); +} + +void +grn_mrb_bulk_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Bulk", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_singleton_method(mrb, (struct RObject *)klass, "true?", + mrb_grn_bulk_s_is_true, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_bulk_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "domain", + mrb_grn_bulk_get_domain, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "value", + mrb_grn_bulk_get_value, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "==", + mrb_grn_bulk_equal, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "inspect", + grn_mrb_object_inspect, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h new file mode 100644 index 00000000..f8f14b5f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_bulk.h @@ -0,0 +1,41 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" +#include "../grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_bulk_init(grn_ctx *ctx); + +mrb_value grn_mrb_value_from_bulk(mrb_state *mrb, grn_obj *bulk); +grn_obj *grn_mrb_value_to_bulk(mrb_state *mrb, + mrb_value mrb_value_, + grn_obj *bulk); +grn_bool grn_mrb_bulk_cast(mrb_state *mrb, + grn_obj *from, + grn_obj *to, + grn_id domain_id); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.c new file mode 100644 index 00000000..843350f9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.c @@ -0,0 +1,130 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "../grn_db.h" +#include "../grn_cache.h" +#include "mrb_bulk.h" +#include "mrb_cache.h" + +static struct mrb_data_type mrb_grn_cache_type = { + "Groonga::Cache", + NULL +}; + +static mrb_value +mrb_grn_cache_class_current(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_cache *cache; + mrb_value mrb_cache; + + cache = grn_cache_current_get(ctx); + mrb_cache = mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, cache)); + + return mrb_cache; +} + +static mrb_value +mrb_grn_cache_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_cache_ptr; + + mrb_get_args(mrb, "o", &mrb_cache_ptr); + DATA_TYPE(self) = &mrb_grn_cache_type; + DATA_PTR(self) = mrb_cptr(mrb_cache_ptr); + return self; +} + +static mrb_value +mrb_grn_cache_fetch(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_cache *cache; + char *key; + mrb_int key_size; + grn_rc rc; + grn_obj cache_value; + mrb_value mrb_cache_value; + + cache = DATA_PTR(self); + mrb_get_args(mrb, "s", &key, &key_size); + + GRN_TEXT_INIT(&cache_value, 0); + rc = grn_cache_fetch(ctx, cache, key, key_size, &cache_value); + if (rc == GRN_SUCCESS) { + mrb_cache_value = grn_mrb_value_from_bulk(mrb, &cache_value); + } else { + mrb_cache_value = mrb_nil_value(); + } + GRN_OBJ_FIN(ctx, &cache_value); + + return mrb_cache_value; +} + +static mrb_value +mrb_grn_cache_update(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_cache *cache; + char *key; + mrb_int key_size; + char *value; + mrb_int value_size; + grn_obj value_buffer; + + cache = DATA_PTR(self); + mrb_get_args(mrb, "ss", &key, &key_size, &value, &value_size); + + GRN_TEXT_INIT(&value_buffer, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET(ctx, &value_buffer, value, value_size); + grn_cache_update(ctx, cache, key, key_size, &value_buffer); + GRN_OBJ_FIN(ctx, &value_buffer); + + return mrb_nil_value(); +} + +void +grn_mrb_cache_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Cache", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_class_method(mrb, klass, "current", + mrb_grn_cache_class_current, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_cache_initialize, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "fetch", + mrb_grn_cache_fetch, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "update", + mrb_grn_cache_update, MRB_ARGS_REQ(2)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.h new file mode 100644 index 00000000..14628ba8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_cache.h @@ -0,0 +1,33 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" +#include "../grn_db.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_cache_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c new file mode 100644 index 00000000..b36a42bf --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.c @@ -0,0 +1,173 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include "../grn_proc.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_column.h" +#include "mrb_bulk.h" +#include "mrb_converter.h" + +static mrb_value +mrb_grn_column_class_parse_flags(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *error_message_tag; + char *flags_text; + mrb_int flags_text_size; + grn_column_flags flags; + + mrb_get_args(mrb, "zs", &error_message_tag, &flags_text, &flags_text_size); + + flags = grn_proc_column_parse_flags(ctx, + error_message_tag, + flags_text, + flags_text + flags_text_size); + return mrb_fixnum_value(flags); +} + +static mrb_value +mrb_grn_column_array_reference(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *column; + mrb_int record_id; + grn_obj *column_value; + + column = DATA_PTR(self); + mrb_get_args(mrb, "i", &record_id); + + column_value = grn_obj_get_value(ctx, column, record_id, NULL); + return grn_mrb_value_from_grn_obj(mrb, column_value); +} + +static mrb_value +mrb_grn_column_is_scalar(mrb_state *mrb, mrb_value self) +{ + grn_obj *column; + grn_obj_flags column_type; + + column = DATA_PTR(self); + column_type = (column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK); + + return mrb_bool_value(column_type == GRN_OBJ_COLUMN_SCALAR); +} + +static mrb_value +mrb_grn_column_is_vector(mrb_state *mrb, mrb_value self) +{ + grn_obj *column; + grn_obj_flags column_type; + + column = DATA_PTR(self); + column_type = (column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK); + + return mrb_bool_value(column_type == GRN_OBJ_COLUMN_VECTOR); +} + +static mrb_value +mrb_grn_column_is_index(mrb_state *mrb, mrb_value self) +{ + grn_obj *column; + grn_obj_flags column_type; + + column = DATA_PTR(self); + column_type = (column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK); + + return mrb_bool_value(column_type == GRN_OBJ_COLUMN_INDEX); +} + +static mrb_value +mrb_grn_column_is_locked(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int is_locked; + + is_locked = grn_obj_is_locked(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_bool_value(is_locked != 0); +} + +static mrb_value +mrb_grn_column_get_table(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + + table = grn_column_table(ctx, DATA_PTR(self)); + if (!table) { + return mrb_nil_value(); + } + + return grn_mrb_value_from_grn_obj(mrb, table); +} + +static mrb_value +mrb_grn_column_truncate(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *column; + + column = DATA_PTR(self); + grn_column_truncate(ctx, column); + grn_mrb_ctx_check(mrb); + return mrb_nil_value(); +} + +void +grn_mrb_column_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *object_class = data->object_class; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Column", object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_class_method(mrb, klass, "parse_flags", + mrb_grn_column_class_parse_flags, MRB_ARGS_REQ(2)); + + mrb_define_method(mrb, klass, "[]", + mrb_grn_column_array_reference, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "scalar?", + mrb_grn_column_is_scalar, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "vector?", + mrb_grn_column_is_vector, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "index?", + mrb_grn_column_is_index, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "locked?", + mrb_grn_column_is_locked, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "table", + mrb_grn_column_get_table, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "truncate", + mrb_grn_column_truncate, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h new file mode 100644 index 00000000..110b294c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_column.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_column_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c new file mode 100644 index 00000000..0c9c7481 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.c @@ -0,0 +1,196 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_command.h" + +static struct mrb_data_type mrb_grn_command_type = { + "Groonga::Command", + NULL +}; + +mrb_value +mrb_grn_command_instantiate(grn_ctx *ctx, grn_obj *command) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + mrb_value mrb_name; + struct RClass *command_class; + struct RClass *target_command_class; + mrb_value mrb_target_command_class; + mrb_value mrb_arguments[1]; + + name_size = grn_obj_name(ctx, command, name, GRN_TABLE_MAX_KEY_SIZE); + mrb_name = mrb_str_new(mrb, name, name_size); + + command_class = mrb_class_get_under(mrb, module, "Command"); + mrb_target_command_class = mrb_funcall(mrb, + mrb_obj_value(command_class), + "find_class", 1, mrb_name); + if (mrb_nil_p(mrb_target_command_class)) { + target_command_class = command_class; + } else { + target_command_class = mrb_class_ptr(mrb_target_command_class); + } + mrb_arguments[0] = mrb_cptr_value(mrb, command); + return mrb_obj_new(mrb, target_command_class, 1, mrb_arguments); +} + +static void +mrb_grn_command_run_wrapper(grn_ctx *ctx, + grn_obj *command, + grn_command_input *input, + void *user_data) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + int arena_index; + mrb_value mrb_command; + mrb_value mrb_input; + + arena_index = mrb_gc_arena_save(mrb); + mrb_command = mrb_grn_command_instantiate(ctx, command); + { + struct RClass *command_input_class; + mrb_value mrb_arguments[1]; + command_input_class = mrb_class_get_under(mrb, module, "CommandInput"); + mrb_arguments[0] = mrb_cptr_value(mrb, input); + mrb_input = mrb_obj_new(mrb, command_input_class, 1, mrb_arguments); + } + mrb_funcall(mrb, mrb_command, "run_internal", 1, mrb_input); + if (ctx->rc == GRN_SUCCESS && mrb->exc) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_obj_name(ctx, command, name, GRN_TABLE_MAX_KEY_SIZE); + if (mrb->exc == mrb->nomem_err) { + MERR("failed to allocate memory in mruby: <%.*s>", + name_size, name); + } else { + mrb_value reason; + reason = mrb_funcall(mrb, mrb_obj_value(mrb->exc), "inspect", 0); + ERR(GRN_COMMAND_ERROR, + "failed to run command: <%*.s>: %.*s", + name_size, name, + (int)RSTRING_LEN(reason), RSTRING_PTR(reason)); + } + } + mrb_gc_arena_restore(mrb, arena_index); +} + +static mrb_value +mrb_grn_command_class_register(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_name; + mrb_value *mrb_arguments; + mrb_int n_arguments; + + mrb_get_args(mrb, "Sa", &mrb_name, &mrb_arguments, &n_arguments); + + { + grn_expr_var *vars; + mrb_int i; + + for (i = 0; i < n_arguments; i++) { + mrb_arguments[i] = mrb_convert_type(mrb, mrb_arguments[i], + MRB_TT_STRING, "String", "to_str"); + } + vars = GRN_MALLOCN(grn_expr_var, n_arguments); + for (i = 0; i < n_arguments; i++) { + mrb_value mrb_argument = mrb_arguments[i]; + grn_expr_var *var = &vars[i]; + var->name = RSTRING_PTR(mrb_argument); + var->name_size = RSTRING_LEN(mrb_argument); + GRN_TEXT_INIT(&(var->value), 0); + } + + grn_command_register(ctx, + RSTRING_PTR(mrb_name), + RSTRING_LEN(mrb_name), + mrb_grn_command_run_wrapper, + vars, + n_arguments, + NULL); + + for (i = 0; i < n_arguments; i++) { + grn_expr_var *var = &vars[i]; + GRN_OBJ_FIN(ctx, &(var->value)); + } + GRN_FREE(vars); + } + + grn_mrb_ctx_check(mrb); + + { + grn_mrb_data *data = &(ctx->impl->mrb); + struct RClass *command_class; + command_class = mrb_class_get_under(mrb, data->module, "Command"); + mrb_funcall(mrb, + mrb_obj_value(command_class), + "register_class", 2, mrb_name, klass); + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_command_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_command_ptr; + + mrb_get_args(mrb, "o", &mrb_command_ptr); + DATA_TYPE(self) = &mrb_grn_command_type; + DATA_PTR(self) = mrb_cptr(mrb_command_ptr); + return self; +} + +void +grn_mrb_command_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *procedure_class; + struct RClass *klass; + + procedure_class = mrb_class_get_under(mrb, module, "Procedure"); + klass = mrb_define_class_under(mrb, module, "Command", procedure_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_class_method(mrb, klass, "register", + mrb_grn_command_class_register, + MRB_ARGS_REQ(2)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_command_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h new file mode 100644 index 00000000..1872ca9f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_command_init(grn_ctx *ctx); + +mrb_value grn_mrb_command_instantiate(grn_ctx *ctx, grn_obj *command); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c new file mode 100644 index 00000000..36570fd1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.c @@ -0,0 +1,139 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_converter.h" +#include "mrb_command_input.h" + +static struct mrb_data_type mrb_grn_command_input_type = { + "Groonga::CommandInput", + NULL +}; + +static mrb_value +mrb_grn_command_input_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_command_input_ptr; + + mrb_get_args(mrb, "o", &mrb_command_input_ptr); + DATA_TYPE(self) = &mrb_grn_command_input_type; + DATA_PTR(self) = mrb_cptr(mrb_command_input_ptr); + return self; +} + +static mrb_value +mrb_grn_command_input_array_reference(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_command_input *input; + mrb_value mrb_key_or_offset; + grn_obj *argument; + + input = DATA_PTR(self); + mrb_get_args(mrb, "o", &mrb_key_or_offset); + + switch (mrb_type(mrb_key_or_offset)) { + case MRB_TT_FIXNUM : + { + mrb_int offset = mrb_fixnum(mrb_key_or_offset); + argument = grn_command_input_at(ctx, input, offset); + } + break; + case MRB_TT_SYMBOL : + { + mrb_sym mrb_key_symbol; + const char *key; + mrb_int key_length; + + mrb_key_symbol = mrb_symbol(mrb_key_or_offset); + key = mrb_sym2name_len(mrb, mrb_key_symbol, &key_length); + argument = grn_command_input_get(ctx, input, key, key_length); + } + break; + case MRB_TT_STRING : + { + mrb_value mrb_key = mrb_key_or_offset; + argument = grn_command_input_get(ctx, input, + RSTRING_PTR(mrb_key), + RSTRING_LEN(mrb_key)); + } + break; + default : + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "must be offset (as integer) or key (as symbol or string): %S", + mrb_key_or_offset); + break; + } + + if (!argument) { + return mrb_nil_value(); + } + + if (GRN_TEXT_LEN(argument) == 0) { + return mrb_nil_value(); + } + + return mrb_str_new_static(mrb, + GRN_TEXT_VALUE(argument), + GRN_TEXT_LEN(argument)); +} + +static mrb_value +mrb_grn_command_input_get_arguments(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_command_input *input; + grn_obj *arguments; + + input = DATA_PTR(self); + arguments = grn_command_input_get_arguments(ctx, input); + + return grn_mrb_value_from_grn_obj(mrb, arguments); +} + +void +grn_mrb_command_input_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "CommandInput", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_command_input_initialize, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "[]", + mrb_grn_command_input_array_reference, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "arguments", + mrb_grn_command_input_get_arguments, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h new file mode 100644 index 00000000..7766d819 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_input.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_command_input_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_version.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_version.c new file mode 100644 index 00000000..8c7c0789 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_version.c @@ -0,0 +1,41 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include + +#include "mrb_command_version.h" + +void +grn_mrb_command_version_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *command_version_module; + + command_version_module = mrb_define_module_under(mrb, module, + "CommandVersion"); + + mrb_define_const(mrb, command_version_module, "DEFAULT", + mrb_fixnum_value(GRN_COMMAND_VERSION_DEFAULT)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_version.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_version.h new file mode 100644 index 00000000..167b7cb9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_command_version.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_command_version_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_config.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_config.c new file mode 100644 index 00000000..52c722a4 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_config.c @@ -0,0 +1,90 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include + +#include "../grn_mrb.h" +#include "mrb_config.h" +#include "mrb_ctx.h" + +static mrb_value +config_array_reference(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *key; + mrb_int key_size; + const char *value; + uint32_t value_size; + grn_rc rc; + + mrb_get_args(mrb, "s", &key, &key_size); + + rc = grn_config_get(ctx, key, key_size, &value, &value_size); + if (rc != GRN_SUCCESS) { + grn_mrb_ctx_check(mrb); + } + + if (!value) { + return mrb_nil_value(); + } else { + return mrb_str_new(mrb, value, value_size); + } +} + +static mrb_value +config_array_set(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *key; + mrb_int key_size; + mrb_value mrb_value_; + grn_rc rc; + + mrb_get_args(mrb, "sS", &key, &key_size, &mrb_value_); + + rc = grn_config_set(ctx, + key, key_size, + RSTRING_PTR(mrb_value_), RSTRING_LEN(mrb_value_)); + if (rc != GRN_SUCCESS) { + grn_mrb_ctx_check(mrb); + } + + return mrb_value_; +} + +void +grn_mrb_config_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module; + + module = mrb_define_module_under(mrb, data->module, "Config"); + + mrb_define_singleton_method(mrb, (struct RObject *)module, + "[]", config_array_reference, + MRB_ARGS_REQ(1)); + mrb_define_singleton_method(mrb, (struct RObject *)module, + "[]=", config_array_set, + MRB_ARGS_REQ(2)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_config.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_config.h new file mode 100644 index 00000000..a460db09 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_config.h @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_config_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_content_type.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_content_type.c new file mode 100644 index 00000000..1010a429 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_content_type.c @@ -0,0 +1,49 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include + +#include "mrb_ctx.h" +#include "mrb_content_type.h" + +void +grn_mrb_content_type_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module; + + module = mrb_define_module_under(mrb, data->module, "ContentType"); + + mrb_define_const(mrb, module, "NONE", + mrb_fixnum_value(GRN_CONTENT_NONE)); + mrb_define_const(mrb, module, "TSV", + mrb_fixnum_value(GRN_CONTENT_TSV)); + mrb_define_const(mrb, module, "JSON", + mrb_fixnum_value(GRN_CONTENT_JSON)); + mrb_define_const(mrb, module, "XML", + mrb_fixnum_value(GRN_CONTENT_XML)); + mrb_define_const(mrb, module, "MSGPACK", + mrb_fixnum_value(GRN_CONTENT_MSGPACK)); + mrb_define_const(mrb, module, "GROONGA_COMMAND_LIST", + mrb_fixnum_value(GRN_CONTENT_GROONGA_COMMAND_LIST)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_content_type.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_content_type.h new file mode 100644 index 00000000..094f3df0 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_content_type.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_content_type_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c new file mode 100644 index 00000000..147c47a3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.c @@ -0,0 +1,350 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include "../grn_db.h" +#include + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "mrb_converter.h" +#include "mrb_bulk.h" + +void +grn_mrb_value_to_raw_data_buffer_init(mrb_state *mrb, + grn_mrb_value_to_raw_data_buffer *buffer) +{ + GRN_VOID_INIT(&(buffer->from)); + GRN_VOID_INIT(&(buffer->to)); +} + +void +grn_mrb_value_to_raw_data_buffer_fin(mrb_state *mrb, + grn_mrb_value_to_raw_data_buffer *buffer) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + GRN_OBJ_FIN(ctx, &(buffer->from)); + GRN_OBJ_FIN(ctx, &(buffer->to)); +} + +void +grn_mrb_value_to_raw_data(mrb_state *mrb, + const char *context, + mrb_value mrb_value_, + grn_id domain_id, + grn_mrb_value_to_raw_data_buffer *buffer, + void **raw_value, + unsigned int *raw_value_size) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + enum mrb_vtype mrb_value_type; + grn_bool try_cast = GRN_FALSE; + grn_obj *from_bulk = NULL; + + if (mrb_nil_p(mrb_value_)) { + *raw_value = NULL; + *raw_value_size = 0; + return; + } + + mrb_value_type = mrb_type(mrb_value_); + + switch (mrb_value_type) { + case MRB_TT_STRING : + switch (domain_id) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + *raw_value = RSTRING_PTR(mrb_value_); + *raw_value_size = RSTRING_LEN(mrb_value_); + break; + default : + try_cast = GRN_TRUE; + break; + } + break; + default : + { + struct RClass *klass; + grn_mrb_data *data = &(ctx->impl->mrb); + + klass = mrb_class(mrb, mrb_value_); + if (domain_id == GRN_DB_TIME && + klass == data->builtin.time_class) { + mrb_value mrb_sec; + mrb_value mrb_usec; + + mrb_sec = mrb_funcall(mrb, mrb_value_, "to_i", 0); + mrb_usec = mrb_funcall(mrb, mrb_value_, "usec", 0); + buffer->value.time_value = GRN_TIME_PACK(mrb_fixnum(mrb_sec), + mrb_fixnum(mrb_usec)); + *raw_value = &(buffer->value.time_value); + *raw_value_size = sizeof(buffer->value.time_value); + } else { + try_cast = GRN_TRUE; + if (mrb_value_type == MRB_TT_DATA && + klass == mrb_class_get_under(mrb, data->module, "Bulk")) { + from_bulk = DATA_PTR(mrb_value_); + } + } + } + break; + } + + if (!try_cast) { + return; + } + + if (!from_bulk) { + from_bulk = &(buffer->from); + grn_mrb_value_to_bulk(mrb, mrb_value_, from_bulk); + } + if (!grn_mrb_bulk_cast(mrb, from_bulk, &(buffer->to), domain_id)) { + grn_obj *domain; + char domain_name[GRN_TABLE_MAX_KEY_SIZE]; + int domain_name_size; + + domain = grn_ctx_at(ctx, domain_id); + domain_name_size = grn_obj_name(ctx, domain, domain_name, + GRN_TABLE_MAX_KEY_SIZE); + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "%S: failed to convert to %S: %S", + mrb_str_new_static(mrb, context, strlen(context)), + mrb_str_new_static(mrb, domain_name, domain_name_size), + mrb_funcall(mrb, mrb_value_, "inspect", 0)); + } + *raw_value = GRN_BULK_HEAD(&(buffer->to)); + *raw_value_size = GRN_BULK_VSIZE(&(buffer->to)); +} + +mrb_value +grn_mrb_value_from_raw_data(mrb_state *mrb, + grn_id domain, + void *raw_value, + unsigned int raw_value_size) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_value_; + + switch (domain) { + case GRN_DB_INT32 : + if (raw_value_size == 0) { + mrb_value_ = mrb_fixnum_value(0); + } else { + int32_t value; + value = *((int32_t *)raw_value); + mrb_value_ = mrb_fixnum_value(value); + } + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + mrb_value_ = mrb_str_new(mrb, + raw_value, + raw_value_size); + break; + default : + { + grn_obj *domain_object; +#define MESSAGE_SIZE 4096 + char message[MESSAGE_SIZE]; + char domain_name[GRN_TABLE_MAX_KEY_SIZE]; + int domain_name_size; + + domain_object = grn_ctx_at(ctx, domain); + if (domain_object) { + domain_name_size = grn_obj_name(ctx, domain_object, + domain_name, GRN_TABLE_MAX_KEY_SIZE); + grn_obj_unlink(ctx, domain_object); + } else { + grn_strcpy(domain_name, GRN_TABLE_MAX_KEY_SIZE, "unknown"); + domain_name_size = strlen(domain_name); + } + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "unsupported raw value type: <%d>(%.*s)", + domain, + domain_name_size, + domain_name); + mrb_raise(mrb, E_RANGE_ERROR, message); + } +#undef MESSAGE_SIZE + break; + } + + return mrb_value_; +} + +struct RClass * +grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_mrb_data *data; + struct RClass *klass = NULL; + + data = &(ctx->impl->mrb); + switch (object->header.type) { + case GRN_BULK : + klass = mrb_class_get_under(mrb, data->module, "Bulk"); + break; + case GRN_PTR : + klass = mrb_class_get_under(mrb, data->module, "Pointer"); + break; + case GRN_ACCESSOR : + klass = mrb_class_get_under(mrb, data->module, "Accessor"); + break; + case GRN_COLUMN_FIX_SIZE : + klass = mrb_class_get_under(mrb, data->module, "FixedSizeColumn"); + break; + case GRN_COLUMN_VAR_SIZE : + klass = mrb_class_get_under(mrb, data->module, "VariableSizeColumn"); + break; + case GRN_COLUMN_INDEX : + klass = mrb_class_get_under(mrb, data->module, "IndexColumn"); + break; + case GRN_TYPE : + klass = mrb_class_get_under(mrb, data->module, "Type"); + break; + case GRN_PROC : + klass = mrb_class_get_under(mrb, data->module, "Procedure"); + break; + case GRN_EXPR : + klass = mrb_class_get_under(mrb, data->module, "Expression"); + break; + case GRN_TABLE_NO_KEY : + klass = mrb_class_get_under(mrb, data->module, "Array"); + break; + case GRN_TABLE_HASH_KEY : + klass = mrb_class_get_under(mrb, data->module, "HashTable"); + break; + case GRN_TABLE_PAT_KEY : + klass = mrb_class_get_under(mrb, data->module, "PatriciaTrie"); + break; + case GRN_TABLE_DAT_KEY : + klass = mrb_class_get_under(mrb, data->module, "DoubleArrayTrie"); + break; + case GRN_DB : + klass = mrb_class_get_under(mrb, data->module, "Database"); + break; + case GRN_VOID : + klass = mrb_class_get_under(mrb, data->module, "Void"); + break; + default : + break; + } + + if (!klass) { +#define BUFFER_SIZE 1024 + char buffer[BUFFER_SIZE]; + grn_snprintf(buffer, BUFFER_SIZE, BUFFER_SIZE, + "can't find class for object type: %#x", object->header.type); + mrb_raise(mrb, E_ARGUMENT_ERROR, buffer); +#undef BUFFER_SIZE + } + + return klass; +} + +mrb_value +grn_mrb_value_from_grn_obj(mrb_state *mrb, grn_obj *object) +{ + struct RClass *mrb_class; + mrb_value mrb_new_arguments[1]; + mrb_value mrb_object; + + if (!object) { + return mrb_nil_value(); + } + + mrb_class = grn_mrb_class_from_grn_obj(mrb, object); + mrb_new_arguments[0] = mrb_cptr_value(mrb, object); + mrb_object = mrb_obj_new(mrb, mrb_class, 1, mrb_new_arguments); + return mrb_object; +} + +grn_id +grn_mrb_class_to_type(mrb_state *mrb, struct RClass *klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_id type = GRN_DB_VOID; + + if (klass == mrb->nil_class) { + type = GRN_DB_VOID; + } else if (klass == mrb->true_class || + klass == mrb->false_class) { + type = GRN_DB_BOOL; + } else if (klass == mrb->symbol_class) { + type = GRN_DB_TEXT; + } else if (klass == mrb->fixnum_class) { + type = GRN_DB_INT64; + } else if (klass == mrb->float_class) { + type = GRN_DB_FLOAT; + } else if (klass == mrb->string_class) { + type = GRN_DB_TEXT; + } else if (klass == ctx->impl->mrb.builtin.time_class) { + type = GRN_DB_TIME; + } else { + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "unsupported class: %S", mrb_obj_value(klass)); + } + + return type; +} + +static mrb_value +mrb_grn_converter_class_convert(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *from = &(ctx->impl->mrb.buffer.from); + grn_obj *to = &(ctx->impl->mrb.buffer.to); + mrb_value mrb_from; + mrb_value mrb_to_class; + grn_id to_type; + + mrb_get_args(mrb, "oC", &mrb_from, &mrb_to_class); + + grn_mrb_value_to_bulk(mrb, mrb_from, from); + to_type = grn_mrb_class_to_type(mrb, mrb_class_ptr(mrb_to_class)); + if (!grn_mrb_bulk_cast(mrb, from, to, to_type)) { + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "failed to convert to %S: %S", + mrb_to_class, + mrb_from); + } + + return grn_mrb_value_from_bulk(mrb, to); +} + +void +grn_mrb_converter_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module; + + module = mrb_define_module_under(mrb, data->module, "Converter"); + + mrb_define_class_method(mrb, module, "convert", + mrb_grn_converter_class_convert, + MRB_ARGS_REQ(2)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h new file mode 100644 index 00000000..9b8546dd --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_converter.h @@ -0,0 +1,64 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define GRN_MRB_DATA_PTR(mrb_object) \ + (mrb_nil_p((mrb_object)) ? NULL : DATA_PTR((mrb_object))) + +void grn_mrb_converter_init(grn_ctx *ctx); + +typedef struct { + grn_obj from; + grn_obj to; + union { + int64_t time_value; + } value; +} grn_mrb_value_to_raw_data_buffer; + +void grn_mrb_value_to_raw_data_buffer_init(mrb_state *mrb, + grn_mrb_value_to_raw_data_buffer *buffer); +void grn_mrb_value_to_raw_data_buffer_fin(mrb_state *mrb, + grn_mrb_value_to_raw_data_buffer *buffer); +void grn_mrb_value_to_raw_data(mrb_state *mrb, + const char *context, + mrb_value mrb_value_, + grn_id domain_id, + grn_mrb_value_to_raw_data_buffer *buffer, + void **raw_value, + unsigned int *raw_value_size); +mrb_value grn_mrb_value_from_raw_data(mrb_state *mrb, + grn_id domain, + void *raw_value, + unsigned int raw_value_size); + +struct RClass *grn_mrb_class_from_grn_obj(mrb_state *mrb, grn_obj *object); +mrb_value grn_mrb_value_from_grn_obj(mrb_state *mrb, grn_obj *object); + +grn_id grn_mrb_class_to_grn_type(mrb_state *mrb, struct RClass *klass); +grn_id grn_mrb_value_to_grn_type(mrb_state *mrb, mrb_value value); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c new file mode 100644 index 00000000..e89df53e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.c @@ -0,0 +1,838 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include + +#include "../grn_mrb.h" +#include "mrb_ctx.h" +#include "mrb_bulk.h" +#include "mrb_converter.h" + +static mrb_value +ctx_class_instance(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_ctx; + mrb_sym iv_name; + + iv_name = mrb_intern_lit(mrb, "@instance"); + mrb_ctx = mrb_iv_get(mrb, klass, iv_name); + if (mrb_nil_p(mrb_ctx)) { + struct RBasic *raw_mrb_ctx; + raw_mrb_ctx = mrb_obj_alloc(mrb, MRB_TT_DATA, mrb_class_ptr(klass)); + mrb_ctx = mrb_obj_value(raw_mrb_ctx); + DATA_PTR(mrb_ctx) = ctx; + mrb_iv_set(mrb, klass, iv_name, mrb_ctx); + } + + return mrb_ctx; +} + +static mrb_value +ctx_array_reference(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_id_or_name; + grn_obj *object; + + mrb_get_args(mrb, "o", &mrb_id_or_name); + + if (mrb_nil_p(mrb_id_or_name)) { + return mrb_nil_value(); + } + + if (mrb_fixnum_p(mrb_id_or_name)) { + grn_id id = mrb_fixnum(mrb_id_or_name); + object = grn_ctx_at(ctx, id); + } else { + mrb_value mrb_name; + mrb_name = mrb_convert_type(mrb, mrb_id_or_name, + MRB_TT_STRING, "String", "to_str"); + object = grn_ctx_get(ctx, + RSTRING_PTR(mrb_name), + RSTRING_LEN(mrb_name)); + } + + return grn_mrb_value_from_grn_obj(mrb, object); +} + +static mrb_value +ctx_get_rc(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return mrb_fixnum_value(ctx->rc); +} + +static mrb_value +ctx_set_rc(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int rc; + + mrb_get_args(mrb, "i", &rc); + ctx->rc = rc; + + return mrb_fixnum_value(ctx->rc); +} + +static mrb_value +ctx_get_error_level(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return mrb_fixnum_value(ctx->errlvl); +} + +static mrb_value +ctx_set_error_level(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int error_level; + + mrb_get_args(mrb, "i", &error_level); + ctx->errlvl = error_level; + + return mrb_fixnum_value(ctx->errlvl); +} + +static mrb_value +ctx_get_error_file(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return mrb_str_new_cstr(mrb, ctx->errfile); +} + +static mrb_value +ctx_set_error_file(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value error_file; + + mrb_get_args(mrb, "S", &error_file); + mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@error_file"), error_file); + ctx->errfile = mrb_string_value_cstr(mrb, &error_file); + + return error_file; +} + +static mrb_value +ctx_get_error_line(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return mrb_fixnum_value(ctx->errline); +} + +static mrb_value +ctx_set_error_line(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int error_line; + + mrb_get_args(mrb, "i", &error_line); + ctx->errline = error_line; + + return mrb_fixnum_value(ctx->errline); +} + +static mrb_value +ctx_get_error_method(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return mrb_str_new_cstr(mrb, ctx->errfunc); +} + +static mrb_value +ctx_set_error_method(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value error_method; + + mrb_get_args(mrb, "S", &error_method); + mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@error_method"), error_method); + ctx->errfunc = mrb_string_value_cstr(mrb, &error_method); + + return error_method; +} + +static mrb_value +ctx_get_error_message(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return mrb_str_new_cstr(mrb, ctx->errbuf); +} + +static mrb_value +ctx_set_error_message(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value error_message; + + mrb_get_args(mrb, "S", &error_message); + grn_ctx_log(ctx, "%.*s", + (int)RSTRING_LEN(error_message), + RSTRING_PTR(error_message)); + + return error_message; +} + +static mrb_value +ctx_clear_error(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + ERRCLR(ctx); + + return mrb_nil_value(); +} + +static mrb_value +ctx_get_command_version(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return mrb_fixnum_value(grn_ctx_get_command_version(ctx)); +} + +static mrb_value +ctx_set_command_version(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int command_version; + + mrb_get_args(mrb, "i", &command_version); + grn_ctx_set_command_version(ctx, command_version); + + return mrb_fixnum_value(command_version); +} + +static mrb_value +ctx_get_output(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return grn_mrb_value_from_bulk(mrb, ctx->impl->output.buf); +} + +static mrb_value +ctx_set_output(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_value_; + + mrb_get_args(mrb, "S", &mrb_value_); + GRN_TEXT_SET(ctx, ctx->impl->output.buf, + RSTRING_PTR(mrb_value_), + RSTRING_LEN(mrb_value_)); + + return mrb_value_; +} + +static mrb_value +ctx_get_database(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + return grn_mrb_value_from_grn_obj(mrb, grn_ctx_db(ctx)); +} + +static mrb_value +ctx_is_opened(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int mrb_id; + + mrb_get_args(mrb, "i", &mrb_id); + + return mrb_bool_value(grn_ctx_is_opened(ctx, mrb_id)); +} + +void +grn_mrb_ctx_check(mrb_state *mrb) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_mrb_data *data = &(ctx->impl->mrb); + struct RClass *module = data->module; + struct RClass *error_class = NULL; +#define MESSAGE_SIZE 4096 + char message[MESSAGE_SIZE]; + + switch (ctx->rc) { + case GRN_SUCCESS: + return; + case GRN_END_OF_DATA: + error_class = mrb_class_get_under(mrb, module, "EndOfData"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "end of data: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_UNKNOWN_ERROR: + error_class = mrb_class_get_under(mrb, module, "UnknownError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "unknown error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_OPERATION_NOT_PERMITTED: + error_class = mrb_class_get_under(mrb, module, "OperationNotPermitted"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "operation not permitted: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NO_SUCH_FILE_OR_DIRECTORY: + error_class = mrb_class_get_under(mrb, module, "NoSuchFileOrDirectory"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "no such file or directory: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NO_SUCH_PROCESS: + error_class = mrb_class_get_under(mrb, module, "NoSuchProcess"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "no such process: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_INTERRUPTED_FUNCTION_CALL: + error_class = mrb_class_get_under(mrb, module, "InterruptedFunctionCall"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "interrupted function call: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_INPUT_OUTPUT_ERROR: + error_class = mrb_class_get_under(mrb, module, "InputOutputError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "input output error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NO_SUCH_DEVICE_OR_ADDRESS: + error_class = mrb_class_get_under(mrb, module, "NoSuchDeviceOrAddress"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "no such device or address: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_ARG_LIST_TOO_LONG: + error_class = mrb_class_get_under(mrb, module, "ArgListTooLong"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "arg list too long: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_EXEC_FORMAT_ERROR: + error_class = mrb_class_get_under(mrb, module, "ExecFormatError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "exec format error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_BAD_FILE_DESCRIPTOR: + error_class = mrb_class_get_under(mrb, module, "BadFileDescriptor"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "bad file descriptor: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NO_CHILD_PROCESSES: + error_class = mrb_class_get_under(mrb, module, "NoChildProcesses"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "no child processes: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_RESOURCE_TEMPORARILY_UNAVAILABLE: + error_class = mrb_class_get_under(mrb, module, + "ResourceTemporarilyUnavailable"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "resource temporarily unavailable: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NOT_ENOUGH_SPACE: + error_class = mrb_class_get_under(mrb, module, "NotEnoughSpace"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "not enough space: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_PERMISSION_DENIED: + error_class = mrb_class_get_under(mrb, module, "PermissionDenied"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "permission denied: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_BAD_ADDRESS: + error_class = mrb_class_get_under(mrb, module, "BadAddress"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "bad address: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_RESOURCE_BUSY: + error_class = mrb_class_get_under(mrb, module, "ResourceBusy"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "resource busy: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_FILE_EXISTS: + error_class = mrb_class_get_under(mrb, module, "FileExists"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "file exists: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_IMPROPER_LINK: + error_class = mrb_class_get_under(mrb, module, "ImproperLink"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "improper link: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NO_SUCH_DEVICE: + error_class = mrb_class_get_under(mrb, module, "NoSuchDevice"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "no such device: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NOT_A_DIRECTORY: + error_class = mrb_class_get_under(mrb, module, "NotDirectory"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "not directory: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_IS_A_DIRECTORY: + error_class = mrb_class_get_under(mrb, module, "IsDirectory"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "is directory: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_INVALID_ARGUMENT: + error_class = mrb_class_get_under(mrb, module, "InvalidArgument"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "invalid argument: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_TOO_MANY_OPEN_FILES_IN_SYSTEM: + error_class = mrb_class_get_under(mrb, module, "TooManyOpenFilesInSystem"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "too many open files in system: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_TOO_MANY_OPEN_FILES: + error_class = mrb_class_get_under(mrb, module, "TooManyOpenFiles"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "too many open files: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_INAPPROPRIATE_I_O_CONTROL_OPERATION: + error_class = mrb_class_get_under(mrb, module, + "InappropriateIOControlOperation"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "inappropriate IO control operation: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_FILE_TOO_LARGE: + error_class = mrb_class_get_under(mrb, module, "FileTooLarge"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "file too large: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NO_SPACE_LEFT_ON_DEVICE: + error_class = mrb_class_get_under(mrb, module, "NoSpaceLeftOnDevice"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "no space left on device: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_INVALID_SEEK: + error_class = mrb_class_get_under(mrb, module, "InvalidSeek"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "invalid seek: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_READ_ONLY_FILE_SYSTEM: + error_class = mrb_class_get_under(mrb, module, "ReadOnlyFileSystem"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "read only file system: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_TOO_MANY_LINKS: + error_class = mrb_class_get_under(mrb, module, "TooManyLinks"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "too many links: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_BROKEN_PIPE: + error_class = mrb_class_get_under(mrb, module, "BrokenPipe"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "broken pipe: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_DOMAIN_ERROR: + error_class = mrb_class_get_under(mrb, module, "DomainError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "domain error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_RESULT_TOO_LARGE: + error_class = mrb_class_get_under(mrb, module, "ResultTooLarge"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "result too large: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_RESOURCE_DEADLOCK_AVOIDED: + error_class = mrb_class_get_under(mrb, module, "ResourceDeadlockAvoided"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "resource deadlock avoided: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NO_MEMORY_AVAILABLE: + error_class = mrb_class_get_under(mrb, module, "NoMemoryAvailable"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "no memory available: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_FILENAME_TOO_LONG: + error_class = mrb_class_get_under(mrb, module, "FilenameTooLong"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "filename too long: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NO_LOCKS_AVAILABLE: + error_class = mrb_class_get_under(mrb, module, "NoLocksAvailable"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "no locks available: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_FUNCTION_NOT_IMPLEMENTED: + error_class = mrb_class_get_under(mrb, module, "FunctionNotImplemented"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "function not implemented: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_DIRECTORY_NOT_EMPTY: + error_class = mrb_class_get_under(mrb, module, "DirectoryNotEmpty"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "directory not empty: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_ILLEGAL_BYTE_SEQUENCE: + error_class = mrb_class_get_under(mrb, module, "IllegalByteSequence"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "illegal byte sequence: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_SOCKET_NOT_INITIALIZED: + error_class = mrb_class_get_under(mrb, module, "SocketNotInitialized"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "socket not initialized: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_OPERATION_WOULD_BLOCK: + error_class = mrb_class_get_under(mrb, module, "OperationWouldBlock"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "operation would block: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_ADDRESS_IS_NOT_AVAILABLE: + error_class = mrb_class_get_under(mrb, module, "AddressIsNotAvailable"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "address is not available: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NETWORK_IS_DOWN: + error_class = mrb_class_get_under(mrb, module, "NetworkIsDown"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "network is down: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NO_BUFFER: + error_class = mrb_class_get_under(mrb, module, "NoBuffer"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "no buffer: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_SOCKET_IS_ALREADY_CONNECTED: + error_class = mrb_class_get_under(mrb, module, "SocketIsAlreadyConnected"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "socket is already connected: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_SOCKET_IS_NOT_CONNECTED: + error_class = mrb_class_get_under(mrb, module, "SocketIsNotConnected"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "socket is not connected: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_SOCKET_IS_ALREADY_SHUTDOWNED: + error_class = mrb_class_get_under(mrb, module, "SocketIsAlreadyShutdowned"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "socket is already shutdowned: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_OPERATION_TIMEOUT: + error_class = mrb_class_get_under(mrb, module, "OperationTimeout"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "operation timeout: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_CONNECTION_REFUSED: + error_class = mrb_class_get_under(mrb, module, "ConnectionRefused"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "connection refused: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_RANGE_ERROR: + error_class = mrb_class_get_under(mrb, module, "RangeError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "range error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_TOKENIZER_ERROR: + error_class = mrb_class_get_under(mrb, module, "TokenizerError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "tokenizer error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_FILE_CORRUPT: + error_class = mrb_class_get_under(mrb, module, "FileCorrupt"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "file corrupt: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_INVALID_FORMAT: + error_class = mrb_class_get_under(mrb, module, "InvalidFormat"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "invalid format: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_OBJECT_CORRUPT: + error_class = mrb_class_get_under(mrb, module, "ObjectCorrupt"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "object corrupt: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_TOO_MANY_SYMBOLIC_LINKS: + error_class = mrb_class_get_under(mrb, module, "TooManySymbolicLinks"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "too many symbolic links: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NOT_SOCKET: + error_class = mrb_class_get_under(mrb, module, "NotSocket"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "not socket: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_OPERATION_NOT_SUPPORTED: + error_class = mrb_class_get_under(mrb, module, "OperationNotSupported"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "operation not supported: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_ADDRESS_IS_IN_USE: + error_class = mrb_class_get_under(mrb, module, "AddressIsInUse"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "address is in use: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_ZLIB_ERROR: + error_class = mrb_class_get_under(mrb, module, "ZlibError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "zlib error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_LZ4_ERROR: + error_class = mrb_class_get_under(mrb, module, "LZ4Error"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "LZ4 error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_STACK_OVER_FLOW: + error_class = mrb_class_get_under(mrb, module, "StackOverFlow"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "stack over flow: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_SYNTAX_ERROR: + error_class = mrb_class_get_under(mrb, module, "SyntaxError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "syntax error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_RETRY_MAX: + error_class = mrb_class_get_under(mrb, module, "RetryMax"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "retry max: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_INCOMPATIBLE_FILE_FORMAT: + error_class = mrb_class_get_under(mrb, module, "IncompatibleFileFormat"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "incompatible file format: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_UPDATE_NOT_ALLOWED: + error_class = mrb_class_get_under(mrb, module, "UpdateNotAllowed"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "update not allowed: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_TOO_SMALL_OFFSET: + error_class = mrb_class_get_under(mrb, module, "TooSmallOffset"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "too small offset: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_TOO_LARGE_OFFSET: + error_class = mrb_class_get_under(mrb, module, "TooLargeOffset"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "too large offset: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_TOO_SMALL_LIMIT: + error_class = mrb_class_get_under(mrb, module, "TooSmallLimit"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "too small limit: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_CAS_ERROR: + error_class = mrb_class_get_under(mrb, module, "CASError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "CAS error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_UNSUPPORTED_COMMAND_VERSION: + error_class = mrb_class_get_under(mrb, module, "UnsupportedCommandVersion"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "unsupported command version: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_NORMALIZER_ERROR: + error_class = mrb_class_get_under(mrb, module, "NormalizerError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "normalizer error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_TOKEN_FILTER_ERROR: + error_class = mrb_class_get_under(mrb, module, "TokenFilterError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "token filter error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_COMMAND_ERROR: + error_class = mrb_class_get_under(mrb, module, "CommandError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "command error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_PLUGIN_ERROR: + error_class = mrb_class_get_under(mrb, module, "PluginError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "plugin error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_SCORER_ERROR: + error_class = mrb_class_get_under(mrb, module, "ScorerError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "scorer error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_CANCEL: + error_class = mrb_class_get_under(mrb, module, "Cancel"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "cancel: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_WINDOW_FUNCTION_ERROR: + error_class = mrb_class_get_under(mrb, module, "WindowFunctionError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "window function error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + case GRN_ZSTD_ERROR: + error_class = mrb_class_get_under(mrb, module, "ZstdError"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "Zstandard error: <%s>(%d)", + ctx->errbuf, ctx->rc); + break; + } + + if (!error_class) { + error_class = mrb_class_get_under(mrb, module, "Error"); + grn_snprintf(message, MESSAGE_SIZE, MESSAGE_SIZE, + "unsupported error: <%s>(%d)", + ctx->errbuf, ctx->rc); + } +#undef MESSAGE_SIZE + + mrb_raise(mrb, error_class, message); +} + +void +grn_mrb_ctx_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Context", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_class_method(mrb, klass, "instance", + ctx_class_instance, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "[]", ctx_array_reference, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "rc", ctx_get_rc, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "rc=", ctx_set_rc, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "error_level", ctx_get_error_level, + MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "error_level=", ctx_set_error_level, + MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "error_file", ctx_get_error_file, + MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "error_file=", ctx_set_error_file, + MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "error_line", ctx_get_error_line, + MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "error_line=", ctx_set_error_line, + MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "error_method", ctx_get_error_method, + MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "error_method=", ctx_set_error_method, + MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "error_message", ctx_get_error_message, + MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "error_message=", ctx_set_error_message, + MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "clear_error", ctx_clear_error, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "command_version", + ctx_get_command_version, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "command_version=", + ctx_set_command_version, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "output", + ctx_get_output, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "output=", + ctx_set_output, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "database", ctx_get_database, + MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "opened?", ctx_is_opened, + MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h new file mode 100644 index 00000000..72519ae6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_ctx.h @@ -0,0 +1,33 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_ctx_init(grn_ctx *ctx); +void grn_mrb_ctx_check(mrb_state *mrb); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c new file mode 100644 index 00000000..5ff2bdbe --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.c @@ -0,0 +1,206 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_database.h" +#include "mrb_converter.h" + +static struct mrb_data_type mrb_grn_database_type = { + "Groonga::Database", + NULL +}; + +static mrb_value +mrb_grn_database_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_database_ptr; + + mrb_get_args(mrb, "o", &mrb_database_ptr); + DATA_TYPE(self) = &mrb_grn_database_type; + DATA_PTR(self) = mrb_cptr(mrb_database_ptr); + return self; +} + +static mrb_value +mrb_grn_database_class_open(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *database; + char *path; + + mrb_get_args(mrb, "z", &path); + + database = grn_db_open(ctx, path); + grn_mrb_ctx_check(mrb); + + return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, database)); +} + +static mrb_value +mrb_grn_database_class_create(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *database; + char *path; + + mrb_get_args(mrb, "z", &path); + + database = grn_db_create(ctx, path, NULL); + grn_mrb_ctx_check(mrb); + + return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, database)); +} + +static mrb_value +mrb_grn_database_recover(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + grn_db_recover(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_database_is_locked(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int is_locked; + + is_locked = grn_obj_is_locked(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_bool_value(is_locked != 0); +} + +static mrb_value +mrb_grn_database_get_last_modified(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + uint32_t last_modified; + struct RClass *time_class; + + last_modified = grn_db_get_last_modified(ctx, DATA_PTR(self)); + + time_class = mrb_class_get(mrb, "Time"); + return mrb_funcall(mrb, + mrb_obj_value(time_class), + "at", + 1, + mrb_float_value(mrb, last_modified)); +} + +static mrb_value +mrb_grn_database_is_dirty(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_bool is_dirty; + + is_dirty = grn_db_is_dirty(ctx, DATA_PTR(self)); + + return mrb_bool_value(is_dirty); +} + +static mrb_value +mrb_grn_database_array_reference(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *database; + mrb_value mrb_id_or_key; + + mrb_get_args(mrb, "o", &mrb_id_or_key); + + database = DATA_PTR(self); + + if (mrb_fixnum_p(mrb_id_or_key)) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + name_size = grn_table_get_key(ctx, + grn_ctx_db(ctx), + mrb_fixnum(mrb_id_or_key), + name, + GRN_TABLE_MAX_KEY_SIZE); + if (name_size == 0) { + return mrb_nil_value(); + } else { + return mrb_str_new(mrb, name, name_size); + } + } else { + grn_id name_domain_id = GRN_DB_SHORT_TEXT; + grn_id id; + grn_mrb_value_to_raw_data_buffer buffer; + void *name; + unsigned int name_size; + + grn_mrb_value_to_raw_data_buffer_init(mrb, &buffer); + grn_mrb_value_to_raw_data(mrb, "name", mrb_id_or_key, + name_domain_id, &buffer, + &name, &name_size); + id = grn_table_get(ctx, database, name, name_size); + grn_mrb_value_to_raw_data_buffer_fin(mrb, &buffer); + + if (id == GRN_ID_NIL) { + return mrb_nil_value(); + } else { + return mrb_fixnum_value(id); + } + } +} + +void +grn_mrb_database_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *object_class = data->object_class; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Database", object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_class_method(mrb, klass, "open", + mrb_grn_database_class_open, + MRB_ARGS_REQ(1)); + mrb_define_class_method(mrb, klass, "create", + mrb_grn_database_class_create, + MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_database_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "recover", + mrb_grn_database_recover, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "locked?", + mrb_grn_database_is_locked, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "last_modified", + mrb_grn_database_get_last_modified, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "dirty?", + mrb_grn_database_is_dirty, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "[]", + mrb_grn_database_array_reference, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h new file mode 100644 index 00000000..512e33c9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_database.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_database_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c new file mode 100644 index 00000000..20007fef --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.c @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_double_array_trie.h" + +static struct mrb_data_type mrb_grn_double_array_trie_type = { + "Groonga::DoubleArrayTrie", + NULL +}; + +static mrb_value +mrb_grn_double_array_trie_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_double_array_trie_ptr; + + mrb_get_args(mrb, "o", &mrb_double_array_trie_ptr); + DATA_TYPE(self) = &mrb_grn_double_array_trie_type; + DATA_PTR(self) = mrb_cptr(mrb_double_array_trie_ptr); + return self; +} + +void +grn_mrb_double_array_trie_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *table_class; + struct RClass *klass; + + table_class = mrb_class_get_under(mrb, module, "Table"); + klass = mrb_define_class_under(mrb, module, "DoubleArrayTrie", table_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_double_array_trie_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h new file mode 100644 index 00000000..4e7bd59d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_double_array_trie.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_double_array_trie_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c new file mode 100644 index 00000000..f162d499 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.c @@ -0,0 +1,202 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include + +#include "../grn_mrb.h" +#include "mrb_error.h" + +void +grn_mrb_error_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *error_class; + struct RClass *groonga_error_class; + + error_class = mrb_define_class_under(mrb, module, "Error", + mrb->eStandardError_class); + groonga_error_class = mrb_define_class_under(mrb, module, "GroongaError", + error_class); + + mrb_define_class_under(mrb, module, "EndOfData", + groonga_error_class); + mrb_define_class_under(mrb, module, "UnknownError", + groonga_error_class); + mrb_define_class_under(mrb, module, "OperationNotPermitted", + groonga_error_class); + mrb_define_class_under(mrb, module, "NoSuchFileOrDirectory", + groonga_error_class); + mrb_define_class_under(mrb, module, "NoSuchProcess", + groonga_error_class); + mrb_define_class_under(mrb, module, "InterruptedFunctionCall", + groonga_error_class); + mrb_define_class_under(mrb, module, "InputOutputError", + groonga_error_class); + mrb_define_class_under(mrb, module, "NoSuchDeviceOrAddress", + groonga_error_class); + mrb_define_class_under(mrb, module, "ArgListTooLong", + groonga_error_class); + mrb_define_class_under(mrb, module, "ExecFormatError", + groonga_error_class); + mrb_define_class_under(mrb, module, "BadFileDescriptor", + groonga_error_class); + mrb_define_class_under(mrb, module, "NoChildProcesses", + groonga_error_class); + mrb_define_class_under(mrb, module, "ResourceTemporarilyUnavailable", + groonga_error_class); + mrb_define_class_under(mrb, module, "NotEnoughSpace", + groonga_error_class); + mrb_define_class_under(mrb, module, "PermissionDenied", + groonga_error_class); + mrb_define_class_under(mrb, module, "BadAddress", + groonga_error_class); + mrb_define_class_under(mrb, module, "ResourceBusy", + groonga_error_class); + mrb_define_class_under(mrb, module, "FileExists", + groonga_error_class); + mrb_define_class_under(mrb, module, "ImproperLink", + groonga_error_class); + mrb_define_class_under(mrb, module, "NoSuchDevice", + groonga_error_class); + mrb_define_class_under(mrb, module, "NotDirectory", + groonga_error_class); + mrb_define_class_under(mrb, module, "IsDirectory", + groonga_error_class); + mrb_define_class_under(mrb, module, "InvalidArgument", + groonga_error_class); + mrb_define_class_under(mrb, module, "TooManyOpenFilesInSystem", + groonga_error_class); + mrb_define_class_under(mrb, module, "TooManyOpenFiles", + groonga_error_class); + mrb_define_class_under(mrb, module, "InappropriateIOControlOperation", + groonga_error_class); + mrb_define_class_under(mrb, module, "FileTooLarge", + groonga_error_class); + mrb_define_class_under(mrb, module, "NoSpaceLeftOnDevice", + groonga_error_class); + mrb_define_class_under(mrb, module, "InvalidSeek", + groonga_error_class); + mrb_define_class_under(mrb, module, "ReadOnlyFileSystem", + groonga_error_class); + mrb_define_class_under(mrb, module, "TooManyLinks", + groonga_error_class); + mrb_define_class_under(mrb, module, "BrokenPipe", + groonga_error_class); + mrb_define_class_under(mrb, module, "DomainError", + groonga_error_class); + mrb_define_class_under(mrb, module, "ResultTooLarge", + groonga_error_class); + mrb_define_class_under(mrb, module, "ResourceDeadlockAvoided", + groonga_error_class); + mrb_define_class_under(mrb, module, "NoMemoryAvailable", + groonga_error_class); + mrb_define_class_under(mrb, module, "FilenameTooLong", + groonga_error_class); + mrb_define_class_under(mrb, module, "NoLocksAvailable", + groonga_error_class); + mrb_define_class_under(mrb, module, "FunctionNotImplemented", + groonga_error_class); + mrb_define_class_under(mrb, module, "DirectoryNotEmpty", + groonga_error_class); + mrb_define_class_under(mrb, module, "IllegalByteSequence", + groonga_error_class); + mrb_define_class_under(mrb, module, "SocketNotInitialized", + groonga_error_class); + mrb_define_class_under(mrb, module, "OperationWouldBlock", + groonga_error_class); + mrb_define_class_under(mrb, module, "AddressIsNotAvailable", + groonga_error_class); + mrb_define_class_under(mrb, module, "NetworkIsDown", + groonga_error_class); + mrb_define_class_under(mrb, module, "NoBuffer", + groonga_error_class); + mrb_define_class_under(mrb, module, "SocketIsAlreadyConnected", + groonga_error_class); + mrb_define_class_under(mrb, module, "SocketIsNotConnected", + groonga_error_class); + mrb_define_class_under(mrb, module, "SocketIsAlreadyShutdowned", + groonga_error_class); + mrb_define_class_under(mrb, module, "OperationTimeout", + groonga_error_class); + mrb_define_class_under(mrb, module, "ConnectionRefused", + groonga_error_class); + mrb_define_class_under(mrb, module, "RangeError", + groonga_error_class); + mrb_define_class_under(mrb, module, "TokenizerError", + groonga_error_class); + mrb_define_class_under(mrb, module, "FileCorrupt", + groonga_error_class); + mrb_define_class_under(mrb, module, "InvalidFormat", + groonga_error_class); + mrb_define_class_under(mrb, module, "ObjectCorrupt", + groonga_error_class); + mrb_define_class_under(mrb, module, "TooManySymbolicLinks", + groonga_error_class); + mrb_define_class_under(mrb, module, "NotSocket", + groonga_error_class); + mrb_define_class_under(mrb, module, "OperationNotSupported", + groonga_error_class); + mrb_define_class_under(mrb, module, "AddressIsInUse", + groonga_error_class); + mrb_define_class_under(mrb, module, "ZlibError", + groonga_error_class); + mrb_define_class_under(mrb, module, "LZ4Error", + groonga_error_class); + mrb_define_class_under(mrb, module, "StackOverFlow", + groonga_error_class); + mrb_define_class_under(mrb, module, "SyntaxError", + groonga_error_class); + mrb_define_class_under(mrb, module, "RetryMax", + groonga_error_class); + mrb_define_class_under(mrb, module, "IncompatibleFileFormat", + groonga_error_class); + mrb_define_class_under(mrb, module, "UpdateNotAllowed", + groonga_error_class); + mrb_define_class_under(mrb, module, "TooSmallOffset", + groonga_error_class); + mrb_define_class_under(mrb, module, "TooLargeOffset", + groonga_error_class); + mrb_define_class_under(mrb, module, "TooSmallLimit", + groonga_error_class); + mrb_define_class_under(mrb, module, "CASError", + groonga_error_class); + mrb_define_class_under(mrb, module, "UnsupportedCommandVersion", + groonga_error_class); + mrb_define_class_under(mrb, module, "NormalizerError", + groonga_error_class); + mrb_define_class_under(mrb, module, "TokenFilterError", + groonga_error_class); + mrb_define_class_under(mrb, module, "CommandError", + groonga_error_class); + mrb_define_class_under(mrb, module, "PluginError", + groonga_error_class); + mrb_define_class_under(mrb, module, "ScorerError", + groonga_error_class); + mrb_define_class_under(mrb, module, "Cancel", + groonga_error_class); + mrb_define_class_under(mrb, module, "WindowFunctionError", + groonga_error_class); + mrb_define_class_under(mrb, module, "ZstdError", + groonga_error_class); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h new file mode 100644 index 00000000..917bfec5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_error.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_error_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_eval_context.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_eval_context.c new file mode 100644 index 00000000..fd5be59c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_eval_context.c @@ -0,0 +1,98 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "../grn_mrb.h" +#include "mrb_ctx.h" +#include "mrb_eval_context.h" + +static mrb_value +eval_context_compile(mrb_state *mrb, mrb_value self) +{ + char *script; + mrb_int script_length; + mrbc_context* compile_ctx; + struct mrb_parser_state *parser; + struct RProc *proc; + + mrb_get_args(mrb, "s", &script, &script_length); + + compile_ctx = mrbc_context_new(mrb); + if (!compile_ctx) { + mrb_raise(mrb, E_RUNTIME_ERROR, + "[mruby][eval][compile] failed to allocate context"); + } + compile_ctx->capture_errors = TRUE; + + parser = mrb_parse_nstring(mrb, script, script_length, compile_ctx); + if (!parser) { + mrbc_context_free(mrb, compile_ctx); + mrb_raise(mrb, E_RUNTIME_ERROR, + "[mruby][eval][compile] failed to allocate parser"); + } + if (parser->nerr > 0) { + struct mrb_parser_message *error = &(parser->error_buffer[0]); + mrb_value new_args[1]; + mrb_value exception; + + new_args[0] = mrb_format(mrb, + "line %S:%S: %S", + mrb_fixnum_value(error->lineno), + mrb_fixnum_value(error->column), + mrb_str_new_cstr(mrb, error->message)); + exception = mrb_obj_new(mrb, E_SYNTAX_ERROR, 1, new_args); + mrb_parser_free(parser); + mrbc_context_free(mrb, compile_ctx); + + mrb_exc_raise(mrb, exception); + } + + proc = mrb_generate_code(mrb, parser); + { + mrb_code *iseq = proc->body.irep->iseq; + while (GET_OPCODE(*iseq) != OP_STOP) { + iseq++; + } + *iseq = MKOP_AB(OP_RETURN, 1, OP_R_NORMAL); + } + mrb_parser_free(parser); + mrbc_context_free(mrb, compile_ctx); + return mrb_obj_value(proc); +} + +void +grn_mrb_eval_context_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "EvalContext", mrb->object_class); + + mrb_define_method(mrb, klass, "compile", eval_context_compile, + MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_eval_context.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_eval_context.h new file mode 100644 index 00000000..c277ed5e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_eval_context.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_eval_context_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c new file mode 100644 index 00000000..2b8f6a04 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.c @@ -0,0 +1,1079 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include +#include +#include + +#include "../grn_expr.h" +#include "../grn_proc.h" +#include "../grn_util.h" +#include "../grn_mrb.h" +#include "mrb_accessor.h" +#include "mrb_ctx.h" +#include "mrb_expr.h" +#include "mrb_operator.h" +#include "mrb_converter.h" +#include "mrb_options.h" + +static struct mrb_data_type mrb_grn_scan_info_type = { + "Groonga::ScanInfo", + NULL +}; +static struct mrb_data_type mrb_grn_expr_code_type = { + "Groonga::ExpressionCode", + NULL +}; +static struct mrb_data_type mrb_grn_expression_type = { + "Groonga::Expression", + NULL +}; + +static mrb_value +mrb_grn_scan_info_new(mrb_state *mrb, scan_info *scan_info) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + struct RClass *module = ctx->impl->mrb.module; + struct RClass *klass; + mrb_value mrb_scan_info; + + mrb_scan_info = mrb_cptr_value(mrb, scan_info); + klass = mrb_class_get_under(mrb, module, "ScanInfo"); + return mrb_obj_new(mrb, klass, 1, &mrb_scan_info); +} + +static mrb_value +mrb_grn_expr_code_new(mrb_state *mrb, grn_expr_code *code) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + struct RClass *module = ctx->impl->mrb.module; + struct RClass *klass; + mrb_value mrb_code; + + mrb_code = mrb_cptr_value(mrb, code); + klass = mrb_class_get_under(mrb, module, "ExpressionCode"); + return mrb_obj_new(mrb, klass, 1, &mrb_code); +} + +static mrb_value +mrb_grn_scan_info_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_ptr; + + mrb_get_args(mrb, "o", &mrb_ptr); + DATA_TYPE(self) = &mrb_grn_scan_info_type; + DATA_PTR(self) = mrb_cptr(mrb_ptr); + return self; +} + +static mrb_value +mrb_grn_expr_code_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_code; + + mrb_get_args(mrb, "o", &mrb_code); + DATA_TYPE(self) = &mrb_grn_expr_code_type; + DATA_PTR(self) = mrb_cptr(mrb_code); + return self; +} + +static mrb_value +mrb_grn_scan_info_put_index(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + scan_info *si; + mrb_value mrb_index; + mrb_int sid; + mrb_int weight; + mrb_value mrb_scorer; + mrb_value mrb_scorer_args_expr; + mrb_int scorer_args_expr_offset; + grn_obj *index; + grn_obj *scorer = NULL; + grn_obj *scorer_args_expr = NULL; + + mrb_get_args(mrb, "oiiooi", + &mrb_index, &sid, &weight, + &mrb_scorer, + &mrb_scorer_args_expr, + &scorer_args_expr_offset); + si = DATA_PTR(self); + index = DATA_PTR(mrb_index); + if (!mrb_nil_p(mrb_scorer)) { + scorer = DATA_PTR(mrb_scorer); + } + if (!mrb_nil_p(mrb_scorer_args_expr)) { + scorer_args_expr = DATA_PTR(mrb_scorer_args_expr); + } + grn_scan_info_put_index(ctx, si, index, sid, weight, + scorer, + scorer_args_expr, + scorer_args_expr_offset); + return self; +} + +static mrb_value +mrb_grn_scan_info_get_op(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + grn_operator op; + + si = DATA_PTR(self); + op = grn_scan_info_get_op(si); + return grn_mrb_value_from_operator(mrb, op); +} + +static mrb_value +mrb_grn_scan_info_set_op(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_value mrb_op; + grn_operator op; + + mrb_get_args(mrb, "o", &mrb_op); + si = DATA_PTR(self); + op = grn_mrb_value_to_operator(mrb, mrb_op); + grn_scan_info_set_op(si, op); + return self; +} + +static mrb_value +mrb_grn_scan_info_set_end(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_int end; + + mrb_get_args(mrb, "i", &end); + si = DATA_PTR(self); + grn_scan_info_set_end(si, end); + return self; +} + +static mrb_value +mrb_grn_scan_info_set_query(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_value mrb_query; + + mrb_get_args(mrb, "o", &mrb_query); + si = DATA_PTR(self); + if (mrb_nil_p(mrb_query)) { + grn_scan_info_set_query(si, NULL); + } else { + grn_scan_info_set_query(si, DATA_PTR(mrb_query)); + } + return self; +} + +static mrb_value +mrb_grn_scan_info_set_flags(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_int flags; + + mrb_get_args(mrb, "i", &flags); + si = DATA_PTR(self); + grn_scan_info_set_flags(si, flags); + return self; +} + +static mrb_value +mrb_grn_scan_info_get_flags(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + int flags; + + si = DATA_PTR(self); + flags = grn_scan_info_get_flags(si); + return mrb_fixnum_value(flags); +} + +static mrb_value +mrb_grn_scan_info_set_logical_op(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_value mrb_logical_op; + grn_operator logical_op; + + mrb_get_args(mrb, "o", &mrb_logical_op); + si = DATA_PTR(self); + logical_op = grn_mrb_value_to_operator(mrb, mrb_logical_op); + grn_scan_info_set_logical_op(si, logical_op); + return self; +} + +static mrb_value +mrb_grn_scan_info_get_logical_op(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + grn_operator logical_op; + + si = DATA_PTR(self); + logical_op = grn_scan_info_get_logical_op(si); + return grn_mrb_value_from_operator(mrb, logical_op); +} + +static mrb_value +mrb_grn_scan_info_set_max_interval(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_int max_interval; + + mrb_get_args(mrb, "i", &max_interval); + si = DATA_PTR(self); + grn_scan_info_set_max_interval(si, max_interval); + return self; +} + +static mrb_value +mrb_grn_scan_info_get_max_interval(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + int max_interval; + + si = DATA_PTR(self); + max_interval = grn_scan_info_get_max_interval(si); + return mrb_fixnum_value(max_interval); +} + +static mrb_value +mrb_grn_scan_info_set_similarity_threshold(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_int similarity_threshold; + + mrb_get_args(mrb, "i", &similarity_threshold); + si = DATA_PTR(self); + grn_scan_info_set_similarity_threshold(si, similarity_threshold); + return self; +} + +static mrb_value +mrb_grn_scan_info_get_similarity_threshold(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + int similarity_threshold; + + si = DATA_PTR(self); + similarity_threshold = grn_scan_info_get_similarity_threshold(si); + return mrb_fixnum_value(similarity_threshold); +} + +static mrb_value +mrb_grn_scan_info_get_arg(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + scan_info *si; + mrb_int index; + grn_obj *arg; + + mrb_get_args(mrb, "i", &index); + + si = DATA_PTR(self); + arg = grn_scan_info_get_arg(ctx, si, index); + + return grn_mrb_value_from_grn_obj(mrb, arg); +} + +static mrb_value +mrb_grn_scan_info_push_arg(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_value mrb_arg; + grn_bool success; + + mrb_get_args(mrb, "o", &mrb_arg); + + si = DATA_PTR(self); + success = grn_scan_info_push_arg(si, DATA_PTR(mrb_arg)); + + return mrb_bool_value(success); +} + +static mrb_value +mrb_grn_scan_info_get_start_position(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + int start_position; + + si = DATA_PTR(self); + start_position = grn_scan_info_get_start_position(si); + return mrb_fixnum_value(start_position); +} + +static mrb_value +mrb_grn_scan_info_set_start_position(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + mrb_int start_position; + + mrb_get_args(mrb, "i", &start_position); + si = DATA_PTR(self); + grn_scan_info_set_start_position(si, start_position); + return self; +} + +static mrb_value +mrb_grn_scan_info_reset_position(mrb_state *mrb, mrb_value self) +{ + scan_info *si; + + si = DATA_PTR(self); + grn_scan_info_reset_position(si); + return self; +} + +static mrb_value +mrb_grn_expr_code_inspect(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_expr_code *code; + mrb_value inspected; + + code = DATA_PTR(self); + + inspected = mrb_str_buf_new(mrb, 48); + + mrb_str_cat_lit(mrb, inspected, "#<"); + mrb_str_cat_cstr(mrb, inspected, mrb_obj_classname(mrb, self)); + mrb_str_cat_lit(mrb, inspected, ":"); + mrb_str_concat(mrb, inspected, mrb_ptr_to_str(mrb, mrb_cptr(self))); + + { + int32_t weight; + uint32_t offset; + + weight = grn_expr_code_get_weight(ctx, DATA_PTR(self), &offset); + + mrb_str_cat_lit(mrb, inspected, " weight="); + mrb_str_concat(mrb, inspected, + mrb_funcall(mrb, + mrb_fixnum_value(weight), + "inspect", + 0)); + mrb_str_cat_lit(mrb, inspected, ", offset="); + mrb_str_concat(mrb, inspected, + mrb_funcall(mrb, + mrb_fixnum_value(offset), + "inspect", + 0)); + } + + mrb_str_cat_lit(mrb, inspected, ", n_args="); + mrb_str_concat(mrb, inspected, + mrb_funcall(mrb, + mrb_fixnum_value(code->nargs), + "inspect", + 0)); + + mrb_str_cat_lit(mrb, inspected, ", modify="); + mrb_str_concat(mrb, inspected, + mrb_funcall(mrb, + mrb_fixnum_value(code->modify), + "inspect", + 0)); + + mrb_str_cat_lit(mrb, inspected, ", op="); + mrb_str_concat(mrb, inspected, + mrb_funcall(mrb, + grn_mrb_value_from_operator(mrb, code->op), + "inspect", + 0)); + + mrb_str_cat_lit(mrb, inspected, ", flags="); + mrb_str_concat(mrb, inspected, + mrb_funcall(mrb, + mrb_fixnum_value(code->flags), + "inspect", + 0)); + + mrb_str_cat_lit(mrb, inspected, ", value="); + mrb_str_concat(mrb, inspected, + mrb_funcall(mrb, + grn_mrb_value_from_grn_obj(mrb, code->value), + "inspect", + 0)); + + mrb_str_cat_lit(mrb, inspected, ">"); + + return inspected; +} + +static mrb_value +mrb_grn_expr_code_get_weight(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + int32_t weight; + uint32_t offset; + mrb_value mrb_values[2]; + + weight = grn_expr_code_get_weight(ctx, DATA_PTR(self), &offset); + mrb_values[0] = mrb_fixnum_value(weight); + mrb_values[1] = mrb_fixnum_value(offset); + return mrb_ary_new_from_values(mrb, 2, mrb_values); +} + +static mrb_value +mrb_grn_expr_code_get_value(mrb_state *mrb, mrb_value self) +{ + grn_expr_code *expr_code; + + expr_code = DATA_PTR(self); + return grn_mrb_value_from_grn_obj(mrb, expr_code->value); +} + +static mrb_value +mrb_grn_expr_code_get_n_args(mrb_state *mrb, mrb_value self) +{ + grn_expr_code *expr_code; + + expr_code = DATA_PTR(self); + return mrb_fixnum_value(expr_code->nargs); +} + +static mrb_value +mrb_grn_expr_code_get_op(mrb_state *mrb, mrb_value self) +{ + grn_expr_code *expr_code; + + expr_code = DATA_PTR(self); + return grn_mrb_value_from_operator(mrb, expr_code->op); +} + +static mrb_value +mrb_grn_expr_code_get_flags(mrb_state *mrb, mrb_value self) +{ + grn_expr_code *expr_code; + + expr_code = DATA_PTR(self); + return mrb_fixnum_value(expr_code->flags); +} + +static mrb_value +mrb_grn_expr_code_get_modify(mrb_state *mrb, mrb_value self) +{ + grn_expr_code *expr_code; + + expr_code = DATA_PTR(self); + return mrb_fixnum_value(expr_code->modify); +} + +static mrb_value +mrb_grn_expression_class_create(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_expr; + mrb_value mrb_table; + mrb_value mrb_new_arguments[1]; + grn_obj *expr, *variable = NULL; + + mrb_get_args(mrb, "o", &mrb_table); + if (mrb_nil_p(mrb_table)) { + expr = grn_expr_create(ctx, NULL, 0); + } else { + grn_obj *table = DATA_PTR(mrb_table); + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expr, variable); + } + + if (!expr) { + grn_mrb_ctx_check(mrb); + return mrb_nil_value(); + } + + mrb_new_arguments[0] = mrb_cptr_value(mrb, expr); + mrb_expr = mrb_obj_new(mrb, mrb_class_ptr(klass), 1, mrb_new_arguments); + { + mrb_value mrb_variable = mrb_nil_value(); + if (variable) { + mrb_variable = grn_mrb_value_from_grn_obj(mrb, variable); + } + mrb_iv_set(mrb, mrb_expr, mrb_intern_lit(mrb, "@variable"), mrb_variable); + } + + return mrb_expr; +} + +static mrb_value +mrb_grn_expression_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_expression_ptr; + + mrb_get_args(mrb, "o", &mrb_expression_ptr); + DATA_TYPE(self) = &mrb_grn_expression_type; + DATA_PTR(self) = mrb_cptr(mrb_expression_ptr); + return self; +} + +static mrb_value +mrb_grn_expression_is_empty(mrb_state *mrb, mrb_value self) +{ + grn_expr *expr; + + expr = DATA_PTR(self); + return mrb_bool_value(expr->codes_curr == 0); +} + +static mrb_value +mrb_grn_expression_codes(mrb_state *mrb, mrb_value self) +{ + grn_expr *expr; + mrb_value mrb_codes; + int i; + + expr = DATA_PTR(self); + mrb_codes = mrb_ary_new_capa(mrb, expr->codes_curr); + for (i = 0; i < expr->codes_curr; i++) { + grn_expr_code *code = expr->codes + i; + mrb_ary_push(mrb, mrb_codes, mrb_grn_expr_code_new(mrb, code)); + } + + return mrb_codes; +} + +static mrb_value +mrb_grn_expression_array_reference(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + mrb_value mrb_key; + grn_obj *var; + + mrb_get_args(mrb, "o", &mrb_key); + + expr = DATA_PTR(self); + switch (mrb_type(mrb_key)) { + case MRB_TT_SYMBOL : + { + const char *name; + mrb_int name_length; + + name = mrb_sym2name_len(mrb, mrb_symbol(mrb_key), &name_length); + var = grn_expr_get_var(ctx, expr, name, name_length); + } + break; + case MRB_TT_STRING : + var = grn_expr_get_var(ctx, expr, + RSTRING_PTR(mrb_key), RSTRING_LEN(mrb_key)); + break; + case MRB_TT_FIXNUM : + var = grn_expr_get_var_by_offset(ctx, expr, mrb_fixnum(mrb_key)); + break; + default : + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "key must be Symbol, String or Fixnum: %S", + mrb_key); + break; + } + + return grn_mrb_value_from_grn_obj(mrb, var); +} + +static mrb_value +mrb_grn_expression_set_condition(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + mrb_value mrb_condition; + grn_obj *condition_ptr; + + mrb_get_args(mrb, "o", &mrb_condition); + + expr = DATA_PTR(self); + condition_ptr = grn_expr_get_or_add_var(ctx, + expr, + GRN_SELECT_INTERNAL_VAR_CONDITION, + GRN_SELECT_INTERNAL_VAR_CONDITION_LEN); + GRN_OBJ_FIN(ctx, condition_ptr); + GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT); + GRN_PTR_SET(ctx, condition_ptr, GRN_MRB_DATA_PTR(mrb_condition)); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_expression_take_object(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + mrb_value mrb_object; + grn_obj *grn_object; + + mrb_get_args(mrb, "o", &mrb_object); + expr = DATA_PTR(self); + grn_object = DATA_PTR(mrb_object); + grn_expr_take_obj(ctx, expr, grn_object); + + return mrb_object; +} + +static mrb_value +mrb_grn_expression_allocate_constant(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + mrb_value mrb_object; + grn_obj *grn_object; + + mrb_get_args(mrb, "o", &mrb_object); + expr = DATA_PTR(self); + + switch (mrb_type(mrb_object)) { + case MRB_TT_STRING: + grn_object = grn_expr_alloc_const(ctx, expr); + if (!grn_object) { + grn_mrb_ctx_check(mrb); + } + GRN_TEXT_INIT(grn_object, 0); + GRN_TEXT_SET(ctx, grn_object, + RSTRING_PTR(mrb_object), RSTRING_LEN(mrb_object)); + break; + case MRB_TT_TRUE: + grn_object = grn_expr_alloc_const(ctx, expr); + if (!grn_object) { + grn_mrb_ctx_check(mrb); + } + GRN_BOOL_INIT(grn_object, 0); + GRN_BOOL_SET(ctx, grn_object, GRN_TRUE); + break; + default: + mrb_raisef(mrb, E_ARGUMENT_ERROR, "unsupported type: %S", mrb_object); + break; + } + + return grn_mrb_value_from_grn_obj(mrb, grn_object); +} + +static mrb_value +mrb_grn_expression_parse(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + char *query; + mrb_int query_size; + grn_obj *default_column = NULL; + grn_operator default_mode = GRN_OP_MATCH; + grn_operator default_operator = GRN_OP_AND; + grn_expr_flags flags = GRN_EXPR_SYNTAX_SCRIPT; + mrb_value mrb_options = mrb_nil_value(); + + expr = DATA_PTR(self); + mrb_get_args(mrb, "s|H", &query, &query_size, &mrb_options); + + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_default_column; + mrb_value mrb_flags; + + mrb_default_column = + grn_mrb_options_get_lit(mrb, mrb_options, "default_column"); + default_column = GRN_MRB_DATA_PTR(mrb_default_column); + + mrb_flags = grn_mrb_options_get_lit(mrb, mrb_options, "flags"); + if (!mrb_nil_p(mrb_flags)) { + flags = mrb_fixnum(mrb_flags); + } + } + + grn_expr_parse(ctx, expr, query, query_size, default_column, + default_mode, default_operator, flags); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_expression_append_object(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + mrb_value mrb_object; + grn_obj *object; + mrb_value mrb_op; + grn_operator op; + mrb_int n_args; + + expr = DATA_PTR(self); + mrb_get_args(mrb, "ooi", &mrb_object, &mrb_op, &n_args); + + object = DATA_PTR(mrb_object); + op = grn_mrb_value_to_operator(mrb, mrb_op); + grn_expr_append_obj(ctx, expr, object, op, n_args); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_expression_append_constant(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + mrb_value mrb_constant; + mrb_value mrb_op; + grn_operator op; + mrb_int n_args; + + expr = DATA_PTR(self); + mrb_get_args(mrb, "ooi", &mrb_constant, &mrb_op, &n_args); + + op = grn_mrb_value_to_operator(mrb, mrb_op); + switch (mrb_type(mrb_constant)) { + case MRB_TT_FALSE : + if (mrb_nil_p(mrb_constant)) { + grn_obj constant; + GRN_VOID_INIT(&constant); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } else { + grn_obj constant; + GRN_BOOL_INIT(&constant, 0); + GRN_BOOL_SET(ctx, &constant, GRN_FALSE); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } + break; + case MRB_TT_TRUE : + { + grn_obj constant; + GRN_BOOL_INIT(&constant, 0); + GRN_BOOL_SET(ctx, &constant, GRN_TRUE); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } + break; + case MRB_TT_FIXNUM : + grn_expr_append_const_int(ctx, expr, mrb_fixnum(mrb_constant), op, n_args); + break; + case MRB_TT_SYMBOL : + { + const char *value; + mrb_int value_length; + + value = mrb_sym2name_len(mrb, mrb_symbol(mrb_constant), &value_length); + grn_expr_append_const_str(ctx, expr, value, value_length, op, n_args); + } + break; + case MRB_TT_FLOAT : + { + grn_obj constant; + GRN_FLOAT_INIT(&constant, 0); + GRN_FLOAT_SET(ctx, &constant, mrb_float(mrb_constant)); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } + break; + case MRB_TT_STRING : + grn_expr_append_const_str(ctx, expr, + RSTRING_PTR(mrb_constant), + RSTRING_LEN(mrb_constant), + op, n_args); + break; + default : + { + struct RClass *klass; + + klass = mrb_class(mrb, mrb_constant); + if (klass == ctx->impl->mrb.builtin.time_class) { + grn_obj constant; + mrb_value mrb_sec; + mrb_value mrb_usec; + + mrb_sec = mrb_funcall(mrb, mrb_constant, "to_i", 0); + mrb_usec = mrb_funcall(mrb, mrb_constant, "usec", 0); + GRN_TIME_INIT(&constant, 0); + GRN_TIME_SET(ctx, &constant, + GRN_TIME_PACK(mrb_fixnum(mrb_sec), mrb_fixnum(mrb_usec))); + grn_expr_append_const(ctx, expr, &constant, op, n_args); + GRN_OBJ_FIN(ctx, &constant); + } else { + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "unsupported constant to append to expression: %S", + mrb_constant); + } + } + break; + } + + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_expression_append_operator(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *expr; + mrb_value mrb_op; + mrb_int n_args; + grn_operator op; + + expr = DATA_PTR(self); + mrb_get_args(mrb, "oi", &mrb_op, &n_args); + + op = grn_mrb_value_to_operator(mrb, mrb_op); + grn_expr_append_op(ctx, expr, op, n_args); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +void +grn_mrb_expr_init(grn_ctx *ctx) +{ + mrb_state *mrb = ctx->impl->mrb.state; + struct RClass *module = ctx->impl->mrb.module; + struct RClass *object_class = ctx->impl->mrb.object_class; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "ScanInfo", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_scan_info_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "put_index", + mrb_grn_scan_info_put_index, MRB_ARGS_REQ(6)); + mrb_define_method(mrb, klass, "op", + mrb_grn_scan_info_get_op, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "op=", + mrb_grn_scan_info_set_op, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "end=", + mrb_grn_scan_info_set_end, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "query=", + mrb_grn_scan_info_set_query, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "flags", + mrb_grn_scan_info_get_flags, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "flags=", + mrb_grn_scan_info_set_flags, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "logical_op", + mrb_grn_scan_info_get_logical_op, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "logical_op=", + mrb_grn_scan_info_set_logical_op, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "max_interval", + mrb_grn_scan_info_get_max_interval, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "max_interval=", + mrb_grn_scan_info_set_max_interval, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "similarity_threshold", + mrb_grn_scan_info_get_similarity_threshold, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "similarity_threshold=", + mrb_grn_scan_info_set_similarity_threshold, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "get_arg", + mrb_grn_scan_info_get_arg, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "push_arg", + mrb_grn_scan_info_push_arg, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "start_position", + mrb_grn_scan_info_get_start_position, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "start_position=", + mrb_grn_scan_info_set_start_position, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "reset_position", + mrb_grn_scan_info_reset_position, MRB_ARGS_NONE()); + + klass = mrb_define_class_under(mrb, module, + "ExpressionCode", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_expr_code_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "inspect", + mrb_grn_expr_code_inspect, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "weight", + mrb_grn_expr_code_get_weight, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "value", + mrb_grn_expr_code_get_value, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "n_args", + mrb_grn_expr_code_get_n_args, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "op", + mrb_grn_expr_code_get_op, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "flags", + mrb_grn_expr_code_get_flags, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "modify", + mrb_grn_expr_code_get_modify, MRB_ARGS_NONE()); + + { + struct RClass *expression_code_class = klass; + struct RClass *flags_module; + flags_module = mrb_define_module_under(mrb, expression_code_class, "Flags"); + mrb_define_const(mrb, flags_module, "RELATIONAL_EXPRESSION", + mrb_fixnum_value(GRN_EXPR_CODE_RELATIONAL_EXPRESSION)); + } + + klass = mrb_define_class_under(mrb, module, "Expression", object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + +#define DEFINE_FLAG(name) \ + mrb_define_const(mrb, klass, \ + #name, \ + mrb_fixnum_value(GRN_EXPR_ ## name)) + + DEFINE_FLAG(SYNTAX_QUERY); + DEFINE_FLAG(SYNTAX_SCRIPT); + DEFINE_FLAG(SYNTAX_OUTPUT_COLUMNS); + DEFINE_FLAG(ALLOW_PRAGMA); + DEFINE_FLAG(ALLOW_COLUMN); + DEFINE_FLAG(ALLOW_UPDATE); + DEFINE_FLAG(ALLOW_LEADING_NOT); + +#undef DEFINE_FLAG + + mrb_define_class_method(mrb, klass, "create", + mrb_grn_expression_class_create, + MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_expression_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "empty?", + mrb_grn_expression_is_empty, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "codes", + mrb_grn_expression_codes, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "[]", + mrb_grn_expression_array_reference, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "condition=", + mrb_grn_expression_set_condition, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "take_object", + mrb_grn_expression_take_object, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "allocate_constant", + mrb_grn_expression_allocate_constant, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "parse", + mrb_grn_expression_parse, MRB_ARGS_ARG(1, 1)); + + mrb_define_method(mrb, klass, "append_object", + mrb_grn_expression_append_object, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, klass, "append_constant", + mrb_grn_expression_append_constant, MRB_ARGS_REQ(3)); + mrb_define_method(mrb, klass, "append_operator", + mrb_grn_expression_append_operator, MRB_ARGS_REQ(2)); +} + +grn_obj * +grn_mrb_expr_rewrite(grn_ctx *ctx, grn_obj *expr) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + mrb_value mrb_expression; + mrb_value mrb_rewritten_expression; + grn_obj *rewritten_expression = NULL; + int arena_index; + + arena_index = mrb_gc_arena_save(mrb); + + mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr); + mrb_rewritten_expression = mrb_funcall(mrb, mrb_expression, "rewrite", 0); + if (mrb_nil_p(mrb_rewritten_expression)) { + goto exit; + } + + if (mrb_type(mrb_rewritten_expression) == MRB_TT_EXCEPTION) { + mrb->exc = mrb_obj_ptr(mrb_rewritten_expression); + mrb_print_error(mrb); + goto exit; + } + + rewritten_expression = DATA_PTR(mrb_rewritten_expression); + +exit: + mrb_gc_arena_restore(mrb, arena_index); + + return rewritten_expression; +} + +scan_info ** +grn_mrb_scan_info_build(grn_ctx *ctx, + grn_obj *expr, + int *n, + grn_operator op, + grn_bool record_exist) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + mrb_value mrb_expression; + mrb_value mrb_sis; + scan_info **sis = NULL; + int i; + int arena_index; + + arena_index = mrb_gc_arena_save(mrb); + + mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr); + mrb_sis = mrb_funcall(mrb, mrb_expression, "build_scan_info", 2, + grn_mrb_value_from_operator(mrb, op), + mrb_bool_value(record_exist)); + + if (mrb_nil_p(mrb_sis)) { + goto exit; + } + + if (mrb_type(mrb_sis) == MRB_TT_EXCEPTION) { + mrb->exc = mrb_obj_ptr(mrb_sis); + mrb_print_error(mrb); + goto exit; + } + + *n = RARRAY_LEN(mrb_sis); + sis = GRN_MALLOCN(scan_info *, *n); + for (i = 0; i < *n; i++) { + mrb_value mrb_si; + mrb_value mrb_si_data; + scan_info *si; + int start; + + mrb_si_data = RARRAY_PTR(mrb_sis)[i]; + start = mrb_fixnum(mrb_funcall(mrb, mrb_si_data, "start", 0)); + si = grn_scan_info_open(ctx, start); + mrb_si = mrb_grn_scan_info_new(mrb, si); + mrb_funcall(mrb, mrb_si, "apply", 1, mrb_si_data); + sis[i] = si; + } + +exit: + mrb_gc_arena_restore(mrb, arena_index); + + return sis; +} + +unsigned int +grn_mrb_expr_estimate_size(grn_ctx *ctx, grn_obj *expr, grn_obj *table) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + mrb_value mrb_expression; + mrb_value mrb_table; + mrb_value mrb_size; + unsigned int size; + int arena_index; + + arena_index = mrb_gc_arena_save(mrb); + + mrb_expression = grn_mrb_value_from_grn_obj(mrb, expr); + mrb_table = grn_mrb_value_from_grn_obj(mrb, table); + mrb_size = mrb_funcall(mrb, mrb_expression, "estimate_size", 1, mrb_table); + if (mrb->exc) { + size = grn_table_size(ctx, table); + } else { + size = mrb_fixnum(mrb_size); + } + + mrb_gc_arena_restore(mrb, arena_index); + + return size; +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h new file mode 100644 index 00000000..22b20220 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_expr.h @@ -0,0 +1,43 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" +#include "../grn_expr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_expr_init(grn_ctx *ctx); + +grn_obj *grn_mrb_expr_rewrite(grn_ctx *ctx, grn_obj *expr); +scan_info **grn_mrb_scan_info_build(grn_ctx *ctx, + grn_obj *expr, + int *n, + grn_operator op, + grn_bool record_exist); +unsigned int grn_mrb_expr_estimate_size(grn_ctx *ctx, + grn_obj *expr, + grn_obj *table); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c new file mode 100644 index 00000000..b1545dbc --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.c @@ -0,0 +1,59 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_fixed_size_column.h" + +static struct mrb_data_type mrb_grn_fixed_size_column_type = { + "Groonga::FixedSizeColumn", + NULL +}; + +static mrb_value +mrb_grn_fixed_size_column_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_fixed_size_column_ptr; + + mrb_get_args(mrb, "o", &mrb_fixed_size_column_ptr); + DATA_TYPE(self) = &mrb_grn_fixed_size_column_type; + DATA_PTR(self) = mrb_cptr(mrb_fixed_size_column_ptr); + return self; +} + +void +grn_mrb_fixed_size_column_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *column_class; + struct RClass *klass; + + column_class = mrb_class_get_under(mrb, module, "Column"); + klass = mrb_define_class_under(mrb, module, "FixedSizeColumn", column_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_fixed_size_column_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h new file mode 100644 index 00000000..9498d337 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_fixed_size_column.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_fixed_size_column_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c new file mode 100644 index 00000000..cf9a0d91 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.c @@ -0,0 +1,117 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_hash_table.h" +#include "mrb_options.h" + +static struct mrb_data_type mrb_grn_hash_table_type = { + "Groonga::HashTable", + NULL +}; + +static mrb_value +mrb_grn_hash_table_class_create(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_options = mrb_nil_value(); + const char *name = NULL; + unsigned int name_size = 0; + const char *path = NULL; + grn_obj_flags flags = GRN_OBJ_TABLE_HASH_KEY; + grn_obj *key_type = NULL; + grn_obj *value_type = NULL; + grn_obj *table; + + mrb_get_args(mrb, "|H", &mrb_options); + + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_name; + mrb_value mrb_flags; + mrb_value mrb_key_type; + mrb_value mrb_value_type; + + mrb_name = grn_mrb_options_get_lit(mrb, mrb_options, "name"); + if (!mrb_nil_p(mrb_name)) { + name = RSTRING_PTR(mrb_name); + name_size = RSTRING_LEN(mrb_name); + } + + mrb_flags = grn_mrb_options_get_lit(mrb, mrb_options, "flags"); + if (!mrb_nil_p(mrb_flags)) { + flags |= mrb_fixnum(mrb_flags); + } + + mrb_key_type = grn_mrb_options_get_lit(mrb, mrb_options, "key_type"); + if (!mrb_nil_p(mrb_key_type)) { + key_type = DATA_PTR(mrb_key_type); + } + + mrb_value_type = grn_mrb_options_get_lit(mrb, mrb_options, "value_type"); + if (!mrb_nil_p(mrb_value_type)) { + key_type = DATA_PTR(mrb_value_type); + } + } + + table = grn_table_create(ctx, name, name_size, path, flags, + key_type, value_type); + grn_mrb_ctx_check(mrb); + + return mrb_funcall(mrb, klass, "new", 1, mrb_cptr_value(mrb, table)); +} + +static mrb_value +mrb_grn_hash_table_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_hash_table_ptr; + + mrb_get_args(mrb, "o", &mrb_hash_table_ptr); + DATA_TYPE(self) = &mrb_grn_hash_table_type; + DATA_PTR(self) = mrb_cptr(mrb_hash_table_ptr); + return self; +} + +void +grn_mrb_hash_table_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *table_class; + struct RClass *klass; + + table_class = mrb_class_get_under(mrb, module, "Table"); + klass = mrb_define_class_under(mrb, module, "HashTable", table_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_class_method(mrb, klass, "create", + mrb_grn_hash_table_class_create, + MRB_ARGS_OPT(1)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_hash_table_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h new file mode 100644 index 00000000..d6b747f0 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_hash_table.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_hash_table_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c new file mode 100644 index 00000000..d5970fee --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.c @@ -0,0 +1,79 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include + +#include "mrb_id.h" + +void +grn_mrb_id_init(grn_ctx *ctx) +{ + mrb_state *mrb = ctx->impl->mrb.state; + struct RClass *module = ctx->impl->mrb.module; + struct RClass *id_module; + + id_module = mrb_define_module_under(mrb, module, "ID"); + + mrb_define_const(mrb, id_module, "NIL", + mrb_fixnum_value(GRN_ID_NIL)); + mrb_define_const(mrb, id_module, "MAX", + mrb_fixnum_value(GRN_ID_MAX)); + + mrb_define_const(mrb, id_module, "VOID", + mrb_fixnum_value(GRN_DB_VOID)); + mrb_define_const(mrb, id_module, "DB", + mrb_fixnum_value(GRN_DB_DB)); + mrb_define_const(mrb, id_module, "OBJECT", + mrb_fixnum_value(GRN_DB_OBJECT)); + mrb_define_const(mrb, id_module, "BOOL", + mrb_fixnum_value(GRN_DB_BOOL)); + mrb_define_const(mrb, id_module, "INT8", + mrb_fixnum_value(GRN_DB_INT8)); + mrb_define_const(mrb, id_module, "UINT8", + mrb_fixnum_value(GRN_DB_UINT8)); + mrb_define_const(mrb, id_module, "INT16", + mrb_fixnum_value(GRN_DB_INT16)); + mrb_define_const(mrb, id_module, "UINT16", + mrb_fixnum_value(GRN_DB_UINT16)); + mrb_define_const(mrb, id_module, "INT32", + mrb_fixnum_value(GRN_DB_INT32)); + mrb_define_const(mrb, id_module, "UINT32", + mrb_fixnum_value(GRN_DB_UINT32)); + mrb_define_const(mrb, id_module, "INT64", + mrb_fixnum_value(GRN_DB_INT64)); + mrb_define_const(mrb, id_module, "UINT64", + mrb_fixnum_value(GRN_DB_UINT64)); + mrb_define_const(mrb, id_module, "FLOAT", + mrb_fixnum_value(GRN_DB_FLOAT)); + mrb_define_const(mrb, id_module, "TIME", + mrb_fixnum_value(GRN_DB_TIME)); + mrb_define_const(mrb, id_module, "SHORT_TEXT", + mrb_fixnum_value(GRN_DB_SHORT_TEXT)); + mrb_define_const(mrb, id_module, "TEXT", + mrb_fixnum_value(GRN_DB_TEXT)); + mrb_define_const(mrb, id_module, "LONG_TEXT", + mrb_fixnum_value(GRN_DB_LONG_TEXT)); + mrb_define_const(mrb, id_module, "TOKYO_GEO_POINT", + mrb_fixnum_value(GRN_DB_TOKYO_GEO_POINT)); + mrb_define_const(mrb, id_module, "WGS84_GEO_POINT", + mrb_fixnum_value(GRN_DB_WGS84_GEO_POINT)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h new file mode 100644 index 00000000..b5418b73 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_id.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_id_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c new file mode 100644 index 00000000..02a3901b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.c @@ -0,0 +1,199 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include "../grn_ii.h" +#include + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_converter.h" +#include "mrb_index_column.h" +#include "mrb_operator.h" +#include "mrb_options.h" + +static struct mrb_data_type mrb_grn_index_column_type = { + "Groonga::IndexColumn", + NULL +}; + +static mrb_value +mrb_grn_index_column_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_index_column_ptr; + + mrb_get_args(mrb, "o", &mrb_index_column_ptr); + DATA_TYPE(self) = &mrb_grn_index_column_type; + DATA_PTR(self) = mrb_cptr(mrb_index_column_ptr); + return self; +} + +static mrb_value +mrb_grn_index_column_get_lexicon(mrb_state *mrb, mrb_value self) +{ + grn_obj *index_column; + grn_obj *lexicon; + + index_column = DATA_PTR(self); + lexicon = ((grn_ii *)index_column)->lexicon; + + return grn_mrb_value_from_grn_obj(mrb, lexicon); +} + +static mrb_value +mrb_grn_index_column_get_source_ids(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *index_column; + grn_obj source_ids; + unsigned int i, n_ids; + mrb_value mrb_source_ids; + + index_column = DATA_PTR(self); + GRN_RECORD_INIT(&source_ids, GRN_OBJ_VECTOR, GRN_DB_VOID); + grn_obj_get_info(ctx, index_column, GRN_INFO_SOURCE, &source_ids); + n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); + + mrb_source_ids = mrb_ary_new_capa(mrb, n_ids); + for (i = 0; i < n_ids; i++) { + grn_id source_id = GRN_RECORD_VALUE_AT(&source_ids, i); + mrb_ary_push(mrb, mrb_source_ids, mrb_fixnum_value(source_id)); + } + + GRN_OBJ_FIN(ctx, &source_ids); + + return mrb_source_ids; +} + +static mrb_value +mrb_grn_index_column_estimate_size_for_term_id(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *index_column; + mrb_int term_id; + unsigned int size; + + index_column = DATA_PTR(self); + mrb_get_args(mrb, "i", &term_id); + + size = grn_ii_estimate_size(ctx, (grn_ii *)index_column, term_id); + return mrb_fixnum_value(size); +} + +static mrb_value +mrb_grn_index_column_estimate_size_for_query(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *index_column; + grn_obj *lexicon; + mrb_value mrb_query; + void *query; + unsigned int query_size; + grn_mrb_value_to_raw_data_buffer buffer; + mrb_value mrb_options = mrb_nil_value(); + grn_search_optarg optarg; + unsigned int size; + + index_column = DATA_PTR(self); + mrb_get_args(mrb, "o|H", &mrb_query, &mrb_options); + + lexicon = grn_ctx_at(ctx, index_column->header.domain); + grn_mrb_value_to_raw_data_buffer_init(mrb, &buffer); + grn_mrb_value_to_raw_data(mrb, "query", mrb_query, lexicon->header.domain, + &buffer, &query, &query_size); + + memset(&optarg, 0, sizeof(grn_search_optarg)); + optarg.mode = GRN_OP_EXACT; + + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_mode; + + mrb_mode = grn_mrb_options_get_lit(mrb, mrb_options, "mode"); + if (!mrb_nil_p(mrb_mode)) { + optarg.mode = grn_mrb_value_to_operator(mrb, mrb_mode); + } + } + + size = grn_ii_estimate_size_for_query(ctx, (grn_ii *)index_column, + query, query_size, &optarg); + grn_mrb_value_to_raw_data_buffer_fin(mrb, &buffer); + + grn_mrb_ctx_check(mrb); + + return mrb_fixnum_value(size); +} + +static mrb_value +mrb_grn_index_column_estimate_size_for_lexicon_cursor(mrb_state *mrb, + mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *index_column; + mrb_value mrb_lexicon_cursor; + grn_table_cursor *lexicon_cursor; + unsigned int size; + + index_column = DATA_PTR(self); + mrb_get_args(mrb, "o", &mrb_lexicon_cursor); + + lexicon_cursor = DATA_PTR(mrb_lexicon_cursor); + size = grn_ii_estimate_size_for_lexicon_cursor(ctx, + (grn_ii *)index_column, + lexicon_cursor); + return mrb_fixnum_value(size); +} + +void +grn_mrb_index_column_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *column_class; + struct RClass *klass; + + column_class = mrb_class_get_under(mrb, module, "Column"); + klass = mrb_define_class_under(mrb, module, "IndexColumn", column_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_index_column_initialize, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "lexicon", + mrb_grn_index_column_get_lexicon, + MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "source_ids", + mrb_grn_index_column_get_source_ids, + MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "estimate_size_for_term_id", + mrb_grn_index_column_estimate_size_for_term_id, + MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "estimate_size_for_query", + mrb_grn_index_column_estimate_size_for_query, + MRB_ARGS_ARG(1, 1)); + mrb_define_method(mrb, klass, "estimate_size_for_lexicon_cursor", + mrb_grn_index_column_estimate_size_for_lexicon_cursor, + MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h new file mode 100644 index 00000000..085a2d3a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_column.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_index_column_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c new file mode 100644 index 00000000..20f1e64f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.c @@ -0,0 +1,245 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include "../grn_ii.h" +#include "../grn_db.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_index_cursor.h" +#include "mrb_converter.h" +#include "mrb_options.h" + +static struct mrb_data_type mrb_grn_index_cursor_type = { + "Groonga::IndexCursor", + NULL +}; + +static mrb_value +mrb_grn_index_cursor_class_open_raw(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_table_cursor; + mrb_value mrb_index; + mrb_value mrb_options = mrb_nil_value(); + grn_obj *index_cursor; + grn_table_cursor *table_cursor; + grn_obj *index; + grn_id rid_min = GRN_ID_NIL; + grn_id rid_max = GRN_ID_MAX; + int flags = 0; + mrb_value mrb_index_cursor; + + mrb_get_args(mrb, "oo|H", &mrb_table_cursor, &mrb_index, &mrb_options); + + table_cursor = DATA_PTR(mrb_table_cursor); + index = DATA_PTR(mrb_index); + if (!mrb_nil_p(mrb_options)) { + /* TODO */ + } + index_cursor = grn_index_cursor_open(ctx, table_cursor, index, + rid_min, rid_max, flags); + grn_mrb_ctx_check(mrb); + + mrb_index_cursor = mrb_funcall(mrb, klass, "new", 1, + mrb_cptr_value(mrb, index_cursor)); + mrb_iv_set(mrb, mrb_index_cursor, mrb_intern_lit(mrb, "@index"), mrb_index); + return mrb_index_cursor; +} + +static mrb_value +mrb_grn_index_cursor_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_index_cursor_ptr; + + mrb_get_args(mrb, "o", &mrb_index_cursor_ptr); + DATA_TYPE(self) = &mrb_grn_index_cursor_type; + DATA_PTR(self) = mrb_cptr(mrb_index_cursor_ptr); + + return self; +} + +static mrb_value +mrb_grn_index_cursor_close(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *index_cursor; + + index_cursor = DATA_PTR(self); + if (index_cursor) { + DATA_PTR(self) = NULL; + grn_obj_close(ctx, index_cursor); + grn_mrb_ctx_check(mrb); + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_index_cursor_count(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_id term_id; + int n_records = 0; + + while (grn_index_cursor_next(ctx, DATA_PTR(self), &term_id)) { + n_records++; + } + + return mrb_fixnum_value(n_records); +} + +static mrb_value +mrb_grn_index_cursor_select(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_result_set; + mrb_value mrb_options; + grn_obj *index_cursor; + grn_obj *expr = NULL; + grn_obj *expr_variable = NULL; + int offset = 0; + int limit = 10; + int max_n_unmatched_records = -1; + int n_matched_records = 0; + int n_unmatched_records = 0; + mrb_value mrb_index; + grn_obj *index; + grn_obj *lexicon; + grn_obj *data_table; + grn_hash *result_set; + grn_posting *posting; + grn_id term_id; + grn_operator op = GRN_OP_OR; + + mrb_get_args(mrb, "o|H", &mrb_result_set, &mrb_options); + + index_cursor = DATA_PTR(self); + result_set = DATA_PTR(mrb_result_set); + + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_expr; + mrb_value mrb_offset; + mrb_value mrb_limit; + mrb_value mrb_max_n_unmatched_records; + + mrb_expr = grn_mrb_options_get_lit(mrb, mrb_options, "expression"); + if (!mrb_nil_p(mrb_expr)) { + expr = DATA_PTR(mrb_expr); + expr_variable = grn_expr_get_var_by_offset(ctx, expr, 0); + } + + mrb_offset = grn_mrb_options_get_lit(mrb, mrb_options, "offset"); + if (!mrb_nil_p(mrb_offset)) { + offset = mrb_fixnum(mrb_offset); + } + + mrb_limit = grn_mrb_options_get_lit(mrb, mrb_options, "limit"); + if (!mrb_nil_p(mrb_limit)) { + limit = mrb_fixnum(mrb_limit); + } + + mrb_max_n_unmatched_records = + grn_mrb_options_get_lit(mrb, mrb_options, "max_n_unmatched_records"); + if (!mrb_nil_p(mrb_max_n_unmatched_records)) { + max_n_unmatched_records = mrb_fixnum(mrb_max_n_unmatched_records); + } + } + + if (limit <= 0) { + return mrb_fixnum_value(n_matched_records); + } + + mrb_index = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@index")); + index = DATA_PTR(mrb_index); + lexicon = ((grn_ii *)index)->lexicon; + data_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, index)); + + if (max_n_unmatched_records < 0) { + max_n_unmatched_records = INT32_MAX; + } + while ((posting = grn_index_cursor_next(ctx, index_cursor, &term_id))) { + if (expr) { + grn_bool matched_raw = GRN_FALSE; + grn_obj *matched; + + GRN_RECORD_SET(ctx, expr_variable, posting->rid); + matched = grn_expr_exec(ctx, expr, 0); + if (matched) { + matched_raw = grn_obj_is_true(ctx, matched); + } else { + grn_mrb_ctx_check(mrb); + } + + if (!matched_raw) { + n_unmatched_records++; + if (n_unmatched_records > max_n_unmatched_records) { + return mrb_fixnum_value(-1); + } + continue; + } + } + n_matched_records++; + if (offset > 0) { + offset--; + continue; + } + grn_ii_posting_add(ctx, posting, result_set, op); + limit--; + if (limit == 0) { + break; + } + } + grn_ii_resolve_sel_and(ctx, result_set, op); + + return mrb_fixnum_value(n_matched_records); +} + +void +grn_mrb_index_cursor_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "IndexCursor", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_class_method(mrb, klass, "open_raw", + mrb_grn_index_cursor_class_open_raw, + MRB_ARGS_ARG(2, 1)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_index_cursor_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "close", + mrb_grn_index_cursor_close, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "count", + mrb_grn_index_cursor_count, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "select", + mrb_grn_index_cursor_select, MRB_ARGS_ARG(1, 1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h new file mode 100644 index 00000000..c1026002 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_index_cursor.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_index_cursor_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_indexable.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_indexable.c new file mode 100644 index 00000000..cd8f44ae --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_indexable.c @@ -0,0 +1,170 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include "../grn_db.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_indexable.h" +#include "mrb_operator.h" +#include "mrb_converter.h" + +static mrb_value +indexable_find_index(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + mrb_value mrb_operator; + grn_operator operator; + grn_index_datum index_datum; + int n_index_data; + + mrb_get_args(mrb, "o", &mrb_operator); + object = DATA_PTR(self); + operator = grn_mrb_value_to_operator(mrb, mrb_operator); + n_index_data = grn_column_find_index_data(ctx, + object, + operator, + &index_datum, + 1); + if (n_index_data == 0) { + return mrb_nil_value(); + } else { + grn_mrb_data *data; + struct RClass *klass; + mrb_value args[2]; + + data = &(ctx->impl->mrb); + klass = mrb_class_get_under(mrb, data->module, "IndexInfo"); + args[0] = grn_mrb_value_from_grn_obj(mrb, index_datum.index); + args[1] = mrb_fixnum_value(index_datum.section); + return mrb_obj_new(mrb, klass, 2, args); + } +} + +static mrb_value +indexable_indexes(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + grn_index_datum index_datum; + grn_index_datum *index_data; + int i, n_index_data; + mrb_value mrb_indexes; + + object = DATA_PTR(self); + n_index_data = grn_column_get_all_index_data(ctx, object, &index_datum, 1); + if (n_index_data == 0) { + return mrb_ary_new(mrb); + } + + if (n_index_data == 1) { + index_data = &index_datum; + } else { + index_data = GRN_MALLOCN(grn_index_datum, n_index_data); + n_index_data = grn_column_get_all_index_data(ctx, + object, + index_data, + n_index_data); + } + + mrb_indexes = mrb_ary_new_capa(mrb, n_index_data); + for (i = 0; i < n_index_data; i++) { + grn_mrb_data *data; + struct RClass *klass; + mrb_value args[2]; + + data = &(ctx->impl->mrb); + klass = mrb_class_get_under(mrb, data->module, "IndexInfo"); + args[0] = grn_mrb_value_from_grn_obj(mrb, index_data[i].index); + args[1] = mrb_fixnum_value(index_data[i].section); + mrb_ary_push(mrb, mrb_indexes, mrb_obj_new(mrb, klass, 2, args)); + } + + if (index_data != &index_datum) { + GRN_FREE(index_data); + } + + return mrb_indexes; +} + +static mrb_value +indexable_index_ids(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + grn_hook_entry entry; + int i; + int n_indexes; + mrb_value mrb_index_ids; + grn_obj hook_data; + + object = DATA_PTR(self); + + if (grn_obj_is_key_accessor(ctx, object)) { + object = grn_ctx_at(ctx, object->header.domain); + } + if (grn_obj_is_table(ctx, object)) { + entry = GRN_HOOK_INSERT; + } else if (grn_obj_is_column(ctx, object)) { + entry = GRN_HOOK_SET; + } else { + return mrb_ary_new(mrb); + } + n_indexes = grn_obj_get_nhooks(ctx, object, entry); + + mrb_index_ids = mrb_ary_new_capa(mrb, n_indexes); + + GRN_TEXT_INIT(&hook_data, 0); + for (i = 0; i < n_indexes; i++) { + GRN_BULK_REWIND(&hook_data); + grn_obj_get_hook(ctx, object, entry, i, &hook_data); + if (GRN_BULK_VSIZE(&hook_data) == + sizeof(grn_obj_default_set_value_hook_data)) { + grn_obj_default_set_value_hook_data *data; + + data = (grn_obj_default_set_value_hook_data *)GRN_TEXT_VALUE(&hook_data); + mrb_ary_push(mrb, mrb_index_ids, mrb_fixnum_value(data->target)); + } + } + + return mrb_index_ids; +} + +void +grn_mrb_indexable_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module; + + module = mrb_define_module_under(mrb, data->module, "Indexable"); + + mrb_define_method(mrb, module, "find_index", + indexable_find_index, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, module, "indexes", + indexable_indexes, MRB_ARGS_NONE()); + mrb_define_method(mrb, module, "index_ids", + indexable_index_ids, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_indexable.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_indexable.h new file mode 100644 index 00000000..3b191c72 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_indexable.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_indexable_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c new file mode 100644 index 00000000..d5ed72df --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.c @@ -0,0 +1,99 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include + +#include "../grn_mrb.h" +#include "mrb_logger.h" + +static mrb_value +logger_s_get_default_path(mrb_state *mrb, mrb_value self) +{ + return mrb_str_new_cstr(mrb, grn_default_logger_get_path()); +} + +static mrb_value +logger_s_get_default_level(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_level_class; + mrb_value mrb_level; + + mrb_level_class = mrb_const_get(mrb, self, mrb_intern_lit(mrb, "Level")); + mrb_level = mrb_fixnum_value(grn_default_logger_get_max_level()); + return mrb_funcall(mrb, mrb_level_class, "find", 1, mrb_level); +} + +static mrb_value +logger_need_log_p(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int level; + + mrb_get_args(mrb, "i", &level); + + return mrb_bool_value(grn_logger_pass(ctx, level)); +} + +static mrb_value +logger_log(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int level; + char *file; + mrb_int line; + char *method; + char *message; + mrb_int message_size; + + mrb_get_args(mrb, "izizs", + &level, &file, &line, &method, &message, &message_size); + grn_logger_put(ctx, level, file, line, method, + "%.*s", (int)message_size, message); + + return self; +} + +void +grn_mrb_logger_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Logger", mrb->object_class); + + mrb_define_singleton_method(mrb, (struct RObject *)klass, "default_path", + logger_s_get_default_path, MRB_ARGS_NONE()); + mrb_define_singleton_method(mrb, (struct RObject *)klass, "default_level", + logger_s_get_default_level, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "need_log?", logger_need_log_p, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "log", logger_log, MRB_ARGS_REQ(5)); + + grn_mrb_load(ctx, "logger/level.rb"); + grn_mrb_load(ctx, "logger.rb"); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h new file mode 100644 index 00000000..d23ddb19 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_logger.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_logger_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.c new file mode 100644 index 00000000..874d4add --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.c @@ -0,0 +1,346 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include "../grn_util.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "../grn_mrb.h" +#include "mrb_ctx.h" +#include "mrb_object.h" +#include "mrb_operator.h" +#include "mrb_options.h" +#include "mrb_converter.h" + +static mrb_value +object_remove_force(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *name; + mrb_int name_size; + + mrb_get_args(mrb, "s", &name, &name_size); + grn_obj_remove_force(ctx, name, name_size); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +mrb_value +grn_mrb_object_inspect(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + mrb_value inspected; + + object = DATA_PTR(self); + inspected = mrb_str_buf_new(mrb, 48); + + mrb_str_cat_lit(mrb, inspected, "#<"); + mrb_str_cat_cstr(mrb, inspected, mrb_obj_classname(mrb, self)); + mrb_str_cat_lit(mrb, inspected, ":"); + mrb_str_concat(mrb, inspected, mrb_ptr_to_str(mrb, mrb_cptr(self))); + if (object) { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_inspect(ctx, &buffer, object); + mrb_str_cat_lit(mrb, inspected, " "); + mrb_str_cat(mrb, inspected, GRN_TEXT_VALUE(&buffer), GRN_TEXT_LEN(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + } else { + mrb_str_cat_lit(mrb, inspected, " (closed)"); + } + mrb_str_cat_lit(mrb, inspected, ">"); + + return inspected; +} + +static mrb_value +object_get_id(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_id id; + + id = grn_obj_id(ctx, DATA_PTR(self)); + + return mrb_fixnum_value(id); +} + +static mrb_value +object_get_name(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_length; + + object = DATA_PTR(self); + name_length = grn_obj_name(ctx, object, name, GRN_TABLE_MAX_KEY_SIZE); + + if (name_length == 0) { + return mrb_nil_value(); + } else { + return mrb_str_new(mrb, name, name_length); + } +} + +static mrb_value +object_get_path(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + const char *path; + + object = DATA_PTR(self); + path = grn_obj_path(ctx, object); + + if (path) { + return mrb_str_new_cstr(mrb, path); + } else { + return mrb_nil_value(); + } +} + +static mrb_value +object_grn_inspect(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj buffer; + mrb_value inspected; + + GRN_TEXT_INIT(&buffer, 0); + grn_inspect(ctx, &buffer, DATA_PTR(self)); + inspected = mrb_str_new(mrb, GRN_TEXT_VALUE(&buffer), GRN_TEXT_LEN(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + + return inspected; +} + +static mrb_value +object_equal(mrb_state *mrb, mrb_value self) +{ + grn_obj *object, *other_object; + mrb_value mrb_other; + + mrb_get_args(mrb, "o", &mrb_other); + if (!mrb_obj_is_kind_of(mrb, mrb_other, mrb_obj_class(mrb, self))) { + return mrb_false_value(); + } + + object = DATA_PTR(self); + other_object = DATA_PTR(mrb_other); + return mrb_bool_value(object == other_object); +} + +static mrb_value +object_hash(mrb_state *mrb, mrb_value self) +{ + grn_obj *object; + + object = DATA_PTR(self); + return mrb_fixnum_value((mrb_int)((uint64_t)object)); +} + +static mrb_value +object_close(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + + object = DATA_PTR(self); + if (!object) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "already closed object"); + } + + grn_obj_close(ctx, object); + DATA_PTR(self) = NULL; + + return mrb_nil_value(); +} + +static mrb_value +object_remove(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_options = mrb_nil_value(); + grn_bool dependent = GRN_FALSE; + grn_obj *object; + + mrb_get_args(mrb, "|H", &mrb_options); + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_dependent; + mrb_dependent = grn_mrb_options_get_lit(mrb, mrb_options, "dependent"); + dependent = mrb_test(mrb_dependent); + } + + object = DATA_PTR(self); + if (dependent) { + grn_obj_remove_dependent(ctx, object); + } else { + grn_obj_remove(ctx, object); + } + grn_mrb_ctx_check(mrb); + + DATA_PTR(self) = NULL; + + return mrb_nil_value(); +} + +static mrb_value +object_is_closed(mrb_state *mrb, mrb_value self) +{ + grn_obj *object; + + object = DATA_PTR(self); + return mrb_bool_value(object == NULL); +} + +static mrb_value +object_get_domain_id(mrb_state *mrb, mrb_value self) +{ + grn_obj *object; + grn_id domain_id; + + object = DATA_PTR(self); + domain_id = object->header.domain; + + if (domain_id == GRN_ID_NIL) { + return mrb_nil_value(); + } else { + return mrb_fixnum_value(domain_id); + } +} + +static mrb_value +object_get_range_id(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + grn_id range_id; + + object = DATA_PTR(self); + range_id = grn_obj_get_range(ctx, object); + + if (range_id == GRN_ID_NIL) { + return mrb_nil_value(); + } else { + return mrb_fixnum_value(range_id); + } +} + +static mrb_value +object_is_temporary(mrb_state *mrb, mrb_value self) +{ + grn_obj *object; + grn_obj_flags flags; + + object = DATA_PTR(self); + flags = object->header.flags; + return mrb_bool_value((flags & GRN_OBJ_PERSISTENT) != GRN_OBJ_PERSISTENT); +} + +static mrb_value +object_is_persistent(mrb_state *mrb, mrb_value self) +{ + grn_obj *object; + grn_obj_flags flags; + + object = DATA_PTR(self); + flags = object->header.flags; + return mrb_bool_value((flags & GRN_OBJ_PERSISTENT) == GRN_OBJ_PERSISTENT); +} + +static mrb_value +object_is_true(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + + object = DATA_PTR(self); + return mrb_bool_value(grn_obj_is_true(ctx, object)); +} + +static mrb_value +object_check_corrupt(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *object; + grn_bool is_corrupt; + + object = DATA_PTR(self); + is_corrupt = grn_obj_is_corrupt(ctx, object); + grn_mrb_ctx_check(mrb); + return mrb_bool_value(is_corrupt); +} + +void +grn_mrb_object_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Object", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + data->object_class = klass; + + mrb_define_class_method(mrb, + klass, + "remove_force", + object_remove_force, + MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "inspect", + grn_mrb_object_inspect, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "id", object_get_id, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "name", object_get_name, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "path", object_get_path, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "grn_inspect", + object_grn_inspect, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "==", object_equal, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "eql?", object_equal, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "hash", object_hash, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "close", object_close, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "remove", object_remove, MRB_ARGS_OPT(1)); + mrb_define_method(mrb, klass, "closed?", object_is_closed, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "domain_id", object_get_domain_id, + MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "range_id", object_get_range_id, + MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "temporary?", object_is_temporary, + MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "persistent?", object_is_persistent, + MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "true?", object_is_true, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "check_corrupt", object_check_corrupt, + MRB_ARGS_NONE()); + + grn_mrb_load(ctx, "index_info.rb"); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h new file mode 100644 index 00000000..5650ba28 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2013-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_object_init(grn_ctx *ctx); + +mrb_value grn_mrb_object_inspect(mrb_state *mrb, mrb_value self); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_object_flags.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object_flags.c new file mode 100644 index 00000000..1fb70299 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object_flags.c @@ -0,0 +1,96 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +# include +# include +# include +# include + +# include "../grn_mrb.h" +# include "mrb_object.h" +# include "mrb_operator.h" +# include "mrb_converter.h" + +void +grn_mrb_object_flags_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *flags_module; + + flags_module = mrb_define_module_under(mrb, module, "ObjectFlags"); + +#define MRB_DEFINE_FLAG(name) \ + mrb_define_const(mrb, flags_module, #name, \ + mrb_fixnum_value(GRN_OBJ_ ## name)) + + MRB_DEFINE_FLAG(TABLE_TYPE_MASK); + MRB_DEFINE_FLAG(TABLE_HASH_KEY); + MRB_DEFINE_FLAG(TABLE_PAT_KEY); + MRB_DEFINE_FLAG(TABLE_DAT_KEY); + MRB_DEFINE_FLAG(TABLE_NO_KEY); + + MRB_DEFINE_FLAG(KEY_MASK); + MRB_DEFINE_FLAG(KEY_UINT); + MRB_DEFINE_FLAG(KEY_INT); + MRB_DEFINE_FLAG(KEY_FLOAT); + MRB_DEFINE_FLAG(KEY_GEO_POINT); + + MRB_DEFINE_FLAG(KEY_WITH_SIS); + MRB_DEFINE_FLAG(KEY_NORMALIZE); + + MRB_DEFINE_FLAG(COLUMN_TYPE_MASK); + MRB_DEFINE_FLAG(COLUMN_SCALAR); + MRB_DEFINE_FLAG(COLUMN_VECTOR); + MRB_DEFINE_FLAG(COLUMN_INDEX); + + MRB_DEFINE_FLAG(COMPRESS_MASK); + MRB_DEFINE_FLAG(COMPRESS_NONE); + MRB_DEFINE_FLAG(COMPRESS_ZLIB); + MRB_DEFINE_FLAG(COMPRESS_LZ4); + MRB_DEFINE_FLAG(COMPRESS_ZSTD); + + MRB_DEFINE_FLAG(WITH_SECTION); + MRB_DEFINE_FLAG(WITH_WEIGHT); + MRB_DEFINE_FLAG(WITH_POSITION); + MRB_DEFINE_FLAG(RING_BUFFER); + + MRB_DEFINE_FLAG(UNIT_MASK); + MRB_DEFINE_FLAG(UNIT_DOCUMENT_NONE); + MRB_DEFINE_FLAG(UNIT_DOCUMENT_SECTION); + MRB_DEFINE_FLAG(UNIT_DOCUMENT_POSITION); + MRB_DEFINE_FLAG(UNIT_SECTION_NONE); + MRB_DEFINE_FLAG(UNIT_SECTION_POSITION); + MRB_DEFINE_FLAG(UNIT_POSITION_NONE); + MRB_DEFINE_FLAG(UNIT_USERDEF_DOCUMENT); + MRB_DEFINE_FLAG(UNIT_USERDEF_SECTION); + MRB_DEFINE_FLAG(UNIT_USERDEF_POSITION); + + MRB_DEFINE_FLAG(NO_SUBREC); + MRB_DEFINE_FLAG(WITH_SUBREC); + + MRB_DEFINE_FLAG(KEY_VAR_SIZE); + + MRB_DEFINE_FLAG(TEMPORARY); + MRB_DEFINE_FLAG(PERSISTENT); +} +#endif /* GRN_WITH_MRUBY */ diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_object_flags.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object_flags.h new file mode 100644 index 00000000..6f7bd7f7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_object_flags.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_object_flags_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c new file mode 100644 index 00000000..e0ef4727 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.c @@ -0,0 +1,155 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include + +#include "mrb_operator.h" + +mrb_value +grn_mrb_value_from_operator(mrb_state *mrb, grn_operator op) +{ + grn_ctx *ctx = (grn_ctx *)(mrb->ud); + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_value mrb_op_raw; + mrb_value mrb_op; + + mrb_op_raw = mrb_fixnum_value(op); + mrb_op = mrb_funcall(mrb, mrb_obj_value(data->groonga.operator_class), + "find", 1, mrb_op_raw); + if (mrb_nil_p(mrb_op)) { + return mrb_op_raw; + } else { + return mrb_op; + } +} + +grn_operator +grn_mrb_value_to_operator(mrb_state *mrb, mrb_value mrb_op) +{ + if (!mrb_fixnum_p(mrb_op)) { + mrb_op = mrb_funcall(mrb, mrb_op, "value", 0); + } + + return mrb_fixnum(mrb_op); +} + +void +grn_mrb_operator_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = ctx->impl->mrb.module; + struct RClass *klass; + mrb_value klass_obj; + + klass = mrb_class_get_under(mrb, module, "Operator"); + data->groonga.operator_class = klass; + + klass_obj = mrb_obj_value(klass); +#define DEFINE_OPERATOR(name) \ + mrb_funcall(mrb, klass_obj, "register", 1, \ + mrb_funcall(mrb, klass_obj, "new", 2, \ + mrb_str_new_lit(mrb, #name), \ + mrb_fixnum_value(GRN_OP_ ## name))) + + DEFINE_OPERATOR(PUSH); + DEFINE_OPERATOR(POP); + DEFINE_OPERATOR(NOP); + DEFINE_OPERATOR(CALL); + DEFINE_OPERATOR(INTERN); + DEFINE_OPERATOR(GET_REF); + DEFINE_OPERATOR(GET_VALUE); + DEFINE_OPERATOR(AND); + DEFINE_OPERATOR(AND_NOT); + DEFINE_OPERATOR(OR); + DEFINE_OPERATOR(ASSIGN); + DEFINE_OPERATOR(STAR_ASSIGN); + DEFINE_OPERATOR(SLASH_ASSIGN); + DEFINE_OPERATOR(MOD_ASSIGN); + DEFINE_OPERATOR(PLUS_ASSIGN); + DEFINE_OPERATOR(MINUS_ASSIGN); + DEFINE_OPERATOR(SHIFTL_ASSIGN); + DEFINE_OPERATOR(SHIFTR_ASSIGN); + DEFINE_OPERATOR(SHIFTRR_ASSIGN); + DEFINE_OPERATOR(AND_ASSIGN); + DEFINE_OPERATOR(XOR_ASSIGN); + DEFINE_OPERATOR(OR_ASSIGN); + DEFINE_OPERATOR(JUMP); + DEFINE_OPERATOR(CJUMP); + DEFINE_OPERATOR(COMMA); + DEFINE_OPERATOR(BITWISE_OR); + DEFINE_OPERATOR(BITWISE_XOR); + DEFINE_OPERATOR(BITWISE_AND); + DEFINE_OPERATOR(BITWISE_NOT); + DEFINE_OPERATOR(EQUAL); + DEFINE_OPERATOR(NOT_EQUAL); + DEFINE_OPERATOR(LESS); + DEFINE_OPERATOR(GREATER); + DEFINE_OPERATOR(LESS_EQUAL); + DEFINE_OPERATOR(GREATER_EQUAL); + DEFINE_OPERATOR(IN); + DEFINE_OPERATOR(MATCH); + DEFINE_OPERATOR(NEAR); + DEFINE_OPERATOR(NEAR2); + DEFINE_OPERATOR(SIMILAR); + DEFINE_OPERATOR(TERM_EXTRACT); + DEFINE_OPERATOR(SHIFTL); + DEFINE_OPERATOR(SHIFTR); + DEFINE_OPERATOR(SHIFTRR); + DEFINE_OPERATOR(PLUS); + DEFINE_OPERATOR(MINUS); + DEFINE_OPERATOR(STAR); + DEFINE_OPERATOR(SLASH); + DEFINE_OPERATOR(MOD); + DEFINE_OPERATOR(DELETE); + DEFINE_OPERATOR(INCR); + DEFINE_OPERATOR(DECR); + DEFINE_OPERATOR(INCR_POST); + DEFINE_OPERATOR(DECR_POST); + DEFINE_OPERATOR(NOT); + DEFINE_OPERATOR(ADJUST); + DEFINE_OPERATOR(EXACT); + DEFINE_OPERATOR(LCP); + DEFINE_OPERATOR(PARTIAL); + DEFINE_OPERATOR(UNSPLIT); + DEFINE_OPERATOR(PREFIX); + DEFINE_OPERATOR(SUFFIX); + DEFINE_OPERATOR(GEO_DISTANCE1); + DEFINE_OPERATOR(GEO_DISTANCE2); + DEFINE_OPERATOR(GEO_DISTANCE3); + DEFINE_OPERATOR(GEO_DISTANCE4); + DEFINE_OPERATOR(GEO_WITHINP5); + DEFINE_OPERATOR(GEO_WITHINP6); + DEFINE_OPERATOR(GEO_WITHINP8); + DEFINE_OPERATOR(OBJ_SEARCH); + DEFINE_OPERATOR(EXPR_GET_VAR); + DEFINE_OPERATOR(TABLE_CREATE); + DEFINE_OPERATOR(TABLE_SELECT); + DEFINE_OPERATOR(TABLE_SORT); + DEFINE_OPERATOR(TABLE_GROUP); + DEFINE_OPERATOR(JSON_PUT); + DEFINE_OPERATOR(GET_MEMBER); + DEFINE_OPERATOR(REGEXP); + DEFINE_OPERATOR(FUZZY); + +#undef DEFINE_OPERATOR +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h new file mode 100644 index 00000000..6f27e137 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_operator.h @@ -0,0 +1,34 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_operator_init(grn_ctx *ctx); +mrb_value grn_mrb_value_from_operator(mrb_state *mrb, grn_operator op); +grn_operator grn_mrb_value_to_operator(mrb_state *mrb, mrb_value mrb_op); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_options.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_options.c new file mode 100644 index 00000000..445bcaf6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_options.c @@ -0,0 +1,39 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include "../grn_db.h" + +#ifdef GRN_WITH_MRUBY +#include +#include + +#include "mrb_options.h" + +mrb_value +grn_mrb_options_get_static(mrb_state *mrb, + mrb_value mrb_options, + const char *key, + size_t key_size) +{ + mrb_sym mrb_key; + + mrb_key = mrb_intern_static(mrb, key, key_size); + return mrb_hash_get(mrb, mrb_options, mrb_symbol_value(mrb_key)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_options.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_options.h new file mode 100644 index 00000000..0cbd7bb7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_options.h @@ -0,0 +1,38 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +mrb_value grn_mrb_options_get_static(mrb_state *mrb, + mrb_value mrb_options, + const char *key, + size_t key_size); +#define grn_mrb_options_get_lit(mrb, mrb_options, literal) \ + grn_mrb_options_get_static(mrb, mrb_options, \ + (literal), mrb_strlen_lit(literal)) + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c new file mode 100644 index 00000000..bd206b5c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.c @@ -0,0 +1,59 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_patricia_trie.h" + +static struct mrb_data_type mrb_grn_patricia_trie_type = { + "Groonga::PatriciaTrie", + NULL +}; + +static mrb_value +mrb_grn_patricia_trie_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_patricia_trie_ptr; + + mrb_get_args(mrb, "o", &mrb_patricia_trie_ptr); + DATA_TYPE(self) = &mrb_grn_patricia_trie_type; + DATA_PTR(self) = mrb_cptr(mrb_patricia_trie_ptr); + return self; +} + +void +grn_mrb_patricia_trie_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *table_class; + struct RClass *klass; + + table_class = mrb_class_get_under(mrb, module, "Table"); + klass = mrb_define_class_under(mrb, module, "PatriciaTrie", table_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_patricia_trie_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h new file mode 100644 index 00000000..11da13a3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_patricia_trie.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_patricia_trie_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_pointer.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_pointer.c new file mode 100644 index 00000000..b0d60f18 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_pointer.c @@ -0,0 +1,77 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_pointer.h" +#include "mrb_object.h" +#include "mrb_converter.h" + +static struct mrb_data_type mrb_grn_pointer_type = { + "Groonga::Pointer", + NULL +}; + +static mrb_value +mrb_grn_pointer_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_pointer_ptr; + + mrb_get_args(mrb, "o", &mrb_pointer_ptr); + DATA_TYPE(self) = &mrb_grn_pointer_type; + DATA_PTR(self) = mrb_cptr(mrb_pointer_ptr); + return self; +} + +static mrb_value +mrb_grn_pointer_get_value(mrb_state *mrb, mrb_value self) +{ + grn_obj *pointer; + + pointer = DATA_PTR(self); + if (GRN_BULK_VSIZE(pointer) == 0) { + return mrb_nil_value(); + } + + return grn_mrb_value_from_grn_obj(mrb, GRN_PTR_VALUE(pointer)); +} + +void +grn_mrb_pointer_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Pointer", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_pointer_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "value", + mrb_grn_pointer_get_value, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "inspect", + grn_mrb_object_inspect, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_pointer.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_pointer.h new file mode 100644 index 00000000..5fe1dfb4 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_pointer.h @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_pointer_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c new file mode 100644 index 00000000..f5045dc1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.c @@ -0,0 +1,108 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_procedure.h" + +#include "mrb_operator.h" + +static struct mrb_data_type mrb_grn_procedure_type = { + "Groonga::Procedure", + NULL +}; + +static mrb_value +mrb_grn_procedure_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_procedure_ptr; + + mrb_get_args(mrb, "o", &mrb_procedure_ptr); + DATA_TYPE(self) = &mrb_grn_procedure_type; + DATA_PTR(self) = mrb_cptr(mrb_procedure_ptr); + return self; +} + +static mrb_value +mrb_grn_procedure_selector_p(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *proc = DATA_PTR(self); + + return mrb_bool_value(grn_obj_is_selector_proc(ctx, proc)); +} + +static mrb_value +mrb_grn_procedure_selector_only_p(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *proc = DATA_PTR(self); + + return mrb_bool_value(grn_obj_is_selector_only_proc(ctx, proc)); +} + +static mrb_value +mrb_grn_procedure_scorer_p(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *proc = DATA_PTR(self); + + return mrb_bool_value(grn_obj_is_scorer_proc(ctx, proc)); +} + +static mrb_value +mrb_grn_procedure_get_selector_operator(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *proc = DATA_PTR(self); + grn_operator selector_op; + + selector_op = grn_proc_get_selector_operator(ctx, proc); + return grn_mrb_value_from_operator(mrb, selector_op); +} + +void +grn_mrb_procedure_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *object_class = data->object_class; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Procedure", object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_procedure_initialize, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "selector?", + mrb_grn_procedure_selector_p, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "selector_only?", + mrb_grn_procedure_selector_only_p, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "scorer?", + mrb_grn_procedure_scorer_p, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "selector_operator", + mrb_grn_procedure_get_selector_operator, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h new file mode 100644 index 00000000..5d64fcd0 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_procedure.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_procedure_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_query_logger.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_query_logger.c new file mode 100644 index 00000000..d19ca780 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_query_logger.c @@ -0,0 +1,76 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include + +#include "../grn_mrb.h" +#include "mrb_query_logger.h" + +static mrb_value +query_logger_need_log_p(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int flag; + + mrb_get_args(mrb, "i", &flag); + + return mrb_bool_value(grn_query_logger_pass(ctx, flag)); +} + +static mrb_value +query_logger_log_raw(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int flag; + char *mark; + char *message; + mrb_int message_size; + + mrb_get_args(mrb, "izs", &flag, &mark, &message, &message_size); + grn_query_logger_put(ctx, flag, mark, + "%.*s", (int)message_size, message); + + return self; +} + +void +grn_mrb_query_logger_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "QueryLogger", mrb->object_class); + + mrb_define_method(mrb, klass, "need_log?", query_logger_need_log_p, + MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "log_raw", query_logger_log_raw, + MRB_ARGS_REQ(3)); + + grn_mrb_load(ctx, "query_logger/flag.rb"); + grn_mrb_load(ctx, "query_logger.rb"); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_query_logger.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_query_logger.h new file mode 100644 index 00000000..c0ea5eaf --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_query_logger.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_query_logger_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_record.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_record.c new file mode 100644 index 00000000..57411d27 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_record.c @@ -0,0 +1,162 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "../grn_db.h" +#include "mrb_record.h" +#include "mrb_bulk.h" + +typedef struct { + grn_obj *table; + grn_id id; + grn_obj key; +} grn_mrb_record; + +static void +mrb_grn_record_free(mrb_state *mrb, void *data) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_mrb_record *record = data; + + if (!record) { + return; + } + + GRN_OBJ_FIN(ctx, &(record->key)); + mrb_free(mrb, record); +} + +static struct mrb_data_type mrb_grn_record_type = { + "Groonga::Record", + mrb_grn_record_free +}; + +static mrb_value +mrb_grn_record_initialize(mrb_state *mrb, mrb_value self) +{ + grn_mrb_record *record; + mrb_value mrb_table; + mrb_value mrb_id; + + mrb_get_args(mrb, "oo", &mrb_table, &mrb_id); + + DATA_TYPE(self) = &mrb_grn_record_type; + + record = mrb_malloc(mrb, sizeof(grn_mrb_record)); + record->table = DATA_PTR(mrb_table); + if (mrb_nil_p(mrb_id)) { + record->id = GRN_ID_NIL; + } else { + record->id = mrb_fixnum(mrb_id); + } + + switch (record->table->header.domain) { + case GRN_ID_NIL : + case GRN_DB_SHORT_TEXT : + GRN_SHORT_TEXT_INIT(&(record->key), 0); + break; + default : + GRN_VALUE_FIX_SIZE_INIT(&(record->key), 0, record->table->header.domain); + break; + } + + DATA_PTR(self) = record; + + mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@table"), mrb_table); + mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@id"), mrb_id); + + return self; +} + +static mrb_value +mrb_grn_record_set_id(mrb_state *mrb, mrb_value self) +{ + grn_mrb_record *record; + mrb_value mrb_id; + + record = DATA_PTR(self); + mrb_get_args(mrb, "o", &mrb_id); + + if (mrb_nil_p(mrb_id)) { + record->id = GRN_ID_NIL; + } else { + record->id = mrb_fixnum(mrb_id); + } + mrb_iv_set(mrb, self, mrb_intern_lit(mrb, "@id"), mrb_id); + + return mrb_id; +} + +static mrb_value +mrb_grn_record_key(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_mrb_record *record; + int key_size; + + record = DATA_PTR(self); + + if (record->id == GRN_ID_NIL) { + return mrb_nil_value(); + } + + if (record->table->header.type == GRN_TABLE_NO_KEY) { + return mrb_nil_value(); + } + + GRN_BULK_REWIND(&(record->key)); + key_size = grn_table_get_key(ctx, record->table, record->id, + GRN_BULK_HEAD(&(record->key)), + GRN_BULK_VSIZE(&(record->key))); + if (key_size > GRN_BULK_VSIZE(&(record->key))) { + grn_bulk_space(ctx, &(record->key), key_size); + key_size = grn_table_get_key(ctx, record->table, record->id, + GRN_BULK_HEAD(&(record->key)), + GRN_BULK_VSIZE(&(record->key))); + } + + return grn_mrb_value_from_bulk(mrb, &(record->key)); +} + +void +grn_mrb_record_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Record", data->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_record_initialize, MRB_ARGS_REQ(2)); + + mrb_define_method(mrb, klass, "id=", + mrb_grn_record_set_id, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "key", + mrb_grn_record_key, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_record.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_record.h new file mode 100644 index 00000000..9c0e6ece --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_record.h @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_record_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c new file mode 100644 index 00000000..fecc6e3d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.c @@ -0,0 +1,493 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" +#include + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_table.h" +#include "mrb_converter.h" +#include "mrb_options.h" + +static mrb_value +mrb_grn_table_array_reference(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + grn_id key_domain_id; + mrb_value mrb_key; + grn_id record_id; + grn_mrb_value_to_raw_data_buffer buffer; + void *key; + unsigned int key_size; + + mrb_get_args(mrb, "o", &mrb_key); + + table = DATA_PTR(self); + if (table->header.type == GRN_DB) { + key_domain_id = GRN_DB_SHORT_TEXT; + } else { + key_domain_id = table->header.domain; + } + + grn_mrb_value_to_raw_data_buffer_init(mrb, &buffer); + grn_mrb_value_to_raw_data(mrb, "key", mrb_key, key_domain_id, + &buffer, &key, &key_size); + record_id = grn_table_get(ctx, table, key, key_size); + grn_mrb_value_to_raw_data_buffer_fin(mrb, &buffer); + + if (record_id == GRN_ID_NIL) { + return mrb_nil_value(); + } else { + return mrb_fixnum_value(record_id); + } +} + +static mrb_value +mrb_grn_table_is_id(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + mrb_int mrb_record_id; + grn_id record_id; + grn_id real_record_id; + + mrb_get_args(mrb, "i", &mrb_record_id); + + table = DATA_PTR(self); + record_id = (grn_id)mrb_record_id; + real_record_id = grn_table_at(ctx, table, record_id); + if (real_record_id == record_id) { + return mrb_true_value(); + } else { + return mrb_false_value(); + } +} + +static mrb_value +mrb_grn_table_find_column(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + mrb_value mrb_column_name; + grn_obj *column; + + mrb_get_args(mrb, "o", &mrb_column_name); + + table = DATA_PTR(self); + column = grn_obj_column(ctx, table, + RSTRING_PTR(mrb_column_name), + RSTRING_LEN(mrb_column_name)); + grn_mrb_ctx_check(mrb); + + return grn_mrb_value_from_grn_obj(mrb, column); +} + +static mrb_value +mrb_grn_table_get_column_ids(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + grn_hash *columns; + int n_columns; + mrb_value mrb_column_ids; + + table = DATA_PTR(self); + columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); + if (!columns) { + grn_mrb_ctx_check(mrb); + return mrb_ary_new(mrb); + } + + n_columns = grn_table_columns(ctx, table, "", 0, (grn_obj *)columns); + mrb_column_ids = mrb_ary_new_capa(mrb, n_columns); + { + grn_id *key; + GRN_HASH_EACH(ctx, columns, id, &key, NULL, NULL, { + mrb_ary_push(mrb, mrb_column_ids, mrb_fixnum_value(*key)); + }); + } + grn_hash_close(ctx, columns); + + grn_mrb_ctx_check(mrb); + + return mrb_column_ids; +} + +static mrb_value +mrb_grn_table_create_column(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + mrb_value mrb_name; + mrb_int flags; + mrb_value mrb_type; + grn_obj *type; + grn_obj *column; + + mrb_get_args(mrb, "oio", &mrb_name, &flags, &mrb_type); + + table = DATA_PTR(self); + type = DATA_PTR(mrb_type); + column = grn_column_create(ctx, table, + RSTRING_PTR(mrb_name), + RSTRING_LEN(mrb_name), + NULL, + flags, + type); + grn_mrb_ctx_check(mrb); + + return grn_mrb_value_from_grn_obj(mrb, column); +} + +static mrb_value +mrb_grn_table_is_locked(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int is_locked; + + is_locked = grn_obj_is_locked(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_bool_value(is_locked != 0); +} + +static mrb_value +mrb_grn_table_get_size(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int size; + + size = grn_table_size(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_fixnum_value(size); +} + +static mrb_value +mrb_grn_table_is_empty(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + unsigned int size; + + size = grn_table_size(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_bool_value(size == 0); +} + +static mrb_value +mrb_grn_table_select(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + grn_obj *expr; + grn_obj *result = NULL; + grn_operator operator = GRN_OP_OR; + mrb_value mrb_expr; + mrb_value mrb_options = mrb_nil_value(); + + table = DATA_PTR(self); + mrb_get_args(mrb, "o|H", &mrb_expr, &mrb_options); + + expr = DATA_PTR(mrb_expr); + + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_result; + mrb_value mrb_operator; + + mrb_result = grn_mrb_options_get_lit(mrb, mrb_options, "result"); + if (!mrb_nil_p(mrb_result)) { + result = DATA_PTR(mrb_result); + } + + mrb_operator = grn_mrb_options_get_lit(mrb, mrb_options, "operator"); + if (!mrb_nil_p(mrb_operator)) { + operator = mrb_fixnum(mrb_operator); + } + } + + result = grn_table_select(ctx, table, expr, result, operator); + if (ctx->rc != GRN_SUCCESS) { + grn_mrb_ctx_check(mrb); + } + + return grn_mrb_value_from_grn_obj(mrb, result); +} + +static mrb_value +mrb_grn_table_sort_raw(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + mrb_value mrb_keys; + grn_table_sort_key *keys; + int i, n_keys; + mrb_int offset; + mrb_int limit; + mrb_value mrb_result; + grn_obj *result; + + table = DATA_PTR(self); + mrb_get_args(mrb, "oiio", &mrb_keys, &offset, &limit, &mrb_result); + + mrb_keys = mrb_convert_type(mrb, mrb_keys, + MRB_TT_ARRAY, "Array", "to_ary"); + + n_keys = RARRAY_LEN(mrb_keys); + keys = GRN_MALLOCN(grn_table_sort_key, n_keys); + for (i = 0; i < n_keys; i++) { + grn_memcpy(&(keys[i]), + DATA_PTR(RARRAY_PTR(mrb_keys)[i]), + sizeof(grn_table_sort_key)); + } + result = DATA_PTR(mrb_result); + grn_table_sort(ctx, table, offset, limit, result, keys, n_keys); + GRN_FREE(keys); + grn_mrb_ctx_check(mrb); + + return mrb_result; +} + +static mrb_value +mrb_grn_table_group_raw(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + mrb_value mrb_keys; + grn_table_sort_key *keys; + int i, n_keys; + mrb_value mrb_result; + grn_table_group_result *result; + + table = DATA_PTR(self); + mrb_get_args(mrb, "oo", &mrb_keys, &mrb_result); + + mrb_keys = mrb_convert_type(mrb, mrb_keys, + MRB_TT_ARRAY, "Array", "to_ary"); + + n_keys = RARRAY_LEN(mrb_keys); + keys = GRN_MALLOCN(grn_table_sort_key, n_keys); + for (i = 0; i < n_keys; i++) { + grn_memcpy(&(keys[i]), + DATA_PTR(RARRAY_PTR(mrb_keys)[i]), + sizeof(grn_table_sort_key)); + } + result = DATA_PTR(mrb_result); + grn_table_group(ctx, table, keys, n_keys, result, 1); + GRN_FREE(keys); + grn_mrb_ctx_check(mrb); + + return mrb_result; +} + +static mrb_value +mrb_grn_table_delete(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + mrb_value mrb_options; + mrb_value mrb_id; + mrb_value mrb_key; + mrb_value mrb_expression; + + table = DATA_PTR(self); + mrb_get_args(mrb, "H", &mrb_options); + + mrb_id = grn_mrb_options_get_lit(mrb, mrb_options, "id"); + if (!mrb_nil_p(mrb_id)) { + grn_table_delete_by_id(ctx, table, mrb_fixnum(mrb_id)); + grn_mrb_ctx_check(mrb); + return mrb_nil_value(); + } + + mrb_key = grn_mrb_options_get_lit(mrb, mrb_options, "key"); + if (!mrb_nil_p(mrb_key)) { + grn_id key_domain_id; + void *key; + unsigned int key_size; + grn_mrb_value_to_raw_data_buffer buffer; + + key_domain_id = table->header.domain; + grn_mrb_value_to_raw_data_buffer_init(mrb, &buffer); + grn_mrb_value_to_raw_data(mrb, "key", mrb_key, key_domain_id, + &buffer, &key, &key_size); + grn_table_delete(ctx, table, key, key_size); + grn_mrb_value_to_raw_data_buffer_fin(mrb, &buffer); + grn_mrb_ctx_check(mrb); + return mrb_nil_value(); + } + + mrb_expression = grn_mrb_options_get_lit(mrb, mrb_options, "expression"); + if (!mrb_nil_p(mrb_expression)) { + grn_obj *expression; + grn_obj *selected_records; + grn_table_cursor *cursor; + + expression = DATA_PTR(mrb_expression); + selected_records = grn_table_select(ctx, table, expression, NULL, GRN_OP_OR); + grn_mrb_ctx_check(mrb); + cursor = grn_table_cursor_open(ctx, selected_records, + NULL, 0, + NULL, 0, + 0, -1, 0); + if (cursor) { + while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) { + grn_id *id; + grn_table_cursor_get_key(ctx, cursor, (void **)&id); + grn_table_delete_by_id(ctx, table, *id); + } + grn_table_cursor_close(ctx, cursor); + } + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); + } + + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "must have :id, :key or :expression: %S", + mrb_options); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_truncate(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_obj *table; + + table = DATA_PTR(self); + grn_table_truncate(ctx, table); + grn_mrb_ctx_check(mrb); + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_apply_expression(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_output_column; + mrb_value mrb_expression; + grn_obj *table; + grn_obj *output_column = NULL; + grn_obj *expression = NULL; + + mrb_get_args(mrb, "oo", &mrb_output_column, &mrb_expression); + + table = DATA_PTR(self); + output_column = GRN_MRB_DATA_PTR(mrb_output_column); + expression = GRN_MRB_DATA_PTR(mrb_expression); + grn_table_apply_expr(ctx, table, output_column, expression); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_apply_window_function_raw(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_output_column; + mrb_value mrb_window_definition; + mrb_value mrb_window_function_call; + grn_obj *table; + grn_obj *output_column = NULL; + grn_window_definition *window_definition = NULL; + grn_obj *window_function_call = NULL; + + mrb_get_args(mrb, "ooo", + &mrb_output_column, + &mrb_window_definition, + &mrb_window_function_call); + + table = DATA_PTR(self); + output_column = GRN_MRB_DATA_PTR(mrb_output_column); + window_definition = GRN_MRB_DATA_PTR(mrb_window_definition); + window_function_call = GRN_MRB_DATA_PTR(mrb_window_function_call); + grn_table_apply_window_function(ctx, + table, + output_column, + window_definition, + window_function_call); + grn_mrb_ctx_check(mrb); + + return mrb_nil_value(); +} + +void +grn_mrb_table_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *object_class = data->object_class; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Table", object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "[]", + mrb_grn_table_array_reference, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "id?", + mrb_grn_table_is_id, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "find_column", + mrb_grn_table_find_column, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "column_ids", + mrb_grn_table_get_column_ids, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "create_column", + mrb_grn_table_create_column, MRB_ARGS_REQ(3)); + + mrb_define_method(mrb, klass, "locked?", + mrb_grn_table_is_locked, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "size", + mrb_grn_table_get_size, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "empty?", + mrb_grn_table_is_empty, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "select", + mrb_grn_table_select, MRB_ARGS_ARG(1, 1)); + mrb_define_method(mrb, klass, "sort_raw", + mrb_grn_table_sort_raw, MRB_ARGS_REQ(4)); + mrb_define_method(mrb, klass, "group_raw", + mrb_grn_table_group_raw, MRB_ARGS_REQ(2)); + + mrb_define_method(mrb, klass, "delete", + mrb_grn_table_delete, MRB_ARGS_REQ(1)); + + mrb_define_method(mrb, klass, "truncate", + mrb_grn_table_truncate, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "apply_expression", + mrb_grn_table_apply_expression, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, klass, "apply_window_function_raw", + mrb_grn_table_apply_window_function_raw, MRB_ARGS_REQ(4)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h new file mode 100644 index 00000000..fd06db56 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c new file mode 100644 index 00000000..a7748168 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.c @@ -0,0 +1,208 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_bulk.h" +#include "mrb_table_cursor.h" + +#include "mrb_converter.h" +#include "mrb_options.h" + +static struct mrb_data_type mrb_grn_table_cursor_type = { + "Groonga::TableCursor", + NULL +}; + +static mrb_value +mrb_grn_table_cursor_class_open_raw(mrb_state *mrb, mrb_value klass) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_table; + mrb_value mrb_options = mrb_nil_value(); + grn_table_cursor *table_cursor; + grn_obj *table; + void *min = NULL; + unsigned int min_size = 0; + grn_mrb_value_to_raw_data_buffer min_buffer; + void *max = NULL; + unsigned int max_size = 0; + grn_mrb_value_to_raw_data_buffer max_buffer; + int offset = 0; + int limit = -1; + int flags = 0; + + mrb_get_args(mrb, "o|H", &mrb_table, &mrb_options); + + table = DATA_PTR(mrb_table); + grn_mrb_value_to_raw_data_buffer_init(mrb, &min_buffer); + grn_mrb_value_to_raw_data_buffer_init(mrb, &max_buffer); + if (!mrb_nil_p(mrb_options)) { + grn_id key_domain_id; + mrb_value mrb_min; + mrb_value mrb_max; + mrb_value mrb_flags; + + if (table->header.type == GRN_DB) { + key_domain_id = GRN_DB_SHORT_TEXT; + } else { + key_domain_id = table->header.domain; + } + + mrb_min = grn_mrb_options_get_lit(mrb, mrb_options, "min"); + grn_mrb_value_to_raw_data(mrb, "min", mrb_min, + key_domain_id, &min_buffer, &min, &min_size); + + mrb_max = grn_mrb_options_get_lit(mrb, mrb_options, "max"); + grn_mrb_value_to_raw_data(mrb, "max", mrb_max, + key_domain_id, &max_buffer, &max, &max_size); + + mrb_flags = grn_mrb_options_get_lit(mrb, mrb_options, "flags"); + if (!mrb_nil_p(mrb_flags)) { + flags = mrb_fixnum(mrb_flags); + } + } + table_cursor = grn_table_cursor_open(ctx, table, + min, min_size, + max, max_size, + offset, limit, flags); + grn_mrb_value_to_raw_data_buffer_fin(mrb, &min_buffer); + grn_mrb_value_to_raw_data_buffer_fin(mrb, &max_buffer); + grn_mrb_ctx_check(mrb); + + { + mrb_value mrb_table_cursor; + mrb_table_cursor = mrb_funcall(mrb, klass, + "new", 1, mrb_cptr_value(mrb, table_cursor)); + mrb_iv_set(mrb, mrb_table_cursor, mrb_intern_lit(mrb, "@table"), mrb_table); + return mrb_table_cursor; + } +} + +static mrb_value +mrb_grn_table_cursor_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_table_cursor_ptr; + + mrb_get_args(mrb, "o", &mrb_table_cursor_ptr); + DATA_TYPE(self) = &mrb_grn_table_cursor_type; + DATA_PTR(self) = mrb_cptr(mrb_table_cursor_ptr); + + return self; +} + +static mrb_value +mrb_grn_table_cursor_close(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_table_cursor *table_cursor; + + table_cursor = DATA_PTR(self); + if (table_cursor) { + DATA_PTR(self) = NULL; + grn_table_cursor_close(ctx, table_cursor); + grn_mrb_ctx_check(mrb); + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_cursor_next(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_id id; + + id = grn_table_cursor_next(ctx, DATA_PTR(self)); + grn_mrb_ctx_check(mrb); + + return mrb_fixnum_value(id); +} + +static mrb_value +mrb_grn_table_cursor_count(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + int n_records = 0; + + while (grn_table_cursor_next(ctx, DATA_PTR(self)) != GRN_ID_NIL) { + n_records++; + } + + return mrb_fixnum_value(n_records); +} + +static mrb_value +mrb_grn_table_cursor_get_key(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_table; + grn_obj *table; + grn_id domain; + void *key; + int key_size; + + mrb_table = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@table")); + table = DATA_PTR(mrb_table); + if (table->header.type == GRN_DB) { + domain = GRN_DB_SHORT_TEXT; + } else { + domain = table->header.domain; + } + key_size = grn_table_cursor_get_key(ctx, DATA_PTR(self), &key); + + return grn_mrb_value_from_raw_data(mrb, domain, key, key_size); +} + +void +grn_mrb_table_cursor_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "TableCursor", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_class_method(mrb, klass, "open_raw", + mrb_grn_table_cursor_class_open_raw, + MRB_ARGS_ARG(1, 1)); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_table_cursor_initialize, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "close", + mrb_grn_table_cursor_close, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "next", + mrb_grn_table_cursor_next, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "count", + mrb_grn_table_cursor_count, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "key", + mrb_grn_table_cursor_get_key, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h new file mode 100644 index 00000000..6ffd51af --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_cursor_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c new file mode 100644 index 00000000..58a3137a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.c @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include + +#include "mrb_table_cursor_flags.h" + +void +grn_mrb_table_cursor_flags_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *flags_module; + + flags_module = mrb_define_module_under(mrb, module, "TableCursorFlags"); + + mrb_define_const(mrb, flags_module, "ASCENDING", + mrb_fixnum_value(GRN_CURSOR_ASCENDING)); + mrb_define_const(mrb, flags_module, "DESCENDING", + mrb_fixnum_value(GRN_CURSOR_DESCENDING)); + mrb_define_const(mrb, flags_module, "GE", + mrb_fixnum_value(GRN_CURSOR_GE)); + mrb_define_const(mrb, flags_module, "GT", + mrb_fixnum_value(GRN_CURSOR_GT)); + mrb_define_const(mrb, flags_module, "LE", + mrb_fixnum_value(GRN_CURSOR_LE)); + mrb_define_const(mrb, flags_module, "LT", + mrb_fixnum_value(GRN_CURSOR_LT)); + mrb_define_const(mrb, flags_module, "BY_KEY", + mrb_fixnum_value(GRN_CURSOR_BY_KEY)); + mrb_define_const(mrb, flags_module, "BY_ID", + mrb_fixnum_value(GRN_CURSOR_BY_ID)); + mrb_define_const(mrb, flags_module, "PREFIX", + mrb_fixnum_value(GRN_CURSOR_PREFIX)); + mrb_define_const(mrb, flags_module, "SIZE_BY_BIT", + mrb_fixnum_value(GRN_CURSOR_SIZE_BY_BIT)); + mrb_define_const(mrb, flags_module, "RK", + mrb_fixnum_value(GRN_CURSOR_RK)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h new file mode 100644 index 00000000..5db915a7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_cursor_flags.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_cursor_flags_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_flags.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_flags.c new file mode 100644 index 00000000..8984ebef --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_flags.c @@ -0,0 +1,48 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include + +#include "mrb_table_group_flags.h" + +void +grn_mrb_table_group_flags_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *flags_module; + + flags_module = mrb_define_module_under(mrb, module, "TableGroupFlags"); + + mrb_define_const(mrb, flags_module, "CALC_COUNT", + mrb_fixnum_value(GRN_TABLE_GROUP_CALC_COUNT)); + mrb_define_const(mrb, flags_module, "CALC_MAX", + mrb_fixnum_value(GRN_TABLE_GROUP_CALC_MAX)); + mrb_define_const(mrb, flags_module, "CALC_MIN", + mrb_fixnum_value(GRN_TABLE_GROUP_CALC_MIN)); + mrb_define_const(mrb, flags_module, "CALC_SUM", + mrb_fixnum_value(GRN_TABLE_GROUP_CALC_SUM)); + mrb_define_const(mrb, flags_module, "CALC_AVG", + mrb_fixnum_value(GRN_TABLE_GROUP_CALC_AVG)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_flags.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_flags.h new file mode 100644 index 00000000..4230a240 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_flags.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_group_flags_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_result.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_result.c new file mode 100644 index 00000000..c4aaafa4 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_result.c @@ -0,0 +1,254 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_converter.h" +#include "mrb_operator.h" +#include "mrb_table_group_result.h" + +static void +mrb_grn_table_group_result_free(mrb_state *mrb, void *data) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_table_group_result *result = data; + + if (!result) { + return; + } + + if (result->calc_target) { + grn_obj_unlink(ctx, result->calc_target); + } + if (result->table) { + grn_obj_unlink(ctx, result->table); + } + mrb_free(mrb, result); +} + +static struct mrb_data_type mrb_grn_table_group_result_type = { + "Groonga::TableGroupResult", + mrb_grn_table_group_result_free +}; + +static mrb_value +mrb_grn_table_group_result_initialize(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + + DATA_TYPE(self) = &mrb_grn_table_group_result_type; + + result = mrb_calloc(mrb, 1, sizeof(grn_table_group_result)); + DATA_PTR(self) = result; + + return self; +} + + +static mrb_value +mrb_grn_table_group_result_close(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + + result = DATA_PTR(self); + if (result) { + mrb_grn_table_group_result_free(mrb, result); + DATA_PTR(self) = NULL; + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_group_result_get_table(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + + result = DATA_PTR(self); + + return grn_mrb_value_from_grn_obj(mrb, result->table); +} + +static mrb_value +mrb_grn_table_group_result_set_table(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + mrb_value mrb_table; + + result = DATA_PTR(self); + mrb_get_args(mrb, "o", &mrb_table); + + if (mrb_nil_p(mrb_table)) { + result->table = NULL; + } else { + result->table = DATA_PTR(mrb_table); + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_group_result_set_key_begin(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + mrb_int key_begin; + + result = DATA_PTR(self); + mrb_get_args(mrb, "i", &key_begin); + + result->key_begin = key_begin; + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_group_result_set_key_end(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + mrb_int key_end; + + result = DATA_PTR(self); + mrb_get_args(mrb, "i", &key_end); + + result->key_end = key_end; + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_group_result_set_limit(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + mrb_int limit; + + result = DATA_PTR(self); + mrb_get_args(mrb, "i", &limit); + + result->limit = limit; + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_group_result_set_flags(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + mrb_int flags; + + result = DATA_PTR(self); + mrb_get_args(mrb, "i", &flags); + + result->flags = flags; + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_group_result_set_operator(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + mrb_value mrb_operator; + + result = DATA_PTR(self); + mrb_get_args(mrb, "o", &mrb_operator); + + result->op = grn_mrb_value_to_operator(mrb, mrb_operator); + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_group_result_set_max_n_sub_records(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + mrb_int max_n_sub_records; + + result = DATA_PTR(self); + mrb_get_args(mrb, "i", &max_n_sub_records); + + result->max_n_subrecs = max_n_sub_records; + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_group_result_set_calc_target(mrb_state *mrb, mrb_value self) +{ + grn_table_group_result *result; + mrb_value mrb_calc_target; + + result = DATA_PTR(self); + mrb_get_args(mrb, "o", &mrb_calc_target); + + if (mrb_nil_p(mrb_calc_target)) { + result->calc_target = NULL; + } else { + result->calc_target = DATA_PTR(mrb_calc_target); + } + + return mrb_nil_value(); +} + +void +grn_mrb_table_group_result_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "TableGroupResult", + mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_table_group_result_initialize, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "close", + mrb_grn_table_group_result_close, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "table", + mrb_grn_table_group_result_get_table, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "table=", + mrb_grn_table_group_result_set_table, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "key_begin=", + mrb_grn_table_group_result_set_key_begin, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "key_end=", + mrb_grn_table_group_result_set_key_end, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "limit=", + mrb_grn_table_group_result_set_limit, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "flags=", + mrb_grn_table_group_result_set_flags, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "operator=", + mrb_grn_table_group_result_set_operator, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "max_n_sub_records=", + mrb_grn_table_group_result_set_max_n_sub_records, + MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "calc_target=", + mrb_grn_table_group_result_set_calc_target, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_result.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_result.h new file mode 100644 index 00000000..c3b17af2 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_group_result.h @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_group_result_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_flags.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_flags.c new file mode 100644 index 00000000..47f0169e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_flags.c @@ -0,0 +1,42 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include + +#include "mrb_table_sort_flags.h" + +void +grn_mrb_table_sort_flags_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *flags_module; + + flags_module = mrb_define_module_under(mrb, module, "TableSortFlags"); + + mrb_define_const(mrb, flags_module, "ASCENDING", + mrb_fixnum_value(GRN_TABLE_SORT_ASC)); + mrb_define_const(mrb, flags_module, "DESCENDING", + mrb_fixnum_value(GRN_TABLE_SORT_DESC)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_flags.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_flags.h new file mode 100644 index 00000000..7450399e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_flags.h @@ -0,0 +1,31 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_sort_flags_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_key.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_key.c new file mode 100644 index 00000000..f8692d48 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_key.c @@ -0,0 +1,159 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_table_sort_key.h" + +static void +mrb_grn_table_sort_key_free(mrb_state *mrb, void *data) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_table_sort_key *sort_key = data; + + if (!sort_key) { + return; + } + + if (sort_key->key) { + if (sort_key->key->header.type == GRN_ACCESSOR) { + grn_obj_unlink(ctx, sort_key->key); + } + } + mrb_free(mrb, sort_key); +} + +static struct mrb_data_type mrb_grn_table_sort_key_type = { + "Groonga::TableSortKey", + mrb_grn_table_sort_key_free +}; + +static mrb_value +mrb_grn_table_sort_key_initialize(mrb_state *mrb, mrb_value self) +{ + grn_table_sort_key *result; + + DATA_TYPE(self) = &mrb_grn_table_sort_key_type; + + result = mrb_calloc(mrb, 1, sizeof(grn_table_sort_key)); + DATA_PTR(self) = result; + + return self; +} + + +static mrb_value +mrb_grn_table_sort_key_close(mrb_state *mrb, mrb_value self) +{ + grn_table_sort_key *sort_key; + + sort_key = DATA_PTR(self); + if (sort_key) { + mrb_grn_table_sort_key_free(mrb, sort_key); + DATA_PTR(self) = NULL; + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_sort_key_set_key(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + grn_table_sort_key *sort_key; + mrb_value mrb_key; + + sort_key = DATA_PTR(self); + mrb_get_args(mrb, "o", &mrb_key); + + if (sort_key->key) { + grn_obj_unlink(ctx, sort_key->key); + } + + if (mrb_nil_p(mrb_key)) { + sort_key->key = NULL; + } else { + sort_key->key = DATA_PTR(mrb_key); + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_sort_key_set_flags(mrb_state *mrb, mrb_value self) +{ + grn_table_sort_key *sort_key; + mrb_int flags; + + sort_key = DATA_PTR(self); + mrb_get_args(mrb, "i", &flags); + + sort_key->flags = flags; + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_table_sort_key_set_offset(mrb_state *mrb, mrb_value self) +{ + grn_table_sort_key *sort_key; + mrb_int offset; + + sort_key = DATA_PTR(self); + mrb_get_args(mrb, "i", &offset); + + sort_key->offset = offset; + + return mrb_nil_value(); +} + +void +grn_mrb_table_sort_key_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "TableSortKey", + mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_table_sort_key_initialize, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "close", + mrb_grn_table_sort_key_close, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "key=", + mrb_grn_table_sort_key_set_key, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "flags=", + mrb_grn_table_sort_key_set_flags, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "offset=", + mrb_grn_table_sort_key_set_offset, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_key.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_key.h new file mode 100644 index 00000000..9ca38bfc --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_table_sort_key.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_table_sort_key_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_thread.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_thread.c new file mode 100644 index 00000000..ba3a7e7b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_thread.c @@ -0,0 +1,46 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include + +#include "mrb_thread.h" + +static mrb_value +thread_limit(mrb_state *mrb, mrb_value self) +{ + uint32_t limit; + limit = grn_thread_get_limit(); + return mrb_fixnum_value(limit); +} + +void +grn_mrb_thread_init(grn_ctx *ctx) +{ + mrb_state *mrb = ctx->impl->mrb.state; + struct RClass *module = ctx->impl->mrb.module; + struct RClass *thread_module; + + thread_module = mrb_define_module_under(mrb, module, "Thread"); + + mrb_define_class_method(mrb, thread_module, + "limit", thread_limit, MRB_ARGS_NONE()); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_thread.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_thread.h new file mode 100644 index 00000000..030eafed --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_thread.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_thread_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c new file mode 100644 index 00000000..a288d60f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.c @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_type.h" + +static struct mrb_data_type mrb_grn_type_type = { + "Groonga::Type", + NULL +}; + +static mrb_value +mrb_grn_type_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_type_ptr; + + mrb_get_args(mrb, "o", &mrb_type_ptr); + DATA_TYPE(self) = &mrb_grn_type_type; + DATA_PTR(self) = mrb_cptr(mrb_type_ptr); + return self; +} + +void +grn_mrb_type_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *object_class = data->object_class; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Type", object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_type_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h new file mode 100644 index 00000000..8dc74b79 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_type.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_type_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c new file mode 100644 index 00000000..78f3de86 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.c @@ -0,0 +1,60 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include + +#include "mrb_variable_size_column.h" + +static struct mrb_data_type mrb_grn_variable_size_column_type = { + "Groonga::VariableSizeColumn", + NULL +}; + +static mrb_value +mrb_grn_variable_size_column_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_variable_size_column_ptr; + + mrb_get_args(mrb, "o", &mrb_variable_size_column_ptr); + DATA_TYPE(self) = &mrb_grn_variable_size_column_type; + DATA_PTR(self) = mrb_cptr(mrb_variable_size_column_ptr); + return self; +} + +void +grn_mrb_variable_size_column_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *column_class; + struct RClass *klass; + + column_class = mrb_class_get_under(mrb, module, "Column"); + klass = mrb_define_class_under(mrb, module, + "VariableSizeColumn", column_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_variable_size_column_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h new file mode 100644 index 00000000..1bac1238 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_variable_size_column.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_variable_size_column_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c new file mode 100644 index 00000000..33cdea6c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.c @@ -0,0 +1,59 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "../grn_db.h" +#include "mrb_void.h" + +static struct mrb_data_type mrb_grn_void_type = { + "Groonga::Void", + NULL +}; + +static mrb_value +mrb_grn_void_initialize(mrb_state *mrb, mrb_value self) +{ + mrb_value mrb_void_ptr; + + mrb_get_args(mrb, "o", &mrb_void_ptr); + DATA_TYPE(self) = &mrb_grn_void_type; + DATA_PTR(self) = mrb_cptr(mrb_void_ptr); + return self; +} + +void +grn_mrb_void_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Void", mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + mrb_define_method(mrb, klass, "initialize", + mrb_grn_void_initialize, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h new file mode 100644 index 00000000..dced2747 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_void.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_void_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_window_definition.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_window_definition.c new file mode 100644 index 00000000..86ff372e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_window_definition.c @@ -0,0 +1,164 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "mrb_ctx.h" +#include "mrb_window_definition.h" + +static void +mrb_grn_window_definition_free(mrb_state *mrb, void *data) +{ + grn_window_definition *definition = data; + + if (!definition) { + return; + } + + if (definition->sort_keys) { + mrb_free(mrb, definition->sort_keys); + } + if (definition->group_keys) { + mrb_free(mrb, definition->group_keys); + } + mrb_free(mrb, definition); +} + +static struct mrb_data_type mrb_grn_window_definition_type = { + "Groonga::WindowDefinition", + mrb_grn_window_definition_free +}; + +static mrb_value +mrb_grn_window_definition_initialize(mrb_state *mrb, mrb_value self) +{ + grn_window_definition *result; + + DATA_TYPE(self) = &mrb_grn_window_definition_type; + + result = mrb_calloc(mrb, 1, sizeof(grn_window_definition)); + DATA_PTR(self) = result; + + return self; +} + + +static mrb_value +mrb_grn_window_definition_close(mrb_state *mrb, mrb_value self) +{ + grn_window_definition *definition; + + definition = DATA_PTR(self); + if (definition) { + mrb_grn_window_definition_free(mrb, definition); + DATA_PTR(self) = NULL; + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_window_definition_set_sort_keys(mrb_state *mrb, mrb_value self) +{ + grn_window_definition *definition; + mrb_value mrb_keys; + + definition = DATA_PTR(self); + mrb_get_args(mrb, "A!", &mrb_keys); + + if (definition->sort_keys) { + mrb_free(mrb, definition->sort_keys); + } + + if (mrb_nil_p(mrb_keys)) { + definition->sort_keys = NULL; + definition->n_sort_keys = 0; + } else { + mrb_int i, n; + n = RARRAY_LEN(mrb_keys); + definition->sort_keys = mrb_calloc(mrb, n, sizeof(grn_table_sort_key)); + for (i = 0; i < n; i++) { + grn_table_sort_key *sort_key = DATA_PTR(RARRAY_PTR(mrb_keys)[i]); + definition->sort_keys[i] = *sort_key; + } + definition->n_sort_keys = n; + } + + return mrb_nil_value(); +} + +static mrb_value +mrb_grn_window_definition_set_group_keys(mrb_state *mrb, mrb_value self) +{ + grn_window_definition *definition; + mrb_value mrb_keys; + + definition = DATA_PTR(self); + mrb_get_args(mrb, "A!", &mrb_keys); + + if (definition->group_keys) { + mrb_free(mrb, definition->group_keys); + } + + if (mrb_nil_p(mrb_keys)) { + definition->group_keys = NULL; + definition->n_group_keys = 0; + } else { + mrb_int i, n; + n = RARRAY_LEN(mrb_keys); + definition->group_keys = mrb_calloc(mrb, n, sizeof(grn_table_sort_key)); + for (i = 0; i < n; i++) { + grn_table_sort_key *group_key = DATA_PTR(RARRAY_PTR(mrb_keys)[i]); + definition->group_keys[i] = *group_key; + } + definition->n_group_keys = n; + } + + return mrb_nil_value(); +} + +void +grn_mrb_window_definition_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "WindowDefinition", + mrb->object_class); + MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA); + + mrb_define_method(mrb, klass, "initialize", + mrb_grn_window_definition_initialize, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "close", + mrb_grn_window_definition_close, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "sort_keys=", + mrb_grn_window_definition_set_sort_keys, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "group_keys=", + mrb_grn_window_definition_set_group_keys, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_window_definition.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_window_definition.h new file mode 100644 index 00000000..ea1b8ef6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_window_definition.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_window_definition_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c new file mode 100644 index 00000000..b2ca09f9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.c @@ -0,0 +1,253 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_ctx_impl.h" + +#ifdef GRN_WITH_MRUBY +#include +#include +#include +#include + +#include "../grn_mrb.h" +#include "../grn_output.h" +#include "mrb_ctx.h" +#include "mrb_writer.h" +#include "mrb_options.h" + +static mrb_value +writer_write(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value target; + + mrb_get_args(mrb, "o", &target); + + switch (mrb_type(target)) { + case MRB_TT_FALSE : + if (mrb_nil_p(target)) { + GRN_OUTPUT_NULL(); + } else { + GRN_OUTPUT_BOOL(GRN_FALSE); + } + break; + case MRB_TT_TRUE : + GRN_OUTPUT_BOOL(GRN_TRUE); + break; + case MRB_TT_FIXNUM : + GRN_OUTPUT_INT32(mrb_fixnum(target)); + break; + case MRB_TT_FLOAT : + GRN_OUTPUT_FLOAT(mrb_float(target)); + break; + case MRB_TT_SYMBOL : + { + const char *name; + mrb_int name_length; + + name = mrb_sym2name_len(mrb, mrb_symbol(target), &name_length); + GRN_OUTPUT_STR(name, name_length); + } + break; + case MRB_TT_STRING : + GRN_OUTPUT_STR(RSTRING_PTR(target), RSTRING_LEN(target)); + break; + default : + mrb_raisef(mrb, E_ARGUMENT_ERROR, + "must be nil, true, false, number, float, symbol or string: " + "%S", + target); + break; + } + + return mrb_nil_value(); +} + +static mrb_value +writer_open_array(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *name; + mrb_int n_elements; + + mrb_get_args(mrb, "zi", &name, &n_elements); + GRN_OUTPUT_ARRAY_OPEN(name, n_elements); + + return mrb_nil_value(); +} + +static mrb_value +writer_close_array(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + GRN_OUTPUT_ARRAY_CLOSE(); + + return mrb_nil_value(); +} + +static mrb_value +writer_open_map(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + char *name; + mrb_int n_elements; + + mrb_get_args(mrb, "zi", &name, &n_elements); + GRN_OUTPUT_MAP_OPEN(name, n_elements); + + return mrb_nil_value(); +} + +static mrb_value +writer_close_map(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + + GRN_OUTPUT_MAP_CLOSE(); + + return mrb_nil_value(); +} + +static mrb_value +writer_write_table_columns(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_table; + char *columns; + mrb_int columns_size; + grn_obj *table; + grn_obj_format format; + int n_hits = 0; + int offset = 0; + int limit = 0; + int hits_offset = 0; + + mrb_get_args(mrb, "os", &mrb_table, &columns, &columns_size); + + table = DATA_PTR(mrb_table); + GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, hits_offset); + format.flags |= GRN_OBJ_FORMAT_WITH_COLUMN_NAMES; + { + grn_rc rc; + rc = grn_output_format_set_columns(ctx, &format, + table, columns, columns_size); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FORMAT_FIN(ctx, &format); + grn_mrb_ctx_check(mrb); + } + } + GRN_OUTPUT_TABLE_COLUMNS(table, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + + return mrb_nil_value(); +} + +static mrb_value +writer_write_table_records(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_value mrb_table; + mrb_value mrb_options = mrb_nil_value(); + char *columns; + mrb_int columns_size; + grn_obj *table; + grn_obj_format format; + int n_hits = 0; + int offset = 0; + int limit = -1; + int hits_offset = 0; + + mrb_get_args(mrb, "os|H", &mrb_table, &columns, &columns_size, &mrb_options); + + table = DATA_PTR(mrb_table); + if (!mrb_nil_p(mrb_options)) { + mrb_value mrb_offset; + mrb_value mrb_limit; + + mrb_offset = grn_mrb_options_get_lit(mrb, mrb_options, "offset"); + if (!mrb_nil_p(mrb_offset)) { + offset = mrb_fixnum(mrb_offset); + } + + mrb_limit = grn_mrb_options_get_lit(mrb, mrb_options, "limit"); + if (!mrb_nil_p(mrb_limit)) { + limit = mrb_fixnum(mrb_limit); + } + } + if (limit < 0) { + limit = grn_table_size(ctx, table) + limit + 1; + } + GRN_OBJ_FORMAT_INIT(&format, n_hits, offset, limit, hits_offset); + { + grn_rc rc; + rc = grn_output_format_set_columns(ctx, &format, + table, columns, columns_size); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FORMAT_FIN(ctx, &format); + grn_mrb_ctx_check(mrb); + } + } + GRN_OUTPUT_TABLE_RECORDS(table, &format); + GRN_OBJ_FORMAT_FIN(ctx, &format); + + return mrb_nil_value(); +} + +static mrb_value +writer_set_content_type(mrb_state *mrb, mrb_value self) +{ + grn_ctx *ctx = (grn_ctx *)mrb->ud; + mrb_int content_type; + + mrb_get_args(mrb, "i", &content_type); + + grn_ctx_set_output_type(ctx, content_type); + + return mrb_nil_value(); +} + +void +grn_mrb_writer_init(grn_ctx *ctx) +{ + grn_mrb_data *data = &(ctx->impl->mrb); + mrb_state *mrb = data->state; + struct RClass *module = data->module; + struct RClass *klass; + + klass = mrb_define_class_under(mrb, module, "Writer", mrb->object_class); + + mrb_define_method(mrb, klass, "write", writer_write, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, klass, "open_array", + writer_open_array, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, klass, "close_array", + writer_close_array, MRB_ARGS_NONE()); + mrb_define_method(mrb, klass, "open_map", + writer_open_map, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, klass, "close_map", + writer_close_map, MRB_ARGS_NONE()); + + mrb_define_method(mrb, klass, "write_table_columns", + writer_write_table_columns, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, klass, "write_table_records", + writer_write_table_records, MRB_ARGS_ARG(2, 1)); + + mrb_define_method(mrb, klass, "content_type=", + writer_set_content_type, MRB_ARGS_REQ(1)); +} +#endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h new file mode 100644 index 00000000..7b5b32d4 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/mrb_writer.h @@ -0,0 +1,32 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void grn_mrb_writer_init(grn_ctx *ctx); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/Makefile.am new file mode 100644 index 00000000..835d881b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = \ + command_line \ + context \ + expression_tree \ + initialize \ + logger \ + query_logger + +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/accessor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/accessor.rb new file mode 100644 index 00000000..3ae08fb6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/accessor.rb @@ -0,0 +1,5 @@ +module Groonga + class Accessor + include Indexable + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/backtrace_entry.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/backtrace_entry.rb new file mode 100644 index 00000000..34f95e96 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/backtrace_entry.rb @@ -0,0 +1,28 @@ +module Groonga + class BacktraceEntry + class << self + def parse(entry) + match_data = /:(\d+):?/.match(entry) + file = match_data.pre_match + line = match_data[1].to_i + detail_match_data = /\A(in )?(\S+)\s*/.match(match_data.post_match) + if detail_match_data[1] + method = detail_match_data[2] + message = detail_match_data.post_match + else + method = "" + message = match_data.post_match + end + new(file, line, method, message) + end + end + + attr_reader :file, :line, :method, :message + def initialize(file, line, method, message) + @file = file + @line = line + @method = method + @message = message + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb new file mode 100644 index 00000000..26dfe68c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command.rb @@ -0,0 +1,64 @@ +module Groonga + class Command + @@classes = {} + class << self + def register_class(name, klass) + @@classes[name] = klass + end + + def find_class(name) + @@classes[name] + end + end + + private + def context + @context ||= Context.instance + end + + def writer + @writer ||= context.writer + end + + def query_logger + @query_logger ||= context.query_logger + end + + def cache_key(input) + nil + end + + def cache_output(key, options={}) + if key.nil? + yield + else + cache = Cache.current + cached_value = cache.fetch(key) + if cached_value + context.output = cached_value + query_logger.log(:cache, ":", "cache(#{cached_value.bytesize})") + else + yield + cache.update(key, context.output) if options[:update] + end + end + end + + def run_internal(input) + begin + options = { + :update => (input["cache"] != "no"), + } + cache_output(cache_key(input), options) do + run_body(input) + end + rescue GroongaError => groonga_error + context.set_groonga_error(groonga_error) + nil + rescue => error + context.record_error(:command_error, error) + nil + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_input.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_input.rb new file mode 100644 index 00000000..779edb47 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_input.rb @@ -0,0 +1,15 @@ +module Groonga + class CommandInput + include Enumerable + + def each + args = arguments + arg = Record.new(args, nil) + args.each do |id| + arg.id = id + key = arg.key + yield(key, self[key]) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/Makefile.am new file mode 100644 index 00000000..8d580810 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_command_linedir = $(ruby_scriptsdir)/command_line +ruby_scripts_command_line_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb new file mode 100644 index 00000000..edd16d58 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/grndb.rb @@ -0,0 +1,452 @@ +module Groonga + module CommandLine + class Grndb + def initialize(argv) + @program_path, *@arguments = argv + @succeeded = true + @database_path = nil + end + + def run + command_line_parser = create_command_line_parser + options = nil + begin + options = command_line_parser.parse(@arguments) + rescue Slop::Error => error + $stderr.puts(error.message) + $stderr.puts + $stderr.puts(command_line_parser.help_message) + return false + end + @succeeded + end + + private + def create_command_line_parser + program_name = File.basename(@program_path) + parser = CommandLineParser.new(program_name) + + parser.add_command("check") do |command| + command.description = "Check database" + + options = command.options + options.banner += " DB_PATH" + options.string("--target", "Check only the target object.") + + command.add_action do |options| + open_database(command, options) do |database, rest_arguments| + check(database, options, rest_arguments) + end + end + end + + parser.add_command("recover") do |command| + command.description = "Recover database" + + options = command.options + options.banner += " DB_PATH" + options.boolean("--force-truncate", "Force to truncate corrupted objects.") + + command.add_action do |options| + open_database(command, options) do |database, rest_arguments| + recover(database, options, rest_arguments) + end + end + end + + parser + end + + def open_database(command, options) + arguments = options.arguments + if arguments.empty? + $stderr.puts("Database path is missing") + $stderr.puts + $stderr.puts(command.help_message) + @succeesed = false + return + end + + database = nil + @database_path, *rest_arguments = arguments + begin + database = Database.open(@database_path) + rescue Error => error + $stderr.puts("Failed to open database: <#{@database_path}>") + $stderr.puts(error.message) + @succeeded = false + return + end + + begin + yield(database, rest_arguments) + ensure + database.close + end + end + + def failed(*messages) + messages.each do |message| + $stderr.puts(message) + end + @succeeded = false + end + + def recover(database, options, arguments) + recoverer = Recoverer.new + recoverer.database = database + recoverer.force_truncate = options[:force_truncate] + begin + recoverer.recover + rescue Error => error + failed("Failed to recover database: <#{@database_path}>", + error.message) + end + end + + def check(database, options, arguments) + checker = Checker.new + checker.program_path = @program_path + checker.database_path = @database_path + checker.database = database + checker.on_failure = lambda do |message| + failed(message) + end + + checker.check_database + + target_name = options[:target] + if target_name + checker.check_one(target_name) + else + checker.check_all + end + end + + class Checker + attr_writer :program_path + attr_writer :database_path + attr_writer :database + attr_writer :on_failure + + def initialize + @context = Context.instance + @checked = {} + end + + def check_database + check_database_orphan_inspect + check_database_locked + check_database_corrupt + check_database_dirty + end + + def check_one(target_name) + target = @context[target_name] + if target.nil? + exist_p = open_database_cursor do |cursor| + cursor.any? do + cursor.key == target_name + end + end + if exist_p + failed_to_open(target_name) + else + message = "[#{target_name}] Not exist." + failed(message) + end + return + end + + check_object_recursive(target) + end + + def check_all + open_database_cursor do |cursor| + cursor.each do |id| + next if ID.builtin?(id) + next if builtin_object_name?(cursor.key) + next if @context[id] + failed_to_open(cursor.key) + end + end + + @database.each do |object| + check_object(object) + end + end + + private + def check_database_orphan_inspect + open_database_cursor do |cursor| + cursor.each do |id| + if cursor.key == "inspect" and @context[id].nil? + message = + "Database has orphan 'inspect' object. " + + "Remove it by '#{@program_path} recover #{@database_path}'." + failed(message) + break + end + end + end + end + + def check_database_locked + return unless @database.locked? + + message = + "Database is locked. " + + "It may be broken. " + + "Re-create the database." + failed(message) + end + + def check_database_corrupt + return unless @database.corrupt? + + message = + "Database is corrupt. " + + "Re-create the database." + failed(message) + end + + def check_database_dirty + return unless @database.dirty? + + last_modified = @database.last_modified + if File.stat(@database.path).mtime > last_modified + return + end + + open_database_cursor do |cursor| + cursor.each do |id| + next if ID.builtin?(id) + path = "%s.%07x" % [@database.path, id] + next unless File.exist?(path) + return if File.stat(path).mtime > last_modified + end + end + + message = + "Database wasn't closed successfully. " + + "It may be broken. " + + "Re-create the database." + failed(message) + end + + def check_object(object) + return if @checked.key?(object.id) + @checked[object.id] = true + + check_object_locked(object) + check_object_corrupt(object) + end + + def check_object_locked(object) + case object + when IndexColumn + return unless object.locked? + message = + "[#{object.name}] Index column is locked. " + + "It may be broken. " + + "Re-create index by '#{@program_path} recover #{@database_path}'." + failed(message) + when Column + return unless object.locked? + name = object.name + message = + "[#{name}] Data column is locked. " + + "It may be broken. " + + "(1) Truncate the column (truncate #{name}) or " + + "clear lock of the column (lock_clear #{name}) " + + "and (2) load data again." + failed(message) + when Table + return unless object.locked? + name = object.name + message = + "[#{name}] Table is locked. " + + "It may be broken. " + + "(1) Truncate the table (truncate #{name}) or " + + "clear lock of the table (lock_clear #{name}) " + + "and (2) load data again." + failed(message) + end + end + + def check_object_corrupt(object) + case object + when IndexColumn + return unless object.corrupt? + message = + "[#{object.name}] Index column is corrupt. " + + "Re-create index by '#{@program_path} recover #{@database_path}'." + failed(message) + when Column + return unless object.corrupt? + name = object.name + message = + "[#{name}] Data column is corrupt. " + + "(1) Truncate the column (truncate #{name} or " + + "'#{@program_path} recover --force-truncate #{@database_path}') " + + "and (2) load data again." + failed(message) + when Table + return unless object.corrupt? + name = object.name + message = + "[#{name}] Table is corrupt. " + + "(1) Truncate the table (truncate #{name} or " + + "'#{@program_path} recover --force-truncate #{@database_path}') " + + "and (2) load data again." + failed(message) + end + end + + def check_object_recursive(target) + return if @checked.key?(target.id) + + check_object(target) + case target + when Table + unless target.is_a?(Groonga::Array) + domain_id = target.domain_id + domain = @context[domain_id] + if domain.nil? + record = Record.new(@database, domain_id) + failed_to_open(record.key) + elsif domain.is_a?(Table) + check_object_recursive(domain) + end + end + + target.column_ids.each do |column_id| + column = @context[column_id] + if column.nil? + record = Record.new(@database, column_id) + failed_to_open(record.key) + else + check_object_recursive(column) + end + end + when FixedSizeColumn, VariableSizeColumn + range_id = target.range_id + range = @context[range_id] + if range.nil? + record = Record.new(@database, range_id) + failed_to_open(record.key) + elsif range.is_a?(Table) + check_object_recursive(range) + end + + lexicon_ids = [] + target.indexes.each do |index_info| + index = index_info.index + lexicon_ids << index.domain_id + check_object(index) + end + lexicon_ids.uniq.each do |lexicon_id| + lexicon = @context[lexicon_id] + if lexicon.nil? + record = Record.new(@database, lexicon_id) + failed_to_open(record.key) + else + check_object(lexicon) + end + end + when IndexColumn + range_id = target.range_id + range = @context[range_id] + if range.nil? + record = Record.new(@database, range_id) + failed_to_open(record.key) + return + end + check_object(range) + + target.source_ids.each do |source_id| + source = @context[source_id] + if source.nil? + record = Record.new(database, source_id) + failed_to_open(record.key) + elsif source.is_a?(Column) + check_object_recursive(source) + end + end + end + end + + def open_database_cursor(&block) + flags = + TableCursorFlags::ASCENDING | + TableCursorFlags::BY_ID + TableCursor.open(@database, :flags => flags, &block) + end + + def builtin_object_name?(name) + case name + when "inspect" + # Just for compatibility. It's needed for users who used + # Groonga master at between 2016-02-03 and 2016-02-26. + true + else + false + end + end + + def failed(message) + @on_failure.call(message) + end + + def failed_to_open(name) + message = + "[#{name}] Can't open object. " + + "It's broken. " + + "Re-create the object or the database." + failed(message) + end + end + + class Recoverer + attr_writer :database + attr_writer :force_truncate + + def initialize + @context = Context.instance + end + + def recover + if @force_truncate + truncate_corrupt_objects + end + @database.recover + end + + def truncate_corrupt_objects + @database.each do |object| + next unless object.corrupt? + logger = @context.logger + object_path = object.path + object_dirname = File.dirname(object_path) + object_basename = File.basename(object_path) + object.truncate + Dir.foreach(object_dirname) do |path| + if path.start_with?("#{object_basename}.") + begin + File.unlink("#{object_dirname}/#{path}") + message = "Corrupted <#{object_path}> related file is removed: <#{path}>" + $stdout.puts(message) + logger.log(Logger::Level::INFO.to_i, __FILE__, __LINE__, "truncate_corrupt_objects", message) + rescue Error => error + message = "Failed to remove file which is related to corrupted <#{object_path}>: <#{path}>" + $stderr.puts(message) + logger.log_error(message) + end + end + end + end + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/sources.am new file mode 100644 index 00000000..759948ee --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line/sources.am @@ -0,0 +1,2 @@ +RUBY_SCRIPT_FILES = \ + grndb.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line_parser.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line_parser.rb new file mode 100644 index 00000000..7dad55a7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/command_line_parser.rb @@ -0,0 +1,168 @@ +module Slop + class MissingCommand < Error + end + + class UnknownCommand < Error + attr_reader :name + + def initialize(msg, name) + super(msg) + @name = name + end + end +end + +module Groonga + class CommandLineParser + def initialize(program_name=nil) + $0 ||= nil + @program_name = program_name || $0 + @commands = [] + @action_runner = ActionRunner.new + @options = Slop::Options.new + setup_options + end + + def options + yield(@options) if block_given? + @options + end + + def add_command(name) + command = Command.new(@program_name, name) + setup_common_options(command.options) + yield(command) + @commands << command + end + + def add_action(&action) + @action_runner.add(&action) + end + + def parse(command_line) + if @commands.empty? + result = @options.parse(command_line) + apply_actions(result) + return result + end + + if command_line.empty? + message = "Command is missing" + raise Slop::MissingCommand.new(message) + end + + first_argument = command_line.first + if first_argument.start_with?("-") + result = @options.parse(command_line) + apply_actions(result) + return result + end + + command_name = first_argument + command = find_command(command_name) + if command.nil? + message = "Unknown command: <#{command_name}>" + raise Slop::UnknownCommand.new(message, command_name) + end + + command.parse(command_line[1..-1]) + end + + def help_message + message = @options.to_s + @commands.each do |command| + message << "\n" + indent = " " * 4 + message << "#{command.description}:\n" if command.description + message << "#{indent}#{command.options.banner}\n" + end + message + end + + private + def setup_options + @options.banner = "Usage: #{@program_name} [OPTIONS]" + setup_common_options(@options) + @options.on("-h", "--help", "Display this help message.", + :tail => true) do + $stdout.puts(help_message) + end + end + + def setup_common_options(options) + options.string("--log-path", + "Change log path (#{Logger.default_path})", + default: Logger.default_path) + default_log_level = Logger.default_level + options.string("--log-level", + "Change log level (#{default_log_level.name})", + default: default_log_level) + end + + def find_command(name) + @commands.find do |command| + command.name == name + end + end + + def apply_actions(result) + @action_runner.run(result) unless result.help? + end + + class ActionRunner + def initialize + @actions = [] + end + + def add(&action) + @actions << action + end + + def run(*args) + @actions.each do |action| + action.call(*args) + end + end + end + + class Command + attr_reader :name + attr_reader :options + attr_accessor :description + def initialize(program_name, name) + @program_name = program_name + @name = name + @options = Slop::Options.new + setup_options + @description = nil + @action_runner = ActionRunner.new + end + + def add_action(&action) + @action_runner.add(&action) + end + + def parse(command_line) + result = @options.parse(command_line) + @action_runner.run(result) unless result.help? + result + end + + def help_message + message = "" + message << "Description: #{@description}\n" if @description + message << @options.to_s + message + end + + private + def setup_options + @options.banner = "Usage: #{@program_name} #{@name} [OPTIONS]" + @options.on("-h", "--help", "Display this help message.", + :tail => true) do + $stdout.puts(help_message) + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb new file mode 100644 index 00000000..b6f59dc3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context.rb @@ -0,0 +1,85 @@ +require "context/error_level" +require "context/rc" + +module Groonga + class Context + def guard(fallback=nil) + begin + yield + rescue => error + logger.log_error(error) + fallback + end + end + + def logger + @logger ||= Logger.new + end + + def query_logger + @query_logger ||= QueryLogger.new + end + + def writer + @writer ||= Writer.new + end + + def set_groonga_error(groonga_error) + set_error_raw(groonga_error.class.rc, + ErrorLevel::ERROR, + groonga_error.message, + groonga_error.backtrace) + end + + def record_error(rc, error) + rc = RC.find(rc) if rc.is_a?(Symbol) + set_error_raw(rc, ErrorLevel::ERROR, error.message, error.backtrace) + + logger.log_error(error) + end + + def with_command_version(version) + old_version = command_version + begin + self.command_version = version + yield + ensure + self.command_version = old_version + end + end + + def open_temporary(id) + if Thread.limit == 1 + need_close = !opened?(id) + else + need_close = false + end + object = self[id] + begin + yield(object) + ensure + if need_close and object and !object.closed? + case object + when Table, Column + object.close + end + end + end + end + + private + def set_error_raw(rc, error_level, message, backtrace) + self.rc = rc.to_i + self.error_level = error_level.to_i + + self.error_message = message + + if backtrace + entry = BacktraceEntry.parse(backtrace.first) + self.error_file = entry.file + self.error_line = entry.line + self.error_method = entry.method + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/Makefile.am new file mode 100644 index 00000000..8d862082 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_contextdir = $(ruby_scriptsdir)/context +ruby_scripts_context_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/error_level.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/error_level.rb new file mode 100644 index 00000000..c0685f16 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/error_level.rb @@ -0,0 +1,30 @@ +module Groonga + class Context + class ErrorLevel + @@names = {} + + class << self + def find(name) + @@names[name] + end + end + + attr_reader :name + def initialize(name, level) + @@names[name] = self + @name = name + @level = level + end + + def to_i + @level + end + + EMERGENCY = new(:emergency, 1) + ALERT = new(:alert, 2) + CRITICAL = new(:critical, 3) + ERROR = new(:error, 4) + WARNING = new(:warning, 5) + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb new file mode 100644 index 00000000..45187c22 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/rc.rb @@ -0,0 +1,205 @@ +module Groonga + class Context + class RC + @@codes = {} + @@names = {} + + class << self + def find(name_or_code) + if name_or_code.is_a?(Symbol) + @@names[name_or_code] || UNKNOWN_ERROR + else + @@codes[name_or_code] || UNKNOWN_ERROR + end + end + + def register(name, code, error_class) + rc = new(name, code, error_class) + @@codes[code] = rc + @@names[name] = rc + error_class.rc = rc if error_class + rc + end + end + + attr_reader :name + attr_reader :error_class + def initialize(name, code, error_class) + @name = name + @code = code + @error_class = error_class + end + + def to_i + @code + end + + SUCCESS = + register(:success, 0, nil) + END_OF_DATA = + register(:end_of_data, 1, EndOfData) + UNKNOWN_ERROR = + register(:unknown_error, -1, UnknownError) + OPERATION_NOT_PERMITTED = + register(:operation_not_permitted, -2, OperationNotPermitted) + NO_SUCH_FILE_OR_DIRECTORY = + register(:no_such_file_or_directory, -3, NoSuchFileOrDirectory) + NO_SUCH_PROCESS = + register(:no_such_process, -4, NoSuchProcess) + INTERRUPTED_FUNCTION_CALL = + register(:interrupted_function_call, -5, InterruptedFunctionCall) + INPUT_OUTPUT_ERROR = + register(:input_output_error, -6, InputOutputError) + NO_SUCH_DEVICE_OR_ADDRESS = + register(:no_such_device_or_address, -7, NoSuchDeviceOrAddress) + ARG_LIST_TOO_LONG = + register(:arg_list_too_long, -8, ArgListTooLong) + EXEC_FORMAT_ERROR = + register(:exec_format_error, -9, ExecFormatError) + BAD_FILE_DESCRIPTOR = + register(:bad_file_descriptor, -10, BadFileDescriptor) + NO_CHILD_PROCESSES = + register(:no_child_processes, -11, NoChildProcesses) + RESOURCE_TEMPORARILY_UNAVAILABLE = + register(:resource_temporarily_unavailable, -12, + ResourceTemporarilyUnavailable) + NOT_ENOUGH_SPACE = + register(:not_enough_space, -13, NotEnoughSpace) + PERMISSION_DENIED = + register(:permission_denied, -14, PermissionDenied) + BAD_ADDRESS = + register(:bad_address, -15, BadAddress) + RESOURCE_BUSY = + register(:resource_busy, -16, ResourceBusy) + FILE_EXISTS = + register(:file_exists, -17, FileExists) + IMPROPER_LINK = + register(:improper_link, -18, ImproperLink) + NO_SUCH_DEVICE = + register(:no_such_device, -19, NoSuchDevice) + NOT_DIRECTORY = + register(:not_directory, -20, NotDirectory) + IS_DIRECTORY = + register(:is_directory, -21, IsDirectory) + INVALID_ARGUMENT = + register(:invalid_argument, -22, InvalidArgument) + TOO_MANY_OPEN_FILES_IN_SYSTEM = + register(:too_many_open_files_in_system, -23, TooManyOpenFilesInSystem) + TOO_MANY_OPEN_FILES = + register(:too_many_open_files, -24, TooManyOpenFiles) + INAPPROPRIATE_IO_CONTROL_OPERATION = + register(:inappropriate_io_control_operation, -25, + InappropriateIOControlOperation) + FILE_TOO_LARGE = + register(:file_too_large, -26, FileTooLarge) + NO_SPACE_LEFT_ON_DEVICE = + register(:no_space_left_on_device, -27, NoSpaceLeftOnDevice) + INVALID_SEEK = + register(:invalid_seek, -28, InvalidSeek) + READ_ONLY_FILE_SYSTEM = + register(:read_only_file_system, -29, ReadOnlyFileSystem) + TOO_MANY_LINKS = + register(:too_many_links, -30, TooManyLinks) + BROKEN_PIPE = + register(:broken_pipe, -31, BrokenPipe) + DOMAIN_ERROR = + register(:domain_error, -32, DomainError) + RESULT_TOO_LARGE = + register(:result_too_large, -33, ResultTooLarge) + RESOURCE_DEADLOCK_AVOIDED = + register(:resource_deadlock_avoided, -34, ResourceDeadlockAvoided) + NO_MEMORY_AVAILABLE = + register(:no_memory_available, -35, NoMemoryAvailable) + FILENAME_TOO_LONG = + register(:filename_too_long, -36, FilenameTooLong) + NO_LOCKS_AVAILABLE = + register(:no_locks_available, -37, NoLocksAvailable) + FUNCTION_NOT_IMPLEMENTED = + register(:function_not_implemented, -38, FunctionNotImplemented) + DIRECTORY_NOT_EMPTY = + register(:directory_not_empty, -39, DirectoryNotEmpty) + ILLEGAL_BYTE_SEQUENCE = + register(:illegal_byte_sequence, -40, IllegalByteSequence) + SOCKET_NOT_INITIALIZED = + register(:socket_not_initialized, -41, SocketNotInitialized) + OPERATION_WOULD_BLOCK = + register(:operation_would_block, -42, OperationWouldBlock) + ADDRESS_IS_NOT_AVAILABLE = + register(:address_is_not_available, -43, AddressIsNotAvailable) + NETWORK_IS_DOWN = + register(:network_is_down, -44, NetworkIsDown) + NO_BUFFER = + register(:no_buffer, -45, NoBuffer) + SOCKET_IS_ALREADY_CONNECTED = + register(:socket_is_already_connected, -46, SocketIsAlreadyConnected) + SOCKET_IS_NOT_CONNECTED = + register(:socket_is_not_connected, -47, SocketIsNotConnected) + SOCKET_IS_ALREADY_SHUTDOWNED = + register(:socket_is_already_shutdowned, -48, SocketIsAlreadyShutdowned) + OPERATION_TIMEOUT = + register(:operation_timeout, -49, OperationTimeout) + CONNECTION_REFUSED = + register(:connection_refused, -50, ConnectionRefused) + RANGE_ERROR = + register(:range_error, -51, RangeError) + TOKENIZER_ERROR = + register(:tokenizer_error, -52, TokenizerError) + FILE_CORRUPT = + register(:file_corrupt, -53, FileCorrupt) + INVALID_FORMAT = + register(:invalid_format, -54, InvalidFormat) + OBJECT_CORRUPT = + register(:object_corrupt, -55, ObjectCorrupt) + TOO_MANY_SYMBOLIC_LINKS = + register(:too_many_symbolic_links, -56, TooManySymbolicLinks) + NOT_SOCKET = + register(:not_socket, -57, NotSocket) + OPERATION_NOT_SUPPORTED = + register(:operation_not_supported, -58, OperationNotSupported) + ADDRESS_IS_IN_USE = + register(:address_is_in_use, -59, AddressIsInUse) + ZLIB_ERROR = + register(:zlib_error, -60, ZlibError) + LZ4_ERROR = + register(:lz4_error, -61, LZ4Error) + STACK_OVER_FLOW = + register(:stack_over_flow, -62, StackOverFlow) + SYNTAX_ERROR = + register(:syntax_error, -63, SyntaxError) + RETRY_MAX = + register(:retry_max, -64, RetryMax) + INCOMPATIBLE_FILE_FORMAT = + register(:incompatible_file_format, -65, IncompatibleFileFormat) + UPDATE_NOT_ALLOWED = + register(:update_not_allowed, -66, UpdateNotAllowed) + TOO_SMALL_OFFSET = + register(:too_small_offset, -67, TooSmallOffset) + TOO_LARGE_OFFSET = + register(:too_large_offset, -68, TooLargeOffset) + TOO_SMALL_LIMIT = + register(:too_small_limit, -69, TooSmallLimit) + CAS_ERROR = + register(:cas_error, -70, CASError) + UNSUPPORTED_COMMAND_VERSION = + register(:unsupported_command_version, -71, UnsupportedCommandVersion) + NORMALIZER_ERROR = + register(:normalizer_error, -72, NormalizerError) + TOKEN_FILTER_ERROR = + register(:token_filter_error, -73, TokenFilterError) + COMMAND_ERROR = + register(:command_error, -74, CommandError) + PLUGIN_ERROR = + register(:plugin_error, -75, PluginError) + SCORER_ERROR = + register(:scorer_error, -76, ScorerError) + CANCEL = + register(:cancel, -77, Cancel) + WINDOW_FUNCTION_ERROR = + register(:window_function_error, -78, WindowFunctionError) + ZSTD_ERROR = + register(:zstd_error, -79, ZstdError) + + GroongaError.rc = UNKNOWN_ERROR + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/sources.am new file mode 100644 index 00000000..1f0d1624 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/context/sources.am @@ -0,0 +1,3 @@ +RUBY_SCRIPT_FILES = \ + error_level.rb \ + rc.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb new file mode 100644 index 00000000..e0c6b4a0 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/database.rb @@ -0,0 +1,65 @@ +module Groonga + class Database + def each_raw(options=nil) + return to_enum(__method__, options) unless block_given? + + if options + min = options[:prefix] + order = options[:order] + order_by = options[:order_by] + else + min = nil + order = :ascending + order_by = :id + end + flags = 0 + + if order == :descending + flags |= TableCursorFlags::DESCENDING + else + flags |= TableCursorFlags::ASCENDING + end + if order_by == :id + flags |= TableCursorFlags::BY_ID + else + flags |= TableCursorFlags::BY_KEY + end + flags |= TableCursorFlags::PREFIX if min + TableCursor.open(self, :min => min, :flags => flags) do |cursor| + cursor.each do |id| + yield(id, cursor) + end + end + end + + def each(options=nil) + return to_enum(__method__, options) unless block_given? + + context = Context.instance + each_raw(options) do |id, cursor| + object = context[id] + yield(object) if object + end + end + + def each_name(options=nil) + return to_enum(__method__, options) unless block_given? + + each_raw(options) do |id, cursor| + name = cursor.key + yield(name) + end + end + + def each_table(options={}) + return to_enum(__method__, options) unless block_given? + + context = Context.instance + each_name(options) do |name| + next if name.include?(".") + object = context[name] + yield(object) if object.is_a?(Table) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb new file mode 100644 index 00000000..e39c9045 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/error.rb @@ -0,0 +1,16 @@ +module Groonga + class GroongaError + class << self + def rc + @rc + end + + def rc=(rc) + @rc = rc + end + end + end + + class ErrorMessage < Error + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/eval_context.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/eval_context.rb new file mode 100644 index 00000000..05c7ee8d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/eval_context.rb @@ -0,0 +1,18 @@ +module Groonga + class EvalContext + def eval(script) + proc = compile(script) + instance_eval(&proc) + end + + def method_missing(id, *args, &block) + return super unless args.empty? + return super if block_given? + + object = Context.instance[id.to_s] + return super if object.nil? + + object + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression.rb new file mode 100644 index 00000000..27dadcb7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression.rb @@ -0,0 +1,68 @@ +require "expression_rewriter" +require "expression_rewriters" + +require "expression_tree_builder" + +require "scan_info" +require "scan_info_builder" + +require "scan_info_data_size_estimator" +require "expression_size_estimator" + +module Groonga + class Expression + def rewrite + rewritten = nil + begin + return nil unless ExpressionRewriters.enabled? + source = self + ExpressionRewriters.classes.each do |rewriter_class| + rewriter = rewriter_class.new(source) + new_rewritten = rewriter.rewrite + if new_rewritten + rewritten.close if rewritten + rewritten = new_rewritten + source = rewritten + end + end + rescue GroongaError => groonga_error + context.set_groonga_error(groonga_error) + rewritten.close if rewritten + rewritten = nil + rescue => error + context.record_error(:invalid_argument, error) + rewritten.close if rewritten + rewritten = nil + end + rewritten + end + + def build_scan_info(op, record_exist) + begin + builder = ScanInfoBuilder.new(self, op, record_exist) + builder.build + rescue => error + context.record_error(:invalid_argument, error) + nil + end + end + + def estimate_size(table) + begin + estimator = ExpressionSizeEstimator.new(self, table) + estimator.estimate + rescue GroongaError => groonga_error + context.set_groonga_error(groonga_error) + table.size + rescue => error + context.record_error(:unknown_error, error) + table.size + end + end + + private + def context + @context ||= Context.instance + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_rewriter.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_rewriter.rb new file mode 100644 index 00000000..8f56ca7c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_rewriter.rb @@ -0,0 +1,22 @@ +module Groonga + class ExpressionRewriter + class << self + def register(name) + ExpressionRewriters.register(name, self) + end + end + + def initialize(expression) + @expression = expression + end + + def rewrite + nil + end + + private + def context + @context ||= Context.instance + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_rewriters.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_rewriters.rb new file mode 100644 index 00000000..ae773541 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_rewriters.rb @@ -0,0 +1,41 @@ +module Groonga + module ExpressionRewriters + @rewriters = {} + + class << self + def register(name, rewriter_class) + @rewriters[name] = rewriter_class + end + + def enabled? + rewriters_table_name = + Config["expression_rewriter.table"] || "expression_rewriters" + rewriters_table = Context.instance[rewriters_table_name] + return false if rewriters_table.nil? + return false if rewriters_table.empty? + + true + end + + def classes + rewriters_table_name = + Config["expression_rewriter.table"] || "expression_rewriters" + rewriters_table = Context.instance[rewriters_table_name] + return [] if rewriters_table.nil? + + rewriters_table.collect do |id| + record = Record.new(rewriters_table, id) + name = record.key + rewriter = @rewriters[name] + if rewriter.nil? + plugin_name = record.plugin_name.value + require plugin_name + rewriter = @rewriters[name] + raise "unknown rewriter: <#{name}>:<#{plugin_name}>" if rewriter.nil? + end + rewriter + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_size_estimator.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_size_estimator.rb new file mode 100644 index 00000000..597b56f9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_size_estimator.rb @@ -0,0 +1,54 @@ +module Groonga + class ExpressionSizeEstimator + def initialize(expression, table) + @expression = expression + @table = table + @table_size = @table.size + end + + def estimate + builder = ScanInfoBuilder.new(@expression, Operator::OR, false) + data_list = builder.build + return @table_size if data_list.nil? + + current_size = 0 + sizes = [] + data_list.each do |data| + if (data.flags & ScanInfo::Flags::POP) != 0 + size = sizes.pop + case data.logical_op + when Operator::AND, Operator::AND_NOT + current_size = size if size < current_size + when Operator::OR + current_size = size if size > current_size + else + message = "invalid logical operator: <#{data.logical_op.inspect}>" + raise InvalidArgument, message + end + else + if (data.flags & ScanInfo::Flags::PUSH) != 0 + sizes.push(current_size) + current_size = 0 + end + + estimator = ScanInfoDataSizeEstimator.new(data, @table) + size = estimator.estimate + case data.logical_op + when Operator::AND + current_size = size if size < current_size + when Operator::AND_NOT + size = @table_size - size + size = 0 if size < 0 + current_size = size if size < current_size + when Operator::OR + current_size = size if size > current_size + else + message = "invalid logical operator: <#{data.logical_op.inspect}>" + raise InvalidArgument, message + end + end + end + current_size + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree.rb new file mode 100644 index 00000000..124ace0e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree.rb @@ -0,0 +1,9 @@ +require "expression_tree/accessor" +require "expression_tree/constant" +require "expression_tree/binary_operation" +require "expression_tree/function_call" +require "expression_tree/index_column" +require "expression_tree/logical_operation" +require "expression_tree/options" +require "expression_tree/procedure" +require "expression_tree/variable" diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/Makefile.am new file mode 100644 index 00000000..1235932f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_expression_treedir = $(ruby_scriptsdir)/expression_tree +ruby_scripts_expression_tree_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/accessor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/accessor.rb new file mode 100644 index 00000000..ac4b122f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/accessor.rb @@ -0,0 +1,14 @@ +module Groonga + module ExpressionTree + class Accessor + attr_reader :object + def initialize(object) + @object = object + end + + def build(expression) + expression.append_object(@object, Operator::PUSH, 1) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/binary_operation.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/binary_operation.rb new file mode 100644 index 00000000..d59c65c7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/binary_operation.rb @@ -0,0 +1,67 @@ +module Groonga + module ExpressionTree + class BinaryOperation + attr_reader :operator + attr_reader :left + attr_reader :right + def initialize(operator, left, right) + @operator = operator + @left = left + @right = right + end + + def build(expression) + @left.build(expression) + @right.build(expression) + expression.append_operator(@operator, 2) + end + + RANGE_OPERATORS = [ + Operator::LESS, + Operator::GREATER, + Operator::LESS_EQUAL, + Operator::GREATER_EQUAL, + ] + def estimate_size(table) + case @operator + when *RANGE_OPERATORS + estimate_size_range(table) + else + table.size + end + end + + private + def estimate_size_range(table) + return table.size unless @left.is_a?(Variable) + return table.size unless @right.is_a?(Constant) + + column = @left.column + value = @right.value + index_info = column.find_index(@operator) + return table.size if index_info.nil? + + index_column = index_info.index + lexicon = index_column.lexicon + options = {} + case @operator + when Operator::LESS + options[:max] = value + options[:flags] = TableCursorFlags::LT + when Operator::LESS_EQUAL + options[:max] = value + options[:flags] = TableCursorFlags::LE + when Operator::GREATER + options[:min] = value + options[:flags] = TableCursorFlags::GT + when Operator::GREATER_EQUAL + options[:min] = value + options[:flags] = TableCursorFlags::GE + end + TableCursor.open(lexicon, options) do |cursor| + index_column.estimate_size(:lexicon_cursor => cursor) + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/constant.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/constant.rb new file mode 100644 index 00000000..228a1fc8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/constant.rb @@ -0,0 +1,22 @@ +module Groonga + module ExpressionTree + class Constant + attr_reader :value + def initialize(value) + @value = value + end + + def build(expression) + expression.append_constant(@value, Operator::PUSH, 1) + end + + def estimate_size(table) + if Bulk.true?(@value) + table.size + else + 0 + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/function_call.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/function_call.rb new file mode 100644 index 00000000..0c7438d6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/function_call.rb @@ -0,0 +1,66 @@ +module Groonga + module ExpressionTree + class FunctionCall + attr_reader :procedure + attr_reader :arguments + def initialize(procedure, arguments) + @procedure = procedure + @arguments = arguments + end + + def build(expression) + @procedure.build(expression) + @arguments.each do |argument| + argument.build(expression) + end + expression.append_operator(Operator::CALL, @arguments.size) + end + + def estimate_size(table) + return table.size unless @procedure.name == "between" + + column, min, min_border, max, max_border = @arguments + + if column.is_a?(Groonga::ExpressionTree::IndexColumn) + index_column = column.object + else + index_info = column.column.find_index(Operator::CALL) + return table.size if index_info.nil? + index_column = index_info.index + end + + while index_column.is_a?(Groonga::Accessor) + if index_column.have_next? + index_column = index_column.next + else + index_column = index_column.object + index_info = index_column.find_index(Operator::CALL) + return table.size if index_info.nil? + index_column = index_info.index + end + end + + lexicon = index_column.lexicon + options = { + :min => min.value, + :max => max.value, + :flags => 0, + } + if min_border.value == "include" + options[:flags] |= TableCursorFlags::LT + else + options[:flags] |= TableCursorFlags::LE + end + if max_border.value == "include" + options[:flags] |= TableCursorFlags::GT + else + options[:flags] |= TableCursorFlags::GE + end + + TableCursor.open(lexicon, options) do |cursor| + index_column.estimate_size(:lexicon_cursor => cursor) + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/index_column.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/index_column.rb new file mode 100644 index 00000000..c62a8d19 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/index_column.rb @@ -0,0 +1,14 @@ +module Groonga + module ExpressionTree + class IndexColumn + attr_reader :object + def initialize(object) + @object = object + end + + def build(expression) + expression.append_object(@object, Operator::PUSH, 1) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/logical_operation.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/logical_operation.rb new file mode 100644 index 00000000..e8d494f8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/logical_operation.rb @@ -0,0 +1,33 @@ +module Groonga + module ExpressionTree + class LogicalOperation + attr_reader :operator + attr_reader :nodes + def initialize(operator, nodes) + @operator = operator + @nodes = nodes + end + + def build(expression) + @nodes.each_with_index do |node, i| + node.build(expression) + expression.append_operator(@operator, 2) if i > 0 + end + end + + def estimate_size(table) + estimated_sizes = @nodes.collect do |node| + node.estimate_size(table) + end + case @operator + when Operator::AND + estimated_sizes.min + when Operator::OR + estimated_sizes.max + else + estimated_sizes.first + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/options.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/options.rb new file mode 100644 index 00000000..1504b57a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/options.rb @@ -0,0 +1,14 @@ +module Groonga + module ExpressionTree + class Options + attr_reader :object + def initialize(object) + @object = object + end + + def build(expression) + expression.append_object(@object, Operator::PUSH, 1) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/procedure.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/procedure.rb new file mode 100644 index 00000000..1d63149c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/procedure.rb @@ -0,0 +1,18 @@ +module Groonga + module ExpressionTree + class Procedure + attr_reader :object + def initialize(object) + @object = object + end + + def name + @object.name + end + + def build(expression) + expression.append_object(@object, Operator::PUSH, 1) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/sources.am new file mode 100644 index 00000000..d8a776bf --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/sources.am @@ -0,0 +1,10 @@ +RUBY_SCRIPT_FILES = \ + accessor.rb \ + binary_operation.rb \ + constant.rb \ + function_call.rb \ + index_column.rb \ + logical_operation.rb \ + options.rb \ + procedure.rb \ + variable.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/variable.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/variable.rb new file mode 100644 index 00000000..e99ad9a8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree/variable.rb @@ -0,0 +1,18 @@ +module Groonga + module ExpressionTree + class Variable + attr_reader :column + def initialize(column) + @column = column + end + + def build(expression) + expression.append_object(@column, Operator::GET_VALUE, 1) + end + + def estimate_size(table) + table.size + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree_builder.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree_builder.rb new file mode 100644 index 00000000..f2cc297c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/expression_tree_builder.rb @@ -0,0 +1,111 @@ +require "expression_tree" + +module Groonga + class ExpressionTreeBuilder + RELATION_OPERATORS = [ + Operator::MATCH, + Operator::NEAR, + Operator::NEAR2, + Operator::SIMILAR, + Operator::PREFIX, + Operator::SUFFIX, + Operator::EQUAL, + Operator::NOT_EQUAL, + Operator::LESS, + Operator::GREATER, + Operator::LESS_EQUAL, + Operator::GREATER_EQUAL, + Operator::GEO_WITHINP5, + Operator::GEO_WITHINP6, + Operator::GEO_WITHINP8, + Operator::TERM_EXTRACT, + Operator::REGEXP, + Operator::FUZZY, + ] + + ARITHMETIC_OPERATORS = [ + Operator::BITWISE_OR, + Operator::BITWISE_XOR, + Operator::BITWISE_AND, + Operator::BITWISE_NOT, + Operator::SHIFTL, + Operator::SHIFTR, + Operator::SHIFTRR, + Operator::PLUS, + Operator::MINUS, + Operator::STAR, + Operator::MOD, + ] + + LOGICAL_OPERATORS = [ + Operator::AND, + Operator::OR, + Operator::AND_NOT, + Operator::ADJUST, + ] + + def initialize(expression) + @expression = expression + end + + def build + stack = [] + codes = @expression.codes + codes.each do |code| + case code.op + when *LOGICAL_OPERATORS + right = stack.pop + left = stack.pop + nodes = [] + add_logical_operation_node(code.op, nodes, left) + add_logical_operation_node(code.op, nodes, right) + node = ExpressionTree::LogicalOperation.new(code.op, nodes) + stack.push(node) + when *RELATION_OPERATORS, *ARITHMETIC_OPERATORS + right = stack.pop + left = stack.pop + node = ExpressionTree::BinaryOperation.new(code.op, left, right) + stack.push(node) + when Operator::GET_VALUE + node = ExpressionTree::Variable.new(code.value) + stack.push(node) + when Operator::PUSH + case code.value + when Procedure + node = ExpressionTree::Procedure.new(code.value) + when IndexColumn + node = ExpressionTree::IndexColumn.new(code.value) + when Accessor + node = ExpressionTree::Accessor.new(code.value) + when HashTable + node = ExpressionTree::Options.new(code.value) + else + node = ExpressionTree::Constant.new(code.value.value) + end + stack.push(node) + when Operator::CALL + arguments = [] + (code.n_args - 1).times do + arguments.unshift(stack.pop) + end + procedure = stack.pop + node = ExpressionTree::FunctionCall.new(procedure, arguments) + stack.push(node) + else + raise "unknown operator: #{code.inspect}" + end + end + stack.pop + end + + private + def add_logical_operation_node(operator, nodes, node) + if node.is_a?(ExpressionTree::LogicalOperation) and + node.operator == operator + nodes.concat(node.nodes) + else + nodes << node + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/fixed_size_column.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/fixed_size_column.rb new file mode 100644 index 00000000..4fab9fb7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/fixed_size_column.rb @@ -0,0 +1,5 @@ +module Groonga + class FixedSizeColumn + include Indexable + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/id.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/id.rb new file mode 100644 index 00000000..a49e4fde --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/id.rb @@ -0,0 +1,12 @@ +module Groonga + module ID + # TODO: Should we bind GRN_N_RESERVED_TYPES? + N_RESERVED_TYPES = 256 + + class << self + def builtin?(id) + id < N_RESERVED_TYPES + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_column.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_column.rb new file mode 100644 index 00000000..25ebc149 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_column.rb @@ -0,0 +1,39 @@ +module Groonga + class IndexColumn + private :estimate_size_for_term_id + private :estimate_size_for_query + private :estimate_size_for_lexicon_cursor + + # Estimate the number of matched records for term ID or query. + # + # @overload estimate_size(:term_id => term_id) + # @return [Integer] the number of matched records for the term ID. + # + # @overload estimate_size(:query => query) + # @return [Integer] the number of matched records for the query. + # + # @overload estimate_size(:lexicon_cursor => lexicon_cursor) + # @return [Integer] the number of matched records for the lexicon cursor. + # + def estimate_size(parameters) + term_id = parameters[:term_id] + if term_id + return estimate_size_for_term_id(term_id) + end + + query = parameters[:query] + if query + return estimate_size_for_query(query, parameters) + end + + lexicon_cursor = parameters[:lexicon_cursor] + if lexicon_cursor + return estimate_size_for_lexicon_cursor(lexicon_cursor) + end + + message = + "must specify :term_id, :query, :lexicon_cursor: #{parameters.inspect}" + raise InvalidArgument, message + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb new file mode 100644 index 00000000..80440669 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_cursor.rb @@ -0,0 +1,18 @@ +module Groonga + class IndexCursor + class << self + def open(*arguments) + cursor = open_raw(*arguments) + if block_given? + begin + yield(cursor) + ensure + cursor.close + end + else + cursor + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_info.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_info.rb new file mode 100644 index 00000000..cf8336e5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/index_info.rb @@ -0,0 +1,10 @@ +module Groonga + class IndexInfo + attr_reader :index + attr_reader :section_id + def initialize(index, section_id) + @index = index + @section_id = section_id + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/Makefile.am new file mode 100644 index 00000000..e7531fdc --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_initializedir = $(ruby_scriptsdir)/initialize +ruby_scripts_initialize_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb new file mode 100644 index 00000000..c1215f3e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/post.rb @@ -0,0 +1,28 @@ +require "error" + +require "context" + +require "writer" + +require "id" + +require "object" +require "database" +require "table" +require "record" +require "fixed_size_column" +require "variable_size_column" +require "index_column" +require "accessor" +require "command" +require "command_input" +require "table_cursor" +require "index_cursor" + +require "expression" + +require "plugin_loader" + +require "eval_context" + +require "command_line_parser" diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb new file mode 100644 index 00000000..99300d11 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/pre.rb @@ -0,0 +1,3 @@ +require "backtrace_entry" + +require "operator" diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/sources.am new file mode 100644 index 00000000..3c26e19b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/initialize/sources.am @@ -0,0 +1,3 @@ +RUBY_SCRIPT_FILES = \ + pre.rb \ + post.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb new file mode 100644 index 00000000..95f86974 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger.rb @@ -0,0 +1,34 @@ +module Groonga + class Logger + def log_error(error) + log_level = Level::ERROR.to_i + + if error.is_a?(Error) + message = error.message + else + message = "#{error.class}: #{error.message}" + end + backtrace = error.backtrace + first_raw_entry = backtrace.first + if first_raw_entry + first_entry = BacktraceEntry.parse(first_raw_entry) + file = first_entry.file + line = first_entry.line + method = first_entry.method + # message = "#{file}:#{line}:#{method}: #{message}" + else + file = "" + line = 0 + method = "" + end + log(log_level, file, line, method, message) + + backtrace.each_with_index do |raw_entry, i| + entry = BacktraceEntry.parse(raw_entry) + message = entry.message + message = raw_entry if message.empty? + log(log_level, entry.file, entry.line, entry.method, raw_entry) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/Makefile.am new file mode 100644 index 00000000..448e72ca --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_loggerdir = $(ruby_scriptsdir)/logger +ruby_scripts_logger_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/level.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/level.rb new file mode 100644 index 00000000..4b8afa2c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/level.rb @@ -0,0 +1,40 @@ +module Groonga + class Logger + class Level + @@names = {} + @@levels = {} + class << self + def find(name_or_level) + if name_or_level.is_a?(Integer) + @@levels[name_or_level] + else + @@names[name_or_level] + end + end + end + + attr_reader :name + def initialize(name, level) + @@names[name] = self + @@levels[level] = self + @name = name + @level = level + end + + def to_i + @level + end + + NONE = new(:none, 0) + EMERG = new(:emerg, 1) + ALERT = new(:alert, 2) + CRIT = new(:crit, 3) + ERROR = new(:error, 4) + WARNING = new(:warning, 5) + NOTICE = new(:notice, 6) + INFO = new(:info, 7) + DEBUG = new(:debug, 8) + DUMP = new(:dump, 9) + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/sources.am new file mode 100644 index 00000000..7231ee4e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/logger/sources.am @@ -0,0 +1,2 @@ +RUBY_SCRIPT_FILES = \ + level.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/object.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/object.rb new file mode 100644 index 00000000..aa8e9e65 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/object.rb @@ -0,0 +1,18 @@ +module Groonga + class Object + def domain + Context.instance[domain_id] + end + + def range + Context.instance[range_id] + end + + def corrupt? + check_corrupt + false + rescue + true + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/operator.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/operator.rb new file mode 100644 index 00000000..349695e1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/operator.rb @@ -0,0 +1,22 @@ +module Groonga + class Operator + @values = {} + class << self + def register(operator) + const_set(operator.name, operator) + @values[operator.value] = operator + end + + def find(value) + @values[value] + end + end + + attr_reader :name + attr_reader :value + def initialize(name, value) + @name = name + @value = value + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb new file mode 100644 index 00000000..09b972f1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/plugin_loader.rb @@ -0,0 +1,14 @@ +module Groonga + class PluginLoader + class << self + def load_file(path) + begin + load(path) + rescue => error + Context.instance.record_error(:plugin_error, error) + nil + end + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger.rb new file mode 100644 index 00000000..386ec0e2 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger.rb @@ -0,0 +1,9 @@ +module Groonga + class QueryLogger + def log(flag, mark, message) + flag = Flag.find(flag) if flag.is_a?(Symbol) + flag = flag.to_i if flag.is_a?(Flag) + log_raw(flag, mark, message) + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/Makefile.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/Makefile.am new file mode 100644 index 00000000..14b4f61c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/Makefile.am @@ -0,0 +1,9 @@ +include sources.am + +EXTRA_DIST = \ + $(RUBY_SCRIPT_FILES) + +if WITH_MRUBY +ruby_scripts_query_loggerdir = $(ruby_scriptsdir)/query_logger +ruby_scripts_query_logger_DATA = $(RUBY_SCRIPT_FILES) +endif diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/flag.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/flag.rb new file mode 100644 index 00000000..659570f6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/flag.rb @@ -0,0 +1,39 @@ +module Groonga + class QueryLogger + class Flag + @@names = {} + class << self + def find(name) + @@names[name] + end + end + + attr_reader :name + def initialize(name, flag) + @@names[name] = self + @name = name + @flag = flag + end + + def to_i + @flag + end + + NONE = new(:none, 0x00) + COMMAND = new(:command, 0x01 << 0) + RESULT_CODE = new(:result_code, 0x01 << 1) + DESTINATION = new(:destination, 0x01 << 2) + CACHE = new(:cache, 0x01 << 3) + SIZE = new(:size, 0x01 << 4) + SCORE = new(:score, 0x01 << 5) + + all_flags = COMMAND.to_i | + RESULT_CODE.to_i | + DESTINATION.to_i | + CACHE.to_i | + SIZE.to_i | + SCORE.to_i + ALL = new(:all, all_flags) + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/sources.am new file mode 100644 index 00000000..44871a85 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/query_logger/sources.am @@ -0,0 +1,2 @@ +RUBY_SCRIPT_FILES = \ + flag.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/record.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/record.rb new file mode 100644 index 00000000..cd7d1a4c --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/record.rb @@ -0,0 +1,38 @@ +module Groonga + class Record + attr_reader :table + attr_reader :id + + def inspect + super.gsub(/>\z/) do + "@id=#{@id.inspect}, @table=#{@table.inspect}>" + end + end + + def [](name) + column = find_column(name) + if column.nil? + raise InvalidArgument, "unknown column: <#{absolute_column_name(name)}>" + end + column[@id] + end + + def method_missing(name, *args, &block) + return super unless args.empty? + + column = find_column(name) + return super if column.nil? + + column[@id] + end + + private + def absolute_column_name(name) + "#{@table.name}.#{name}" + end + + def find_column(name) + Context.instance[absolute_column_name(name)] + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb new file mode 100644 index 00000000..1352b327 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/require.rb @@ -0,0 +1,71 @@ +$" = [__FILE__] + +class ScriptLoader + @@loading_paths = {} + + def initialize(path) + @base_path = path + end + + def load_once + if absolute_path?(@base_path) + loaded = load_once_path(@base_path) + if loaded.nil? + raise LoadError, error_message + else + loaded + end + else + $LOAD_PATH.each do |load_path| + unless absolute_path?(load_path) + load_path = File.expand_path(load_path) + if File::ALT_SEPARATOR + load_path = load_path.gsub(File::ALT_SEPARATOR, "/") + end + end + loaded = load_once_path(File.join(load_path, @base_path)) + return loaded unless loaded.nil? + end + raise LoadError, error_message + end + end + + private + def error_message + "cannot load such file -- #{@base_path}" + end + + def absolute_path?(path) + path.start_with?("/") or (/\A[a-z]:\\/i === path) + end + + def load_once_path(path) + loaded = load_once_absolute_path(path) + return loaded unless loaded.nil? + + return nil unless File.extname(path).empty? + + load_once_absolute_path("#{path}.rb") + end + + def load_once_absolute_path(path) + return false if $".include?(path) + return false if @@loading_paths.key?(path) + + return nil unless File.file?(path) + + @@loading_paths[path] = true + load(path) + $" << path + @@loading_paths.delete(path) + + true + end +end + +module Kernel + def require(path) + loader = ScriptLoader.new(path) + loader.load_once + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb new file mode 100644 index 00000000..acdb2eeb --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info.rb @@ -0,0 +1,38 @@ +module Groonga + class ScanInfo + module Flags + ACCESSOR = 0x01 + PUSH = 0x02 + POP = 0x04 + PRE_CONST = 0x08 + end + + def apply(data) + self.op = data.op + self.logical_op = data.logical_op + self.end = data.end + self.query = data.query + self.flags = data.flags + if data.max_interval + self.max_interval = data.max_interval + end + if data.similarity_threshold + self.similarity_threshold = data.similarity_threshold + end + data.args.each do |arg| + push_arg(arg) + end + data.search_indexes.each do |search_index| + put_index(search_index.index_column, + search_index.section_id, + search_index.weight, + search_index.scorer, + search_index.scorer_args_expr, + search_index.scorer_args_expr_offset || 0) + end + if data.start_position + self.start_position = data.start_position + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb new file mode 100644 index 00000000..66dad9ea --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_builder.rb @@ -0,0 +1,577 @@ +require "scan_info_data" + +module Groonga + class ScanInfoBuilder + def initialize(expression, operator, record_exist) + @data_list = [] + @expression = expression + @operator = operator + @record_exist = record_exist + @variable = @expression[0] + @table = Context.instance[@variable.domain] + end + + RELATION_OPERATORS = [ + Operator::MATCH, + Operator::NEAR, + Operator::NEAR2, + Operator::SIMILAR, + Operator::PREFIX, + Operator::SUFFIX, + Operator::EQUAL, + Operator::NOT_EQUAL, + Operator::LESS, + Operator::GREATER, + Operator::LESS_EQUAL, + Operator::GREATER_EQUAL, + Operator::GEO_WITHINP5, + Operator::GEO_WITHINP6, + Operator::GEO_WITHINP8, + Operator::TERM_EXTRACT, + Operator::REGEXP, + Operator::FUZZY, + ] + + ARITHMETIC_OPERATORS = [ + Operator::BITWISE_OR, + Operator::BITWISE_XOR, + Operator::BITWISE_AND, + Operator::BITWISE_NOT, + Operator::SHIFTL, + Operator::SHIFTR, + Operator::SHIFTRR, + Operator::PLUS, + Operator::MINUS, + Operator::STAR, + Operator::MOD, + ] + + LOGICAL_OPERATORS = [ + Operator::AND, + Operator::OR, + Operator::AND_NOT, + Operator::ADJUST, + ] + def build + return nil unless valid? + + context = BuildContext.new(@expression) + codes = context.codes + while context.have_next? + code = context.code + code_op = context.code_op + i = context.i + context.next + + case code_op + when *RELATION_OPERATORS + context.status = :start + data = context.data + data.op = code_op + data.end = i + data.weight = code.value.value if code.value + data.match_resolve_index + @data_list << data + context.data = nil + when *LOGICAL_OPERATORS + if context.status == :const + data = context.data + data.op = Operator::PUSH + data.end = data.start + @data_list << data + context.data = nil + end + put_logical_op(code_op, i) + # TODO: rescue and return nil + context.status = :start + when Operator::PUSH + context.data ||= ScanInfoData.new(i) + data = context.data + if code.value == @variable + context.status = :var + else + data.args << code.value + if context.status == :start + data.flags |= ScanInfo::Flags::PRE_CONST + end + context.status = :const + end + if code.modify > 0 and + LOGICAL_OPERATORS.include?(codes[i + code.modify].op) + data.op = Operator::PUSH + data.end = data.start + @data_list << data + context.data = nil + context.status = :start + end + when Operator::GET_VALUE + case context.status + when :start + context.data ||= ScanInfoData.new(i) + data = context.data + context.status = :column1 + data.args << code.value + when :const, :var + context.status = :column1 + data.args << code.value + when :column1 + message = "invalid expression: can't use column as a value: " + message << "<#{code.value.name}>: <#{@expression.grn_inspect}>" + raise ErrorMessage, message + when :column2 + # Do nothing + else + message = "internal expression parsing error: unknown status: " + message << "<#{context.status.inspect}>: " + message << "<#{@expression.grn_inspect}>" + raise ErrorMessage, message + end + when Operator::CALL + context.data ||= ScanInfoData.new(i) + data = context.data + if (code.flags & ExpressionCode::Flags::RELATIONAL_EXPRESSION) != 0 or + (not context.have_next?) + context.status = :start + data.op = code_op + data.end = i + data.call_relational_resolve_indexes + @data_list << data + context.data = nil + else + context.status = :column2 + end + when Operator::GET_REF + context.data ||= ScanInfoData.new(i) + case context.status + when :start + data = context.data + context.status = :column1 + data.args << code.value + end + when Operator::GET_MEMBER + data = context.data + index = data.args.pop + data.start_position = index.value + context.status = :column1 + when Operator::NOT + success = build_not(context, code, i) + return nil unless success + end + end + + if @operator == Operator::OR and !@record_exist + first_data = @data_list.first + if (first_data.flags & ScanInfo::Flags::PUSH) == 0 or + first_data.logical_op != @operator + raise ErrorMessage, "invalid expr" + else + first_data.flags &= ~ScanInfo::Flags::PUSH + first_data.logical_op = @operator + end + else + put_logical_op(@operator, context.n_codes) + end + + optimize + end + + private + def valid? + n_relation_expressions = 0 + n_logical_expressions = 0 + status = :start + codes = @expression.codes + codes.each_with_index do |code, i| + case code.op + when *RELATION_OPERATORS + if status == :start || status == :var + return false + end + status = :start + n_relation_expressions += 1 + when *ARITHMETIC_OPERATORS + if status == :start || status == :var + return false + end + status = :start + return false if n_relation_expressions != (n_logical_expressions + 1) + when *LOGICAL_OPERATORS + case status + when :start + n_logical_expressions += 1 + return false if n_logical_expressions >= n_relation_expressions + when :const + n_logical_expressions += 1 + n_relation_expressions += 1 + return false if n_logical_expressions >= n_relation_expressions + status = :start + else + return false + end + when Operator::PUSH + if code.modify > 0 and + LOGICAL_OPERATORS.include?(codes[i + code.modify].op) + n_relation_expressions += 1 + status = :start + else + if code.value == @variable + status = :var + else + status = :const + end + end + when Operator::GET_VALUE + case status + when :start, :const, :var + status = :column1 + when :column1 + status = :column2 + when :column2 + # Do nothing + else + return false + end + when Operator::CALL + if (code.flags & ExpressionCode::Flags::RELATIONAL_EXPRESSION) != 0 or + code == codes.last + status = :start + n_relation_expressions += 1 + else + status = :column2 + end + when Operator::GET_REF + case status + when :start + status = :column1 + else + return false + end + when Operator::GET_MEMBER + case status + when :const + return false unless codes[i - 1].value.value.is_a?(Integer) + status = :column1 + else + return false + end + when Operator::NOT + # Do nothing + else + return false + end + end + + return false if status != :start + return false if n_relation_expressions != (n_logical_expressions + 1) + + true + end + + def put_logical_op(operator, start) + n_parens = 1 + n_dif_ops = 0 + r = 0 + j = @data_list.size + while j > 0 + j -= 1 + data = @data_list[j] + if (data.flags & ScanInfo::Flags::POP) != 0 + n_dif_ops += 1 + n_parens += 1 + else + if (data.flags & ScanInfo::Flags::PUSH) != 0 + n_parens -= 1 + if n_parens == 0 + if r == 0 + if n_dif_ops > 0 + if j > 0 and operator != Operator::AND_NOT + n_parens = 1 + n_dif_ops = 0 + r = j + else + new_data = ScanInfoData.new(start) + new_data.flags = ScanInfo::Flags::POP + new_data.logical_op = operator + @data_list << new_data + break + end + else + data.flags &= ~ScanInfo::Flags::PUSH + data.logical_op = operator + break + end + else + if n_dif_ops > 0 + new_data = ScanInfoData.new(start) + new_data.flags = ScanInfo::Flags::POP + new_data.logical_op = operator + @data_list << new_data + else + data.flags &= ~ScanInfo::Flags::PUSH + data.logical_op = operator + @data_list = + @data_list[0...j] + + @data_list[r..-1] + + @data_list[j...r] + end + break + end + end + else + if operator == Operator::AND_NOT or operator != data.logical_op + n_dif_ops += 1 + end + end + end + + if j < 0 + raise ErrorMessage, "unmatched nesting level" + end + end + end + + def build_not(context, code, i) + last_data = @data_list.last + return false if last_data.nil? + + case last_data.op + when Operator::LESS + last_data.op = Operator::GREATER_EQUAL + last_data.end += 1 + when Operator::LESS_EQUAL + last_data.op = Operator::GREATER + last_data.end += 1 + when Operator::GREATER + last_data.op = Operator::LESS_EQUAL + last_data.end += 1 + when Operator::GREATER_EQUAL + last_data.op = Operator::LESS + last_data.end += 1 + when Operator::NOT_EQUAL + last_data.op = Operator::EQUAL + last_data.end += 1 + else + if @data_list.size == 1 + if last_data.search_indexes.empty? + if last_data.op == Operator::EQUAL + last_data.op = Operator::NOT_EQUAL + last_data.end += 1 + else + return false + end + else + last_data.logical_op = Operator::AND_NOT + last_data.flags &= ~ScanInfo::Flags::PUSH + @data_list.unshift(create_all_match_data) + end + else + next_code = context.code + return false if next_code.nil? + + case next_code.op + when Operator::AND + context.code_op = Operator::AND_NOT + when Operator::AND_NOT + context.code_op = Operator::AND + when Operator::OR + @data_list[-1, 0] = create_all_match_data + put_logical_op(Operator::AND_NOT, i) + else + return false + end + end + end + + true + end + + def optimize + optimized_data_list = [] + i = 0 + n = @data_list.size + while i < n + data = @data_list[i] + next_data = @data_list[i + 1] + i += 1 + if next_data.nil? + optimized_data_list << data + next + end + if range_operations?(data, next_data) + between_data = create_between_data(data, next_data) + optimized_data_list << between_data + i += 1 + next + end + optimized_data_list << data + end + + optimize_by_estimated_size(optimized_data_list) + end + + def optimize_by_estimated_size(data_list) + return data_list unless Groonga::ORDER_BY_ESTIMATED_SIZE + + start_index = nil + data_list.size.times do |i| + data = data_list[i] + if data.logical_op != Operator::AND + if start_index.nil? + start_index = i + else + sort_by_estimated_size!(data_list, start_index...i) + start_index = nil + end + end + end + unless start_index.nil? + sort_by_estimated_size!(data_list, start_index...data_list.size) + end + data_list + end + + def sort_by_estimated_size!(data_list, range) + target_data_list = data_list[range] + return if target_data_list.size < 2 + + start_logical_op = target_data_list.first.logical_op + sorted_data_list = target_data_list.sort_by do |data| + estimator = ScanInfoDataSizeEstimator.new(data, @table) + estimator.estimate + end + sorted_data_list.each do |sorted_data| + sorted_data.logical_op = Operator::AND + end + sorted_data_list.first.logical_op = start_logical_op + data_list[range] = sorted_data_list + end + + def range_operations?(data, next_data) + return false unless next_data.logical_op == Operator::AND + + op, next_op = data.op, next_data.op + return false if !(lower_condition?(op) or lower_condition?(next_op)) + return false if !(upper_condition?(op) or upper_condition?(next_op)) + + return false if data.args[0] != next_data.args[0] + + data_search_indexes = data.search_indexes + return false if data_search_indexes.empty? + + data_search_indexes == next_data.search_indexes + end + + def lower_condition?(operator) + case operator + when Operator::GREATER, Operator::GREATER_EQUAL + true + else + false + end + end + + def upper_condition?(operator) + case operator + when Operator::LESS, Operator::LESS_EQUAL + true + else + false + end + end + + def create_all_match_data + data = ScanInfoData.new(0) + data.end = 0 + data.flags = ScanInfo::Flags::PUSH + data.op = Operator::CALL + data.logical_op = Operator::OR + data.args = [Context.instance["all_records"]] + data.search_indexes = [] + data + end + + def create_between_data(data, next_data) + between_data = ScanInfoData.new(data.start) + between_data.end = next_data.end + 1 + between_data.flags = data.flags + between_data.op = Operator::CALL + between_data.logical_op = data.logical_op + between_data.args = create_between_data_args(data, next_data) + between_data.search_indexes = data.search_indexes + between_data + end + + def create_between_data_args(data, next_data) + between = Context.instance["between"] + @expression.take_object(between) + column = data.args[0] + op, next_op = data.op, next_data.op + if lower_condition?(op) + min = data.args[1] + min_operator = op + max = next_data.args[1] + max_operator = next_op + else + min = next_data.args[1] + min_operator = next_op + max = data.args[1] + max_operator = op + end + if min_operator == Operator::GREATER + min_border = "exclude" + else + min_border = "include" + end + if max_operator == Operator::LESS + max_border = "exclude" + else + max_border = "include" + end + + [ + between, + column, + min, + @expression.allocate_constant(min_border), + max, + @expression.allocate_constant(max_border), + ] + end + + class BuildContext + attr_accessor :status + attr_reader :codes + attr_reader :n_codes + attr_reader :i + attr_writer :code_op + attr_accessor :data + def initialize(expression) + @expression = expression + @status = :start + @current_data = nil + @codes = @expression.codes + @n_codes = @codes.size + @i = 0 + @code_op = nil + @data = nil + end + + def have_next? + @i < @n_codes + end + + def next + @i += 1 + @code_op = nil + end + + def code + @codes[@i] + end + + def code_op + @code_op || code.op + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb new file mode 100644 index 00000000..342f7a7a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data.rb @@ -0,0 +1,324 @@ +require "scan_info_search_index" + +module Groonga + class ScanInfoData + attr_accessor :start + attr_accessor :end + attr_accessor :op + attr_accessor :logical_op + attr_accessor :query + attr_accessor :args + attr_accessor :search_indexes + attr_accessor :flags + attr_accessor :max_interval + attr_accessor :similarity_threshold + attr_accessor :start_position + attr_accessor :weight + def initialize(start) + @start = start + @end = 0 + @op = Operator::NOP + @logical_op = Operator::OR + @query = nil + @args = [] + @search_indexes = [] + @flags = ScanInfo::Flags::PUSH + @max_interval = nil + @similarity_threshold = nil + @start_position = nil + @weight = 0 + end + + def match_resolve_index + if near_search? + match_near_resolve_index + elsif similar_search? + match_similar_resolve_index + else + match_generic_resolve_index + end + end + + def call_relational_resolve_indexes + procedure, *args = *@args + return unless procedure.selector? + + selector_op = procedure.selector_operator + args.each do |arg| + call_relational_resolve_index(arg, selector_op) + end + end + + private + def near_search? + (@op == Operator::NEAR or @op == Operator::NEAR2) and @args.size == 3 + end + + def match_near_resolve_index + arg = @args[0] + case arg + when Expression + match_resolve_index_expression(arg) + when Accessor + match_resolve_index_accessor(arg) + when Indexable + match_resolve_index_indexable(arg) + else + message = + "The first argument of NEAR/NEAR2 must be Expression, Accessor or Indexable: #{arg.class}" + raise ErrorMessage, message + end + + self.query = @args[1] + self.max_interval = @args[2].value + end + + def similar_search? + @op == Operator::SIMILAR and @args.size == 3 + end + + def match_similar_resolve_index + arg = @args[0] + case arg + when Expression + match_resolve_index_expression(arg) + when Accessor + match_resolve_index_accessor(arg) + when Indexable + match_resolve_index_indexable(arg) + else + message = + "The first argument of SIMILAR must be Expression, Accessor or Indexable: #{arg.class}" + raise ErrorMesesage, message + end + + self.query = @args[1] + self.similarity_threshold = @args[2].value + end + + def match_generic_resolve_index + @args.each do |arg| + case arg + when Expression + match_resolve_index_expression(arg) + when Accessor + match_resolve_index_accessor(arg) + when IndexColumn + match_resolve_index_index_column(arg) + when Indexable + match_resolve_index_indexable(arg) + when Procedure + break + else + self.query = arg + end + end + if @op == Operator::REGEXP and not index_searchable_regexp?(@query) + @search_indexes.clear + end + end + + def index_searchable_regexp?(pattern) + return false if pattern.nil? + + previous_char = nil + pattern.value.each_char do |char| + if previous_char == "\\" + case char + when "Z" + return false + when "b", "B" + return false + when "d", "D", "h", "H", "p", "s", "S", "w", "W" + return false + when "X" + return false + when "k", "g", "1", "2", "3", "4", "5", "6", "7", "8", "9" + return false + when "\\" + previous_char = nil + next + end + else + case char + when ".", "[", "]", "|", "?", "+", "*", "{", "}", "^", "$", "(", ")" + return false + end + end + previous_char = char + end + true + end + + def match_resolve_index_expression(expression) + codes = expression.codes + n_codes = codes.size + i = 0 + while i < n_codes + i = match_resolve_index_expression_codes(expression, codes, i, n_codes) + end + end + + def match_resolve_index_expression_codes(expression, codes, i, n_codes) + code = codes[i] + value = code.value + return i + 1 if value.nil? + + case value + when Accessor, Column + index_info, offset = + match_resolve_index_expression_find_index(expression, + codes, i, n_codes) + i += offset - 1 + if index_info + if value.is_a?(Accessor) + self.flags |= ScanInfo::Flags::ACCESSOR + end + weight, offset = codes[i].weight + i += offset + put_search_index(index_info.index, index_info.section_id, weight) + end + when Procedure + unless value.scorer? + message = "procedure must be scorer: #{scorer.name}>" + raise ErrorMessage, message + end + scorer = value + i += 1 + index_info, offset = + match_resolve_index_expression_find_index(expression, + codes, i, n_codes) + i += offset + if index_info + scorer_args_expr_offset = 0 + if codes[i].op != Operator::CALL + scorer_args_expr_offset = i + end + while i < n_codes and codes[i].op != Operator::CALL + i += 1 + end + weight, offset = codes[i].weight + i += offset + put_search_index(index_info.index, + index_info.section_id, + weight, + scorer, + expression, + scorer_args_expr_offset) + end + when Table + raise ErrorMessage, "invalid match target: <#{value.name}>" + end + i + 1 + end + + def match_resolve_index_expression_find_index(expression, codes, i, n_codes) + code = codes[i] + value = code.value + index_info = nil + offset = 1 + case value + when Accessor + accessor = value + index_info = accessor.find_index(@op) + if index_info + if accessor.have_next? and index_info.index != accessor.object + index_info = IndexInfo.new(accessor, index_info.section_id) + end + end + when FixedSizeColumn, VariableSizeColumn + index_info = value.find_index(@op) + when IndexColumn + index = value + section_id = 0 + rest_n_codes = n_codes - i + if rest_n_codes >= 2 and + codes[i + 1].value.is_a?(Bulk) and + (codes[i + 1].value.domain == ID::UINT32 or + codes[i + 1].value.domain == ID::INT32) and + codes[i + 2].op == Operator::GET_MEMBER + section_id = codes[i + 1].value.value + 1 + offset += 2 + end + index_info = IndexInfo.new(index, section_id) + end + + [index_info, offset] + end + + def match_resolve_index_expression_accessor(expr_code) + accessor = expr_code.value + self.flags |= ScanInfo::Flags::ACCESSOR + index_info = accessor.find_index(op) + return if index_info.nil? + + section_id = index_info.section_id + weight = expr_code.weight + if accessor.next + put_search_index(accessor, section_id, weight) + else + put_search_index(index_info.index, section_id, weight) + end + end + + def match_resolve_index_expression_data_column(expr_code) + column = expr_code.value + index_info = column.find_index(op) + return if index_info.nil? + put_search_index(index_info.index, index_info.section_id, expr_code.weight) + end + + def match_resolve_index_index_column(index) + put_search_index(index, 0, 1) + end + + def match_resolve_index_indexable(indexable) + index_info = indexable.find_index(op) + return if index_info.nil? + put_search_index(index_info.index, index_info.section_id, 1) + end + + def match_resolve_index_accessor(accessor) + self.flags |= ScanInfo::Flags::ACCESSOR + index_info = accessor.find_index(op) + return if index_info.nil? + if accessor.next + put_search_index(accessor, index_info.section_id, 1) + else + put_search_index(index_info.index, index_info.section_id, 1) + end + end + + def call_relational_resolve_index(object, selector_op) + case object + when Accessor + call_relational_resolve_index_accessor(object, selector_op) + when Bulk + self.query = object + when Indexable + call_relational_resolve_index_indexable(object, selector_op) + end + end + + def call_relational_resolve_index_indexable(indexable, selector_op) + index_info = indexable.find_index(selector_op) + return if index_info.nil? + put_search_index(index_info.index, index_info.section_id, 1) + end + + def call_relational_resolve_index_accessor(accessor, selector_op) + self.flags |= ScanInfo::Flags::ACCESSOR + index_info = accessor.find_index(selector_op) + return if index_info.nil? + put_search_index(index_info.index, index_info.section_id, 1) + end + + def put_search_index(index, section_id, weight, *args) + search_index = ScanInfoSearchIndex.new(index, + section_id, + weight + @weight, + *args) + @search_indexes << search_index + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data_size_estimator.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data_size_estimator.rb new file mode 100644 index 00000000..5d3dc4e0 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_data_size_estimator.rb @@ -0,0 +1,185 @@ +module Groonga + class ScanInfoDataSizeEstimator + def initialize(data, table) + @data = data + @table = table + @table_size = @table.size + end + + def estimate + search_index = @data.search_indexes.first + return @table_size if search_index.nil? + + index_column = resolve_index_column(search_index.index_column) + return @table_size if index_column.nil? + + size = nil + case @data.op + when Operator::MATCH, + Operator::FUZZY + size = estimate_match(index_column) + when Operator::REGEXP + size = estimate_regexp(index_column) + when Operator::EQUAL + size = estimate_equal(index_column) + when Operator::LESS, + Operator::LESS_EQUAL, + Operator::GREATER, + Operator::GREATER_EQUAL + size = estimate_range(index_column) + when Operator::PREFIX + size = estimate_prefix(index_column) + when Operator::CALL + size = estimate_call(index_column) + end + size || @table_size + end + + private + def resolve_index_column(index_column) + while index_column.is_a?(Accessor) + index_info = index_column.find_index(@data.op) + return nil if index_info.nil? + break if index_info.index == index_column + index_column = index_info.index + end + + index_column + end + + def sampling_cursor_limit(n_terms) + limit = n_terms * 0.01 + if limit < 10 + 10 + elsif limit > 1000 + 1000 + else + limit.to_i + end + end + + def estimate_match(index_column) + index_column.estimate_size(:query => @data.query.value) + end + + def estimate_regexp(index_column) + index_column.estimate_size(:query => @data.query.value, + :mode => @data.op) + end + + def estimate_equal(index_column) + query = @data.query + if index_column.is_a?(Accessor) + table = index_column.object + if index_column.name == "_id" + if table.id?(query.value) + 1 + else + 0 + end + else + if table[query.value] + 1 + else + 0 + end + end + else + lexicon = index_column.lexicon + if query.domain == lexicon.id + term_id = query.value + else + term_id = lexicon[query] + end + return 0 if term_id.nil? + + index_column.estimate_size(:term_id => term_id) + end + end + + def estimate_range(index_column) + if index_column.is_a?(Table) + is_table_search = true + lexicon = index_column + elsif index_column.is_a?(Groonga::Accessor) + is_table_search = true + lexicon = index_column.object + else + is_table_search = false + lexicon = index_column.lexicon + end + n_terms = lexicon.size + return 0 if n_terms.zero? + + value = @data.query.value + options = { + :limit => sampling_cursor_limit(n_terms), + } + case @data.op + when Operator::LESS + options[:max] = value + options[:flags] = TableCursorFlags::LT + when Operator::LESS_EQUAL + options[:max] = value + options[:flags] = TableCursorFlags::LE + when Operator::GREATER + options[:min] = value + options[:flags] = TableCursorFlags::GT + when Operator::GREATER_EQUAL + options[:min] = value + options[:flags] = TableCursorFlags::GE + end + TableCursor.open(lexicon, options) do |cursor| + if is_table_search + size = 1 + else + size = index_column.estimate_size(:lexicon_cursor => cursor) + end + size += 1 if cursor.next != ID::NIL + size + end + end + + def estimate_prefix(index_column) + is_table_search = + (index_column.is_a?(Accessor) and + index_column.name == "_key") + if is_table_search + lexicon = index_column.object + else + lexicon = index_column.lexicon + end + n_terms = lexicon.size + return 0 if n_terms.zero? + + value = @data.query.value + options = { + :min => value, + :limit => sampling_cursor_limit(n_terms), + :flags => TableCursorFlags::PREFIX, + } + TableCursor.open(lexicon, options) do |cursor| + if is_table_search + size = 1 + else + size = index_column.estimate_size(:lexicon_cursor => cursor) + end + size += 1 if cursor.next != ID::NIL + size + end + end + + def estimate_call(index_column) + procedure = @data.args[0] + arguments = @data.args[1..-1].collect do |arg| + if arg.is_a?(::Groonga::Object) + ExpressionTree::Variable.new(arg) + else + ExpressionTree::Constant.new(arg) + end + end + node = ExpressionTree::FunctionCall.new(procedure, arguments) + node.estimate_size(@table) + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_search_index.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_search_index.rb new file mode 100644 index 00000000..a2818160 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/scan_info_search_index.rb @@ -0,0 +1,9 @@ +module Groonga + class ScanInfoSearchIndex < Struct.new(:index_column, + :section_id, + :weight, + :scorer, + :scorer_args_expr, + :scorer_args_expr_offset) + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am new file mode 100644 index 00000000..9a9e2bae --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/sources.am @@ -0,0 +1,37 @@ +RUBY_SCRIPT_FILES = \ + accessor.rb \ + backtrace_entry.rb \ + command.rb \ + command_input.rb \ + command_line_parser.rb \ + context.rb \ + database.rb \ + error.rb \ + eval_context.rb \ + expression.rb \ + expression_rewriter.rb \ + expression_rewriters.rb \ + expression_size_estimator.rb \ + expression_tree.rb \ + expression_tree_builder.rb \ + fixed_size_column.rb \ + id.rb \ + index_column.rb \ + index_cursor.rb \ + index_info.rb \ + logger.rb \ + object.rb \ + operator.rb \ + plugin_loader.rb \ + query_logger.rb \ + record.rb \ + require.rb \ + scan_info.rb \ + scan_info_builder.rb \ + scan_info_data.rb \ + scan_info_data_size_estimator.rb \ + scan_info_search_index.rb \ + table.rb \ + table_cursor.rb \ + variable_size_column.rb \ + writer.rb diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/table.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table.rb new file mode 100644 index 00000000..75c91894 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table.rb @@ -0,0 +1,144 @@ +module Groonga + class Table + include Enumerable + include Indexable + + def columns + context = Context.instance + column_ids.collect do |id| + context[id] + end + end + + def each + flags = + TableCursorFlags::ASCENDING | + TableCursorFlags::BY_ID + TableCursor.open(self, :flags => flags) do |cursor| + cursor.each do |id| + yield(id) + end + end + end + + def sort(keys, options={}) + offset = options[:offset] || 0 + limit = options[:limit] || -1 + ensure_sort_keys(keys) do |sort_keys| + sorted = Array.create("", self) + begin + sort_raw(sort_keys, offset, limit, sorted) + rescue Exception + sorted.close + raise + end + sorted + end + end + + def group(keys, result) + ensure_sort_keys(keys) do |sort_keys| + group_raw(sort_keys, result) + end + end + + def apply_window_function(output_column, + window_function_call, + options={}) + ensure_sort_keys_accept_nil(options[:sort_keys]) do |sort_keys| + ensure_sort_keys_accept_nil(options[:group_keys]) do |group_keys| + window_definition = WindowDefinition.new + begin + window_definition.sort_keys = sort_keys + window_definition.group_keys = group_keys + apply_window_function_raw(output_column, + window_definition, + window_function_call) + ensure + window_definition.close + end + end + end + end + + private + def ensure_sort_keys_accept_nil(keys, &block) + return yield(nil) if keys.nil? + + ensure_sort_keys(keys, &block) + end + + def ensure_sort_keys(keys) + if keys.is_a?(::Array) and keys.all? {|key| key.is_a?(TableSortKey)} + return yield(keys) + end + + converted_keys = [] + + begin + keys = [keys] unless keys.is_a?(::Array) + sort_keys = keys.collect do |key| + ensure_sort_key(key, converted_keys) + end + yield(sort_keys) + ensure + converted_keys.each do |converted_key| + converted_key.close + end + end + end + + def ensure_sort_key(key, converted_keys) + return key if key.is_a?(TableSortKey) + + sort_key = TableSortKey.new + converted_keys << sort_key + + key_name = nil + order = :ascending + offset = 0 + if key.is_a?(::Hash) + key_name = key[:key] + order = key[:order] || order + offset = key[:offset] || offset + else + key_name = key + end + + case key_name + when String + # Do nothing + when Symbol + key_name = key_name.to_s + else + message = "sort key name must be String or Symbol: " + + "#{key_name.inspect}: #{key.inspect}" + raise ArgumentError, message + end + + if key_name.start_with?("-") + key_name[0] = "" + order = :descending + elsif key_name.start_with?("+") + key_name[0] = "" + end + + key = find_column(key_name) + if key.nil? + table_name = name || "(temporary)" + message = "unknown key: #{key_name.inspect}: " + message << "#{table_name}(#{size})" + raise ArgumentError, message + end + + sort_key.key = key + if order == :ascending + sort_key.flags = Groonga::TableSortFlags::ASCENDING + else + sort_key.flags = Groonga::TableSortFlags::DESCENDING + end + sort_key.offset = offset + sort_key + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb new file mode 100644 index 00000000..45949b71 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/table_cursor.rb @@ -0,0 +1,28 @@ +module Groonga + class TableCursor + include Enumerable + + class << self + def open(*arguments) + cursor = open_raw(*arguments) + if block_given? + begin + yield(cursor) + ensure + cursor.close + end + else + cursor + end + end + end + + def each + loop do + id = self.next + return if id == Groonga::ID::NIL + yield(id) + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/variable_size_column.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/variable_size_column.rb new file mode 100644 index 00000000..3d75502f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/variable_size_column.rb @@ -0,0 +1,5 @@ +module Groonga + class VariableSizeColumn + include Indexable + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb b/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb new file mode 100644 index 00000000..de2bc261 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/scripts/writer.rb @@ -0,0 +1,21 @@ +module Groonga + class Writer + def array(name, n_elements) + open_array(name, n_elements) + begin + yield + ensure + close_array + end + end + + def map(name, n_elements) + open_map(name, n_elements) + begin + yield + ensure + close_map + end + end + end +end diff --git a/storage/mroonga/vendor/groonga/lib/mrb/sources.am b/storage/mroonga/vendor/groonga/lib/mrb/sources.am new file mode 100644 index 00000000..9db16737 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/mrb/sources.am @@ -0,0 +1,93 @@ +libgrnmrb_la_SOURCES = \ + mrb_accessor.c \ + mrb_accessor.h \ + mrb_array.c \ + mrb_array.h \ + mrb_bulk.c \ + mrb_bulk.h \ + mrb_cache.c \ + mrb_cache.h \ + mrb_column.c \ + mrb_column.h \ + mrb_command.c \ + mrb_command.h \ + mrb_command_input.c \ + mrb_command_input.h \ + mrb_command_version.c \ + mrb_command_version.h \ + mrb_config.c \ + mrb_config.h \ + mrb_content_type.c \ + mrb_content_type.h \ + mrb_converter.c \ + mrb_converter.h \ + mrb_ctx.c \ + mrb_ctx.h \ + mrb_database.c \ + mrb_database.h \ + mrb_double_array_trie.c \ + mrb_double_array_trie.h \ + mrb_error.c \ + mrb_error.h \ + mrb_eval_context.c \ + mrb_eval_context.h \ + mrb_expr.c \ + mrb_expr.h \ + mrb_fixed_size_column.c \ + mrb_fixed_size_column.h \ + mrb_hash_table.c \ + mrb_hash_table.h \ + mrb_id.c \ + mrb_id.h \ + mrb_indexable.c \ + mrb_indexable.h \ + mrb_index_column.c \ + mrb_index_column.h \ + mrb_index_cursor.c \ + mrb_index_cursor.h \ + mrb_logger.c \ + mrb_logger.h \ + mrb_object.c \ + mrb_object.h \ + mrb_object_flags.c \ + mrb_object_flags.h \ + mrb_operator.c \ + mrb_operator.h \ + mrb_options.c \ + mrb_options.h \ + mrb_patricia_trie.c \ + mrb_patricia_trie.h \ + mrb_pointer.c \ + mrb_pointer.h \ + mrb_procedure.c \ + mrb_procedure.h \ + mrb_query_logger.c \ + mrb_query_logger.h \ + mrb_record.c \ + mrb_record.h \ + mrb_table.c \ + mrb_table.h \ + mrb_table_cursor.c \ + mrb_table_cursor.h \ + mrb_table_cursor_flags.c \ + mrb_table_cursor_flags.h \ + mrb_table_group_flags.c \ + mrb_table_group_flags.h \ + mrb_table_group_result.c \ + mrb_table_group_result.h \ + mrb_table_sort_flags.c \ + mrb_table_sort_flags.h \ + mrb_table_sort_key.c \ + mrb_table_sort_key.h \ + mrb_thread.c \ + mrb_thread.h \ + mrb_type.c \ + mrb_type.h \ + mrb_variable_size_column.c \ + mrb_variable_size_column.h \ + mrb_void.c \ + mrb_void.h \ + mrb_window_definition.c \ + mrb_window_definition.h \ + mrb_writer.c \ + mrb_writer.h diff --git a/storage/mroonga/vendor/groonga/lib/nfkc-custom-rules.txt b/storage/mroonga/vendor/groonga/lib/nfkc-custom-rules.txt new file mode 100644 index 00000000..496751a5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/nfkc-custom-rules.txt @@ -0,0 +1 @@ +〜 ~ diff --git a/storage/mroonga/vendor/groonga/lib/nfkc.c b/storage/mroonga/vendor/groonga/lib/nfkc.c new file mode 100644 index 00000000..e83fe610 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/nfkc.c @@ -0,0 +1,45 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_nfkc.h" +#include + +#ifdef GRN_WITH_NFKC + +grn_char_type +grn_nfkc_char_type(const unsigned char *utf8) +{ + return grn_nfkc50_char_type(utf8); +} + +const char * +grn_nfkc_decompose(const unsigned char *utf8) +{ + return grn_nfkc50_decompose(utf8); +} + +const char * +grn_nfkc_compose(const unsigned char *prefix_utf8, + const unsigned char *suffix_utf8) +{ + return grn_nfkc50_compose(prefix_utf8, suffix_utf8); +} + +#endif /* GRN_WITH_NFKC */ + diff --git a/storage/mroonga/vendor/groonga/lib/nfkc.rb b/storage/mroonga/vendor/groonga/lib/nfkc.rb new file mode 100755 index 00000000..0c0e7fe7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/nfkc.rb @@ -0,0 +1,897 @@ +#!/usr/bin/env ruby +# -*- coding: utf-8 -*- +# +# Copyright(C) 2010-2016 Brazil +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License version 2.1 as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA + +CUSTOM_RULE_PATH = 'nfkc-custom-rules.txt' + +class SwitchGenerator + def initialize(unicode_version, output) + @unicode_version = unicode_version + @output = output + end + + def generate(bc, decompose_map, compose_map) + STDERR.puts('generating char type code..') + generate_blockcode_char_type(bc) + STDERR.puts('generating decompose code..') + generate_decompose(decompose_map) + STDERR.puts('generating compose code..') + generate_compose(compose_map) + end + + private + def generate_blockcode_char_type(bc) + @output.puts(<<-HEADER) + +grn_char_type +grn_nfkc#{@unicode_version}_char_type(const unsigned char *str) +{ + HEADER + + @lv = 0 + gen_bc(bc, 0) + + @output.puts(<<-FOOTER) + return -1; +} + FOOTER + end + + def gen_bc(hash, level) + bl = ' ' * (level * 2) + h2 = {} + hash.each{|key,val| + key = key.dup + key.force_encoding("ASCII-8BIT") + head = key.bytes[0] + rest = key[1..-1] + if h2[head] + h2[head][rest] = val + else + h2[head] = {rest => val} + end + } + if h2.size < 3 + h2.keys.sort.each{|k| + if (0x80 < k) + @output.printf("#{bl}if (str[#{level}] < 0x%02X) { return #{@lv}; }\n", k) + end + h = h2[k] + if h.keys.join =~ /^\x80*$/n + @lv, = h.values + else + @output.printf("#{bl}if (str[#{level}] == 0x%02X) {\n", k) + gen_bc(h, level + 1) + @output.puts bl + '}' + end + } + @output.puts bl + "return #{@lv};" + else + @output.puts bl + "switch (str[#{level}]) {" + lk = 0x80 + br = true + h2.keys.sort.each{|k| + if (lk < k) + for j in lk..k-1 + @output.printf("#{bl}case 0x%02X :\n", j) + end + br = false + end + unless br + @output.puts bl + " return #{@lv};" + @output.puts bl + ' break;' + end + h = h2[k] + @output.printf("#{bl}case 0x%02X :\n", k) + if h.keys.join =~ /^\x80*$/n + @lv, = h.values + br = false + else + gen_bc(h, level + 1) + @output.puts bl + ' break;' + br = true + end + lk = k + 1 + } + @output.puts bl + 'default :' + @output.puts bl + " return #{@lv};" + @output.puts bl + ' break;' + @output.puts bl + '}' + end + end + + def generate_decompose(hash) + @output.puts(<<-HEADER) + +const char * +grn_nfkc#{@unicode_version}_decompose(const unsigned char *str) +{ + HEADER + + gen_decompose(hash, 0) + + @output.puts(<<-FOOTER) + return 0; +} + FOOTER + end + + def gen_decompose(hash, level) + bl = ' ' * ((level + 0) * 2) + if hash[''] + dst = '' + hash[''].each_byte{|b| dst << format('\x%02X', b)} + @output.puts "#{bl}return \"#{dst}\";" + hash.delete('') + end + return if hash.empty? + h2 = {} + hash.each{|key,val| + key = key.dup + key.force_encoding("ASCII-8BIT") + head = key.bytes[0] + rest = key[1..-1] + if h2[head] + h2[head][rest] = val + else + h2[head] = {rest => val} + end + } + if h2.size == 1 + h2.each{|key,val| + @output.printf("#{bl}if (str[#{level}] == 0x%02X) {\n", key) + gen_decompose(val, level + 1) + @output.puts bl + '}' + } + else + @output.puts "#{bl}switch (str[#{level}]) {" + h2.keys.sort.each{|k| + @output.printf("#{bl}case 0x%02X :\n", k) + gen_decompose(h2[k], level + 1) + @output.puts("#{bl} break;") + } + @output.puts bl + '}' + end + end + + def generate_compose(compose_map) + @output.puts(<<-HEADER) + +const char * +grn_nfkc#{@unicode_version}_compose(const unsigned char *prefix, const unsigned char *suffix) +{ + HEADER + suffix = {} + compose_map.each{|src,dst| + chars = src.chars + if chars.size != 2 + STDERR.puts "caution: more than two chars in pattern #{chars.join('|')}" + end + s = chars.pop + if suffix[s] + suffix[s][chars.join] = dst + else + suffix[s] = {chars.join=>dst} + end + } + gen_compose_sub(suffix, 0) + @output.puts(<<-FOOTER) + return 0; +} + FOOTER + end + + def gen_compose_sub2(hash, level, indent) + bl = ' ' * ((level + indent + 0) * 2) + if hash[''] + @output.print "#{bl}return \"" + hash[''].each_byte{|b| @output.printf('\x%02X', b)} + @output.puts "\";" + hash.delete('') + end + return if hash.empty? + + h2 = {} + hash.each{|key,val| + key = key.dup + key.force_encoding("ASCII-8BIT") + head = key.bytes[0] + rest = key[1..-1] + if h2[head] + h2[head][rest] = val + else + h2[head] = {rest => val} + end + } + + if h2.size == 1 + h2.each{|key,val| + @output.printf("#{bl}if (prefix[#{level}] == 0x%02X) {\n", key) + gen_compose_sub2(val, level + 1, indent) + @output.puts bl + '}' + } + else + @output.puts "#{bl}switch (prefix[#{level}]) {" + h2.keys.sort.each{|k| + @output.printf("#{bl}case 0x%02X :\n", k) + gen_compose_sub2(h2[k], level + 1, indent) + @output.puts("#{bl} break;") + } + @output.puts bl + '}' + end + end + + def gen_compose_sub(hash, level) + bl = ' ' * ((level + 0) * 2) + if hash[''] + gen_compose_sub2(hash[''], 0, level) + hash.delete('') + end + return if hash.empty? + h2 = {} + hash.each{|key,val| + key = key.dup + key.force_encoding("ASCII-8BIT") + head = key.bytes[0] + rest = key[1..-1] + if h2[head] + h2[head][rest] = val + else + h2[head] = {rest => val} + end + } + if h2.size == 1 + h2.each{|key,val| + @output.printf("#{bl}if (suffix[#{level}] == 0x%02X) {\n", key) + gen_compose_sub(val, level + 1) + @output.puts bl + '}' + } + else + @output.puts "#{bl}switch (suffix[#{level}]) {" + h2.keys.sort.each{|k| + @output.printf("#{bl}case 0x%02X :\n", k) + gen_compose_sub(h2[k], level + 1) + @output.puts("#{bl} break;") + } + @output.puts bl + '}' + end + end +end + +class TableGenerator < SwitchGenerator + private + def name_prefix + "grn_nfkc#{@unicode_version}_" + end + + def table_name(type, common_bytes) + suffix = common_bytes.collect {|byte| "%02x" % byte}.join("") + "#{name_prefix}#{type}_table_#{suffix}" + end + + def function_name(type) + "#{name_prefix}#{type}" + end + + def generate_char_convert_tables(type, return_type, byte_size_groups) + if return_type.end_with?("*") + space = "" + else + space = " " + end + byte_size_groups.keys.sort.each do |common_bytes| + chars = byte_size_groups[common_bytes] + lines = [] + all_values = [] + last_bytes = chars.collect {|char| char.bytes.last} + last_bytes.min.step(last_bytes.max).each_slice(8) do |slice| + values = slice.collect do |last_byte| + char = (common_bytes + [last_byte]).pack("c*") + char.force_encoding("UTF-8") + yield(char) + end + all_values.concat(values) + lines << (" " + values.join(", ")) + end + + next if all_values.uniq.size == 1 + + @output.puts(<<-TABLE_HEADER) + +static #{return_type}#{space}#{table_name(type, common_bytes)}[] = { + TABLE_HEADER + @output.puts(lines.join(",\n")) + @output.puts(<<-TABLE_FOOTER) +}; + TABLE_FOOTER + end + end + + def generate_char_convert_function(type, + argument_list, + char_variable, + default, + return_type, + byte_size_groups, + options={}) + modifier = options[:internal] ? "static inline " : "" + @output.puts(<<-HEADER) + +#{modifier}#{return_type} +#{function_name(type)}(#{argument_list}) +{ + HEADER + + prev_common_bytes = [] + prev_n_common_bytes = 0 + first_group = true + byte_size_groups.keys.sort.each do |common_bytes| + chars = byte_size_groups[common_bytes] + chars_bytes = chars.collect(&:bytes).sort + min = chars_bytes.first.last + max = chars_bytes.last.last + n_common_bytes = 0 + if common_bytes.empty? + indent = " " + yield(:no_common_bytes, indent, chars, chars_bytes) + else + if first_group + @output.puts(<<-BODY) + { + BODY + end + + found_different_byte = false + common_bytes.each_with_index do |common_byte, i| + unless found_different_byte + if prev_common_bytes[i] == common_byte + n_common_bytes += 1 + next + end + found_different_byte = true + end + indent = " " * i + # p [i, prev_common_bytes.collect{|x| "%#04x" % x}, common_bytes.collect{|x| "%#04x" % x}, "%#04x" % common_byte, n_common_bytes, prev_n_common_bytes] + # TODO: The following code may be able to be simplified. + if prev_common_bytes[i].nil? + # p nil + @output.puts(<<-BODY) + #{indent}switch (#{char_variable}[#{i}]) { + BODY + elsif i < prev_n_common_bytes + # p :prev + @output.puts(<<-BODY) + #{indent} default : + #{indent} break; + #{indent} } + #{indent} break; + BODY + elsif n_common_bytes < prev_n_common_bytes + # p :common_prev + @output.puts(<<-BODY) + #{indent}switch (#{char_variable}[#{i}]) { + BODY + else + # p :else + prev_common_bytes.size.downto(common_bytes.size + 1) do |j| + sub_indent = " " * (j - 1) + @output.puts(<<-BODY) + #{indent}#{sub_indent}default : + #{indent}#{sub_indent} break; + #{indent}#{sub_indent}} + #{indent}#{sub_indent}break; + BODY + end + end + @output.puts(<<-BODY) + #{indent}case #{"%#04x" % common_byte} : + BODY + end + + n = chars_bytes.first.size - 1 + indent = " " + (" " * common_bytes.size) + yield(:have_common_bytes, indent, chars, chars_bytes, n, common_bytes) + end + + prev_common_bytes = common_bytes + prev_n_common_bytes = n_common_bytes + first_group = false + end + + # p [prev_common_bytes.collect{|x| "%#04x" % x}, prev_n_common_bytes] + + (prev_common_bytes.size - 1).step(0, -1) do |i| + indent = " " * i + @output.puts(<<-BODY) + #{indent}default : + #{indent} break; + #{indent}} + BODY + if i > 0 + @output.puts(<<-BODY) + #{indent}break; + BODY + end + end + + @output.puts(<<-FOOTER) + } + + return #{default}; +} + FOOTER + end + + def generate_char_converter(type, + function_type, + char_map, + default, + return_type, + options={}, + &converter) + byte_size_groups = char_map.keys.group_by do |from| + bytes = from.bytes + bytes[0..-2] + end + + generate_char_convert_tables(type, + return_type, + byte_size_groups, + &converter) + + char_variable = "utf8" + generate_char_convert_function(function_type, + "const unsigned char *#{char_variable}", + char_variable, + default, + return_type, + byte_size_groups, + options) do |state, *args| + case state + when :no_common_bytes + indent, chars, chars_bytes = args + if chars.size == 1 + char = chars[0] + char_byte = chars_bytes.first.first + value = yield(char) + @output.puts(<<-BODY) +#{indent}if (#{char_variable}[0] < 0x80) { +#{indent} if (#{char_variable}[0] == #{"%#04x" % char_byte}) { +#{indent} return #{value}; +#{indent} } else { +#{indent} return #{default}; +#{indent} } +#{indent}} else { + BODY + else + min = chars_bytes.first.first + max = chars_bytes.last.first + @output.puts(<<-BODY) +#{indent}if (#{char_variable}[0] < 0x80) { +#{indent} if (#{char_variable}[0] >= #{"%#04x" % min} && +#{indent} #{char_variable}[0] <= #{"%#04x" % max}) { +#{indent} return #{table_name(type, [])}[#{char_variable}[0] - #{"%#04x" % min}]; +#{indent} } else { +#{indent} return #{default}; +#{indent} } +#{indent}} else { + BODY + end + when :have_common_bytes + indent, chars, chars_bytes, n, common_bytes = args + if chars.size == 1 + char = chars[0] + char_byte = chars_bytes.first.last + value = yield(char) + @output.puts(<<-BODY) +#{indent}if (#{char_variable}[#{n}] == #{"%#04x" % char_byte}) { +#{indent} return #{value}; +#{indent}} +#{indent}break; + BODY + else + sorted_chars = chars.sort + min = chars_bytes.first.last + max = chars_bytes.last.last + all_values = (min..max).collect do |last_byte| + char = (common_bytes + [last_byte]).pack("c*") + char.force_encoding("UTF-8") + yield(char) + end + if all_values.uniq.size == 1 + value = all_values.first + else + value = "#{table_name(type, common_bytes)}[#{char_variable}[#{n}] - #{"%#04x" % min}]" + end + last_n_bits_for_char_in_utf8 = 6 + max_n_chars_in_byte = 2 ** last_n_bits_for_char_in_utf8 + if all_values.size == max_n_chars_in_byte + @output.puts(<<-BODY) +#{indent}return #{value}; + BODY + else + @output.puts(<<-BODY) +#{indent}if (#{char_variable}[#{n}] >= #{"%#04x" % min} && +#{indent} #{char_variable}[#{n}] <= #{"%#04x" % max}) { +#{indent} return #{value}; +#{indent}} +#{indent}break; + BODY + end + end + end + end + end + + def generate_blockcode_char_type(block_codes) + default = "GRN_CHAR_OTHERS" + + char_types = {} + current_type = default + prev_char = nil + block_codes.keys.sort.each do |char| + type = block_codes[char] + if current_type != default + prev_code_point = prev_char.codepoints[0] + code_point = char.codepoints[0] + (prev_code_point...code_point).each do |target_code_point| + target_char = [target_code_point].pack("U*") + char_types[target_char] = current_type + end + end + current_type = type + prev_char = char + end + unless current_type == default + raise "TODO: Consider the max unicode character" + max_unicode_char = "\u{10ffff}" + (prev_char..max_unicode_char).each do |target_char| + char_types[target_char] = current_type + end + end + + generate_char_converter("char_type", + "char_type", + char_types, + default, + "grn_char_type") do |char| + char_types[char] || default + end + end + + def generate_decompose(decompose_map) + default = "NULL" + generate_char_converter("decompose", + "decompose", + decompose_map, + default, + "const char *") do |from| + to = decompose_map[from] + if to + escaped_value = to.bytes.collect {|char| "\\x%02x" % char}.join("") + "\"#{escaped_value}\"" + else + default + end + end + end + + def generate_compose(compose_map) + # require "pp" + # p compose_map.size + # pp compose_map.keys.group_by {|x| x.chars[1]}.size + # pp compose_map.keys.group_by {|x| x.chars[1]}.collect {|k, vs| [k, k.codepoints, vs.size, vs.group_by {|x| x.chars[0].bytesize}.collect {|k2, vs2| [k2, vs2.size]}]} + # pp compose_map.keys.group_by {|x| x.chars[0].bytesize}.collect {|k, vs| [k, vs.size]} + # pp compose_map + + suffix_char_map = {} + compose_map.each do |source, destination| + chars = source.chars + if chars.size != 2 + STDERR.puts "caution: more than two chars in pattern #{chars.join('|')}" + return + end + prefix, suffix = chars + suffix_char_map[suffix] ||= {} + suffix_char_map[suffix][prefix] = destination + end + + suffix_char_map.each do |suffix, prefix_char_map| + suffix_bytes = suffix.bytes.collect {|byte| "%02x" % byte}.join("") + default = "NULL" + generate_char_converter("compose_prefix_#{suffix_bytes}", + "compose_prefix_#{suffix_bytes}", + prefix_char_map, + default, + "const char *", + :internal => true) do |prefix| + to = prefix_char_map[prefix] + if to + escaped_value = to.bytes.collect {|char| "\\x%02x" % char}.join("") + "\"#{escaped_value}\"" + else + default + end + end + end + + + char_variable = "suffix_utf8" + argument_list = + "const unsigned char *prefix_utf8, " + + "const unsigned char *#{char_variable}" + default = "NULL" + byte_size_groups = suffix_char_map.keys.group_by do |from| + bytes = from.bytes + bytes[0..-2] + end + generate_char_convert_function("compose", + argument_list, + char_variable, + default, + "const char *", + byte_size_groups) do |type, *args| + case type + when :no_common_bytes + indent, chars, chars_bytes = args + @output.puts(<<-BODY) +#{indent}switch (#{char_variable}[0]) { + BODY + chars.each do |char| + suffix_bytes = char.bytes.collect {|byte| "%02x" % byte}.join("") + type = "compose_prefix_#{suffix_bytes}" + @output.puts(<<-BODY) +#{indent}case #{"%#04x" % char.bytes.last} : +#{indent} return #{function_name(type)}(prefix_utf8); + BODY + end + @output.puts(<<-BODY) +#{indent}default : +#{indent} return #{default}; +#{indent}} +#{indent}break; + BODY + when :have_common_bytes + indent, chars, chars_bytes, n, common_bytes = args + @output.puts(<<-BODY) +#{indent}switch (#{char_variable}[#{n}]) { + BODY + chars.each do |char| + suffix_bytes = char.bytes.collect {|byte| "%02x" % byte}.join("") + type = "compose_prefix_#{suffix_bytes}" + @output.puts(<<-BODY) +#{indent}case #{"%#04x" % char.bytes.last} : +#{indent} return #{function_name(type)}(prefix_utf8); + BODY + end + @output.puts(<<-BODY) +#{indent}default : +#{indent} return #{default}; +#{indent}} +#{indent}break; + BODY + end + end + end + + def to_bytes_map(char_map) + bytes_map = {} + char_map.each_key do |from| + parent = bytes_map + from.bytes[0..-2].each do |byte| + parent[byte] ||= {} + parent = parent[byte] + end + parent[from.bytes.last] = char_map[from] + end + bytes_map + end +end + +def create_bc(option) + bc = {} + open("|./icudump --#{option}").each{|l| + src,_,code = l.chomp.split("\t") + str = src.split(':').collect(&:hex).pack("c*") + str.force_encoding("UTF-8") + bc[str] = code + } + bc +end + +def ccpush(hash, src, dst) + head = src.shift + hash[head] = {} unless hash[head] + if head + ccpush(hash[head], src, dst) + else + hash[head] = dst + end +end + +def subst(hash, str) + cand = nil + src = str.chars + for i in 0..src.size-1 + h = hash + for j in i..src.size-1 + head = src[j] + h = h[head] + break unless h + if h[nil] + cand = src[0,i].join("") + h[nil] + src[j + 1..-1].join("") + end + end + return cand if cand + end + return str +end + +def map_entry(decompose, cc, src, dst) + dst.downcase! unless $case_sensitive + loop { + dst2 = subst(cc, dst) + break if dst2 == dst + dst = dst2 + } + unless $keep_space + dst = $1 if dst =~ /^ +([^ ].*)$/ + end + decompose[src] = dst if src != dst +end + +def create_decompose_map() + cc = {} + open('|./icudump --cc').each{|l| + _,src,dst = l.chomp.split("\t") + if cc[src] + STDERR.puts "caution: ambiguous mapping #{src}|#{cc[src]}|#{dst}" if cc[src] != dst + end + ccpush(cc, src.chars, dst) + } + decompose_map = {} + open('|./icudump --nfkd').each{|l| + n,src,dst = l.chomp.split("\t") + map_entry(decompose_map, cc, src, dst) + } + if File.readable?(CUSTOM_RULE_PATH) + open(CUSTOM_RULE_PATH).each{|l| + src,dst = l.chomp.split("\t") + map_entry(decompose_map, cc, src, dst) + } + end + unless $case_sensitive + for c in 'A'..'Z' + decompose_map[c] = c.downcase + end + end + return decompose_map +end + +def create_compose_map(decompose_map) + cc = {} + open('|./icudump --cc').each{|l| + _,src,dst = l.chomp.split("\t") + src = src.chars.collect{|c| decompose_map[c] || c}.join + dst = decompose_map[dst] || dst + if cc[src] && cc[src] != dst + STDERR.puts("caution: inconsitent mapping '#{src}' => '#{cc[src]}'|'#{dst}'") + end + cc[src] = dst if src != dst + } + loop { + noccur = 0 + cc2 = {} + cc.each {|src,dst| + src2 = src + chars = src.chars + l = chars.size - 1 + for i in 0..l + for j in i..l + next if i == 0 && j == l + str = chars[i..j].join + if decompose_map[str] + STDERR.printf("caution: recursive mapping '%s'=>'%s'\n", + str, decompose_map[str]) + end + if cc[str] + src2 = (i > 0 ? chars[0..i-1].join : '') + cc[str] + (j < l ? chars[j+1..l].join : '') + noccur += 1 + end + end + end + cc2[src2] = dst if src2 != dst + } + cc = cc2 + STDERR.puts("substituted #{noccur} patterns.") + break if noccur == 0 + STDERR.puts('try again..') + } + return cc +end + +######## main ####### + +generator_class = SwitchGenerator +ARGV.each{|arg| + case arg + when /-*c/i + $case_sensitive = true + when /-*s/i + $keep_space = true + when "--impl=switch" + generator_class = SwitchGenerator + when "--impl=table" + generator_class = TableGenerator + end +} + +STDERR.puts('compiling icudump') +system('cc -Wall -O3 -o icudump -I/tmp/local/include -L/tmp/local/lib icudump.c -licuuc -licui18n') + +STDERR.puts('getting Unicode version') +unicode_version = `./icudump --version`.strip.gsub(".", "") + +STDERR.puts('creating bc..') +bc = create_bc("gc") + +STDERR.puts('creating decompose map..') +decompose_map = create_decompose_map() + +STDERR.puts('creating compose map..') +compose_map = create_compose_map(decompose_map) + +File.open("nfkc#{unicode_version}.c", "w") do |output| + output.puts(<<-HEADER) +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +/* + Don't edit this file by hand. it generated automatically by nfkc.rb. +*/ + +#include "grn.h" +#include "grn_nfkc.h" +#include + +#ifdef GRN_WITH_NFKC + HEADER + + generator = generator_class.new(unicode_version, output) + generator.generate(bc, decompose_map, compose_map) + + output.puts(<<-FOOTER) + +#endif /* GRN_WITH_NFKC */ + + FOOTER +end diff --git a/storage/mroonga/vendor/groonga/lib/nfkc50.c b/storage/mroonga/vendor/groonga/lib/nfkc50.c new file mode 100644 index 00000000..f734e832 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/nfkc50.c @@ -0,0 +1,77784 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +/* + Don't edit this file by hand. it generated automatically by nfkc.rb. +*/ + +#include "grn.h" +#include "grn_nfkc.h" +#include + +#ifdef GRN_WITH_NFKC + +static grn_char_type grn_nfkc50_char_type_table_[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_c2[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_DIGIT, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_c3[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_cb[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_cd[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_ce[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_cf[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_d2[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_d4[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_d5[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_d6[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_d7[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_d8[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_d9[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_db[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_dc[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_de[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_df[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0a4[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0a5[] = { + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0a6[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0a7[] = { + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e0a8[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0a9[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0aa[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0ab[] = { + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e0ac[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0ad[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0ae[] = { + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0af[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b0[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b1[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b2[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b3[] = { + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b4[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b5[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b6[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b7[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b8[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e0b9[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e0ba[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0bb[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0bc[] = { + GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e0bd[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e0be[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e0bf[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e180[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e181[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e183[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e185[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e186[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e189[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e18a[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e18b[] = { + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e18c[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e18d[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_e18e[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e199[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e19a[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e19b[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_e19c[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e19d[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e19f[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_e1a0[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e1a5[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e1a7[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e1a8[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e1ad[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e1ba[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e1bc[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e1bd[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e1be[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e1bf[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e280[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e281[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e282[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e284[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e285[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_e286[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e291[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_e292[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e293[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_e29a[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e29c[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e29d[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_e29e[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e29f[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e2ac[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e2b0[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e2b1[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e2b3[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e2b4[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e2b5[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e2b6[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e2b7[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_e2b8[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e2bf[] = { + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_e382[] = { + GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, + GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, + GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, + GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, GRN_CHAR_HIRAGANA, + GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, + GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, + GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, + GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA +}; + +static grn_char_type grn_nfkc50_char_type_table_e387[] = { + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, GRN_CHAR_KANJI, + GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, + GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA, GRN_CHAR_KATAKANA +}; + +static grn_char_type grn_nfkc50_char_type_table_ea9c[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_eaa0[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_eaa1[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_efac[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_efad[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_efb4[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_efb6[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_efb7[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_efb8[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_efb9[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_efbc[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_efbd[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_efbf[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f09080[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09081[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09084[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f09085[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f09086[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_f0908c[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f0908d[] = { + GRN_CHAR_ALPHA, GRN_CHAR_DIGIT, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_f0908e[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f0908f[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_SYMBOL, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_f09092[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_f090a0[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f090a4[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f090a8[] = { + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f090a9[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f09291[] = { + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d84[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d85[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d86[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d89[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_SYMBOL +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d8d[] = { + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, + GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_SYMBOL, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d91[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d92[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d93[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d94[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d95[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, + GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d9a[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d9b[] = { + GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d9c[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d9d[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d9e[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA +}; + +static grn_char_type grn_nfkc50_char_type_table_f09d9f[] = { + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_SYMBOL, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, + GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_ALPHA, GRN_CHAR_OTHERS, GRN_CHAR_OTHERS, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, + GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT, GRN_CHAR_DIGIT +}; + +grn_char_type +grn_nfkc50_char_type(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x21 && + utf8[0] <= 0x7e) { + return grn_nfkc50_char_type_table_[utf8[0] - 0x21]; + } else { + return GRN_CHAR_OTHERS; + } + } else { + switch (utf8[0]) { + case 0xc2 : + if (utf8[1] >= 0xa1 && + utf8[1] <= 0xbf) { + return grn_nfkc50_char_type_table_c2[utf8[1] - 0xa1]; + } + break; + case 0xc3 : + return grn_nfkc50_char_type_table_c3[utf8[1] - 0x80]; + case 0xc4 : + return GRN_CHAR_ALPHA; + case 0xc5 : + return GRN_CHAR_ALPHA; + case 0xc6 : + return GRN_CHAR_ALPHA; + case 0xc7 : + return GRN_CHAR_ALPHA; + case 0xc8 : + return GRN_CHAR_ALPHA; + case 0xc9 : + return GRN_CHAR_ALPHA; + case 0xca : + return GRN_CHAR_ALPHA; + case 0xcb : + return grn_nfkc50_char_type_table_cb[utf8[1] - 0x80]; + case 0xcd : + if (utf8[1] >= 0xb4 && + utf8[1] <= 0xbe) { + return grn_nfkc50_char_type_table_cd[utf8[1] - 0xb4]; + } + break; + case 0xce : + if (utf8[1] >= 0x84 && + utf8[1] <= 0xbf) { + return grn_nfkc50_char_type_table_ce[utf8[1] - 0x84]; + } + break; + case 0xcf : + return grn_nfkc50_char_type_table_cf[utf8[1] - 0x80]; + case 0xd0 : + return GRN_CHAR_ALPHA; + case 0xd1 : + return GRN_CHAR_ALPHA; + case 0xd2 : + return grn_nfkc50_char_type_table_d2[utf8[1] - 0x80]; + case 0xd3 : + return GRN_CHAR_ALPHA; + case 0xd4 : + return grn_nfkc50_char_type_table_d4[utf8[1] - 0x80]; + case 0xd5 : + return grn_nfkc50_char_type_table_d5[utf8[1] - 0x80]; + case 0xd6 : + if (utf8[1] >= 0x80 && + utf8[1] <= 0xbe) { + return grn_nfkc50_char_type_table_d6[utf8[1] - 0x80]; + } + break; + case 0xd7 : + if (utf8[1] >= 0x80 && + utf8[1] <= 0xb4) { + return grn_nfkc50_char_type_table_d7[utf8[1] - 0x80]; + } + break; + case 0xd8 : + if (utf8[1] >= 0x8b && + utf8[1] <= 0xba) { + return grn_nfkc50_char_type_table_d8[utf8[1] - 0x8b]; + } + break; + case 0xd9 : + return grn_nfkc50_char_type_table_d9[utf8[1] - 0x80]; + case 0xda : + return GRN_CHAR_ALPHA; + case 0xdb : + return grn_nfkc50_char_type_table_db[utf8[1] - 0x80]; + case 0xdc : + if (utf8[1] >= 0x80 && + utf8[1] <= 0xaf) { + return grn_nfkc50_char_type_table_dc[utf8[1] - 0x80]; + } + break; + case 0xdd : + if (utf8[1] >= 0x8d && + utf8[1] <= 0xad) { + return GRN_CHAR_ALPHA; + } + break; + case 0xde : + if (utf8[1] >= 0x80 && + utf8[1] <= 0xb1) { + return grn_nfkc50_char_type_table_de[utf8[1] - 0x80]; + } + break; + case 0xdf : + if (utf8[1] >= 0x80 && + utf8[1] <= 0xba) { + return grn_nfkc50_char_type_table_df[utf8[1] - 0x80]; + } + break; + case 0xe0 : + switch (utf8[1]) { + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_e0a4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_e0a5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_e0a6[utf8[2] - 0x85]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x8e && + utf8[2] <= 0xba) { + return grn_nfkc50_char_type_table_e0a7[utf8[2] - 0x8e]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xb9) { + return grn_nfkc50_char_type_table_e0a8[utf8[2] - 0x85]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x99 && + utf8[2] <= 0xb4) { + return grn_nfkc50_char_type_table_e0a9[utf8[2] - 0x99]; + } + break; + case 0xaa : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_e0aa[utf8[2] - 0x85]; + } + break; + case 0xab : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xb1) { + return grn_nfkc50_char_type_table_e0ab[utf8[2] - 0x90]; + } + break; + case 0xac : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_e0ac[utf8[2] - 0x85]; + } + break; + case 0xad : + if (utf8[2] >= 0x9c && + utf8[2] <= 0xb1) { + return grn_nfkc50_char_type_table_e0ad[utf8[2] - 0x9c]; + } + break; + case 0xae : + if (utf8[2] >= 0x83 && + utf8[2] <= 0xb9) { + return grn_nfkc50_char_type_table_e0ae[utf8[2] - 0x83]; + } + break; + case 0xaf : + if (utf8[2] >= 0xa6 && + utf8[2] <= 0xba) { + return grn_nfkc50_char_type_table_e0af[utf8[2] - 0xa6]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xb9) { + return grn_nfkc50_char_type_table_e0b0[utf8[2] - 0x85]; + } + break; + case 0xb1 : + if (utf8[2] >= 0xa0 && + utf8[2] <= 0xaf) { + return grn_nfkc50_char_type_table_e0b1[utf8[2] - 0xa0]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_e0b2[utf8[2] - 0x85]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x9e && + utf8[2] <= 0xb2) { + return grn_nfkc50_char_type_table_e0b3[utf8[2] - 0x9e]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xb9) { + return grn_nfkc50_char_type_table_e0b4[utf8[2] - 0x85]; + } + break; + case 0xb5 : + if (utf8[2] >= 0xa0 && + utf8[2] <= 0xaf) { + return grn_nfkc50_char_type_table_e0b5[utf8[2] - 0xa0]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_e0b6[utf8[2] - 0x85]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb4) { + return grn_nfkc50_char_type_table_e0b7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_e0b8[utf8[2] - 0x81]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x9b) { + return grn_nfkc50_char_type_table_e0b9[utf8[2] - 0x80]; + } + break; + case 0xba : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_e0ba[utf8[2] - 0x81]; + } + break; + case 0xbb : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x9d) { + return grn_nfkc50_char_type_table_e0bb[utf8[2] - 0x80]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_e0bc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xaa) { + return grn_nfkc50_char_type_table_e0bd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_e0be[utf8[2] - 0x85]; + } + break; + case 0xbf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x91) { + return grn_nfkc50_char_type_table_e0bf[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + case 0xe1 : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xaa) { + return grn_nfkc50_char_type_table_e180[utf8[2] - 0x80]; + } + break; + case 0x81 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x95) { + return grn_nfkc50_char_type_table_e181[utf8[2] - 0x80]; + } + break; + case 0x82 : + if (utf8[2] >= 0xa0 && + utf8[2] <= 0xbf) { + return GRN_CHAR_ALPHA; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbc) { + return grn_nfkc50_char_type_table_e183[utf8[2] - 0x80]; + } + break; + case 0x84 : + return GRN_CHAR_ALPHA; + case 0x85 : + return grn_nfkc50_char_type_table_e185[utf8[2] - 0x80]; + case 0x86 : + return grn_nfkc50_char_type_table_e186[utf8[2] - 0x80]; + case 0x87 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb9) { + return GRN_CHAR_ALPHA; + } + break; + case 0x88 : + return GRN_CHAR_ALPHA; + case 0x89 : + return grn_nfkc50_char_type_table_e189[utf8[2] - 0x80]; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_char_type_table_e18a[utf8[2] - 0x80]; + } + break; + case 0x8b : + return grn_nfkc50_char_type_table_e18b[utf8[2] - 0x80]; + case 0x8c : + return grn_nfkc50_char_type_table_e18c[utf8[2] - 0x80]; + case 0x8d : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbc) { + return grn_nfkc50_char_type_table_e18d[utf8[2] - 0x80]; + } + break; + case 0x8e : + return grn_nfkc50_char_type_table_e18e[utf8[2] - 0x80]; + case 0x8f : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb4) { + return GRN_CHAR_ALPHA; + } + break; + case 0x90 : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xbf) { + return GRN_CHAR_ALPHA; + } + break; + case 0x91 : + return GRN_CHAR_ALPHA; + case 0x92 : + return GRN_CHAR_ALPHA; + case 0x93 : + return GRN_CHAR_ALPHA; + case 0x94 : + return GRN_CHAR_ALPHA; + case 0x95 : + return GRN_CHAR_ALPHA; + case 0x96 : + return GRN_CHAR_ALPHA; + case 0x97 : + return GRN_CHAR_ALPHA; + case 0x98 : + return GRN_CHAR_ALPHA; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb6) { + return grn_nfkc50_char_type_table_e199[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_e19a[utf8[2] - 0x81]; + } + break; + case 0x9b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb0) { + return grn_nfkc50_char_type_table_e19b[utf8[2] - 0x80]; + } + break; + case 0x9c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb6) { + return grn_nfkc50_char_type_table_e19c[utf8[2] - 0x80]; + } + break; + case 0x9d : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb0) { + return grn_nfkc50_char_type_table_e19d[utf8[2] - 0x80]; + } + break; + case 0x9e : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb3) { + return GRN_CHAR_ALPHA; + } + break; + case 0x9f : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb9) { + return grn_nfkc50_char_type_table_e19f[utf8[2] - 0x94]; + } + break; + case 0xa0 : + return grn_nfkc50_char_type_table_e1a0[utf8[2] - 0x80]; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb7) { + return GRN_CHAR_ALPHA; + } + break; + case 0xa2 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xa8) { + return GRN_CHAR_ALPHA; + } + break; + case 0xa4 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x9c) { + return GRN_CHAR_ALPHA; + } + break; + case 0xa5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb4) { + return grn_nfkc50_char_type_table_e1a5[utf8[2] - 0x80]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xa9) { + return GRN_CHAR_ALPHA; + } + break; + case 0xa7 : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_e1a7[utf8[2] - 0x81]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x9f) { + return grn_nfkc50_char_type_table_e1a8[utf8[2] - 0x80]; + } + break; + case 0xac : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xb3) { + return GRN_CHAR_ALPHA; + } + break; + case 0xad : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xbc) { + return grn_nfkc50_char_type_table_e1ad[utf8[2] - 0x85]; + } + break; + case 0xb4 : + return GRN_CHAR_ALPHA; + case 0xb5 : + return GRN_CHAR_ALPHA; + case 0xb6 : + return GRN_CHAR_ALPHA; + case 0xb8 : + return GRN_CHAR_ALPHA; + case 0xb9 : + return GRN_CHAR_ALPHA; + case 0xba : + return grn_nfkc50_char_type_table_e1ba[utf8[2] - 0x80]; + case 0xbb : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb9) { + return GRN_CHAR_ALPHA; + } + break; + case 0xbc : + return grn_nfkc50_char_type_table_e1bc[utf8[2] - 0x80]; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_e1bd[utf8[2] - 0x80]; + } + break; + case 0xbe : + return grn_nfkc50_char_type_table_e1be[utf8[2] - 0x80]; + case 0xbf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_char_type_table_e1bf[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + case 0xe2 : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_e280[utf8[2] - 0x90]; + } + break; + case 0x81 : + return grn_nfkc50_char_type_table_e281[utf8[2] - 0x80]; + case 0x82 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb5) { + return grn_nfkc50_char_type_table_e282[utf8[2] - 0x80]; + } + break; + case 0x84 : + return grn_nfkc50_char_type_table_e284[utf8[2] - 0x80]; + case 0x85 : + return grn_nfkc50_char_type_table_e285[utf8[2] - 0x80]; + case 0x86 : + return grn_nfkc50_char_type_table_e286[utf8[2] - 0x80]; + case 0x87 : + return GRN_CHAR_SYMBOL; + case 0x88 : + return GRN_CHAR_SYMBOL; + case 0x89 : + return GRN_CHAR_SYMBOL; + case 0x8a : + return GRN_CHAR_SYMBOL; + case 0x8b : + return GRN_CHAR_SYMBOL; + case 0x8c : + return GRN_CHAR_SYMBOL; + case 0x8d : + return GRN_CHAR_SYMBOL; + case 0x8e : + return GRN_CHAR_SYMBOL; + case 0x8f : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xa7) { + return GRN_CHAR_SYMBOL; + } + break; + case 0x90 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xa6) { + return GRN_CHAR_SYMBOL; + } + break; + case 0x91 : + return grn_nfkc50_char_type_table_e291[utf8[2] - 0x80]; + case 0x92 : + return grn_nfkc50_char_type_table_e292[utf8[2] - 0x80]; + case 0x93 : + return grn_nfkc50_char_type_table_e293[utf8[2] - 0x80]; + case 0x94 : + return GRN_CHAR_SYMBOL; + case 0x95 : + return GRN_CHAR_SYMBOL; + case 0x96 : + return GRN_CHAR_SYMBOL; + case 0x97 : + return GRN_CHAR_SYMBOL; + case 0x98 : + return GRN_CHAR_SYMBOL; + case 0x99 : + return GRN_CHAR_SYMBOL; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb2) { + return grn_nfkc50_char_type_table_e29a[utf8[2] - 0x80]; + } + break; + case 0x9c : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_e29c[utf8[2] - 0x81]; + } + break; + case 0x9d : + return grn_nfkc50_char_type_table_e29d[utf8[2] - 0x80]; + case 0x9e : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_char_type_table_e29e[utf8[2] - 0x80]; + } + break; + case 0x9f : + return grn_nfkc50_char_type_table_e29f[utf8[2] - 0x80]; + case 0xa0 : + return GRN_CHAR_SYMBOL; + case 0xa1 : + return GRN_CHAR_SYMBOL; + case 0xa2 : + return GRN_CHAR_SYMBOL; + case 0xa3 : + return GRN_CHAR_SYMBOL; + case 0xa4 : + return GRN_CHAR_SYMBOL; + case 0xa5 : + return GRN_CHAR_SYMBOL; + case 0xa6 : + return GRN_CHAR_SYMBOL; + case 0xa7 : + return GRN_CHAR_SYMBOL; + case 0xa8 : + return GRN_CHAR_SYMBOL; + case 0xa9 : + return GRN_CHAR_SYMBOL; + case 0xaa : + return GRN_CHAR_SYMBOL; + case 0xab : + return GRN_CHAR_SYMBOL; + case 0xac : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xa3) { + return grn_nfkc50_char_type_table_e2ac[utf8[2] - 0x80]; + } + break; + case 0xb0 : + return grn_nfkc50_char_type_table_e2b0[utf8[2] - 0x80]; + case 0xb1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb7) { + return grn_nfkc50_char_type_table_e2b1[utf8[2] - 0x80]; + } + break; + case 0xb2 : + return GRN_CHAR_ALPHA; + case 0xb3 : + return grn_nfkc50_char_type_table_e2b3[utf8[2] - 0x80]; + case 0xb4 : + return grn_nfkc50_char_type_table_e2b4[utf8[2] - 0x80]; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xaf) { + return grn_nfkc50_char_type_table_e2b5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_char_type_table_e2b6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x9e) { + return grn_nfkc50_char_type_table_e2b7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x97) { + return grn_nfkc50_char_type_table_e2b8[utf8[2] - 0x80]; + } + break; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbb) { + return grn_nfkc50_char_type_table_e2bf[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + case 0xe3 : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_SYMBOL; + case 0x81 : + return GRN_CHAR_HIRAGANA; + case 0x82 : + return grn_nfkc50_char_type_table_e382[utf8[2] - 0x80]; + case 0x83 : + return GRN_CHAR_KATAKANA; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return grn_nfkc50_char_type_table_e387[utf8[2] - 0x80]; + case 0x88 : + return GRN_CHAR_SYMBOL; + case 0x89 : + return GRN_CHAR_SYMBOL; + case 0x8a : + return GRN_CHAR_SYMBOL; + case 0x8b : + return GRN_CHAR_SYMBOL; + case 0x8c : + return GRN_CHAR_SYMBOL; + case 0x8d : + return GRN_CHAR_SYMBOL; + case 0x8e : + return GRN_CHAR_SYMBOL; + case 0x8f : + return GRN_CHAR_SYMBOL; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xe4 : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_SYMBOL; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xe5 : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xe6 : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xe7 : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xe8 : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xe9 : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xea : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x8f) { + return GRN_CHAR_KANJI; + } + break; + case 0x9c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xa1) { + return grn_nfkc50_char_type_table_ea9c[utf8[2] - 0x80]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xab) { + return grn_nfkc50_char_type_table_eaa0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb7) { + return grn_nfkc50_char_type_table_eaa1[utf8[2] - 0x80]; + } + break; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xaf) { + return GRN_CHAR_KANJI; + } + break; + default : + break; + } + break; + case 0xef : + switch (utf8[1]) { + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_char_type_table_efac[utf8[2] - 0x80]; + } + break; + case 0xad : + return grn_nfkc50_char_type_table_efad[utf8[2] - 0x80]; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb1) { + return GRN_CHAR_ALPHA; + } + break; + case 0xaf : + if (utf8[2] >= 0x93 && + utf8[2] <= 0xbf) { + return GRN_CHAR_ALPHA; + } + break; + case 0xb0 : + return GRN_CHAR_ALPHA; + case 0xb1 : + return GRN_CHAR_ALPHA; + case 0xb2 : + return GRN_CHAR_ALPHA; + case 0xb3 : + return GRN_CHAR_ALPHA; + case 0xb4 : + return grn_nfkc50_char_type_table_efb4[utf8[2] - 0x80]; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xbf) { + return GRN_CHAR_ALPHA; + } + break; + case 0xb6 : + return grn_nfkc50_char_type_table_efb6[utf8[2] - 0x80]; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbd) { + return grn_nfkc50_char_type_table_efb7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_efb8[utf8[2] - 0x90]; + } + break; + case 0xb9 : + return grn_nfkc50_char_type_table_efb9[utf8[2] - 0x80]; + case 0xba : + return GRN_CHAR_ALPHA; + case 0xbb : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbc) { + return GRN_CHAR_ALPHA; + } + break; + case 0xbc : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_efbc[utf8[2] - 0x81]; + } + break; + case 0xbd : + return grn_nfkc50_char_type_table_efbd[utf8[2] - 0x80]; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return GRN_CHAR_ALPHA; + } + break; + case 0xbf : + if (utf8[2] >= 0x82 && + utf8[2] <= 0xbf) { + return grn_nfkc50_char_type_table_efbf[utf8[2] - 0x82]; + } + break; + default : + break; + } + break; + case 0xf0 : + switch (utf8[1]) { + case 0x90 : + switch (utf8[2]) { + case 0x80 : + return grn_nfkc50_char_type_table_f09080[utf8[3] - 0x80]; + case 0x81 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x9d) { + return grn_nfkc50_char_type_table_f09081[utf8[3] - 0x80]; + } + break; + case 0x82 : + return GRN_CHAR_ALPHA; + case 0x83 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xba) { + return GRN_CHAR_ALPHA; + } + break; + case 0x84 : + return grn_nfkc50_char_type_table_f09084[utf8[3] - 0x80]; + case 0x85 : + return grn_nfkc50_char_type_table_f09085[utf8[3] - 0x80]; + case 0x86 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x8a) { + return grn_nfkc50_char_type_table_f09086[utf8[3] - 0x80]; + } + break; + case 0x8c : + return grn_nfkc50_char_type_table_f0908c[utf8[3] - 0x80]; + case 0x8d : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x8a) { + return grn_nfkc50_char_type_table_f0908d[utf8[3] - 0x80]; + } + break; + case 0x8e : + return grn_nfkc50_char_type_table_f0908e[utf8[3] - 0x80]; + case 0x8f : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x95) { + return grn_nfkc50_char_type_table_f0908f[utf8[3] - 0x80]; + } + break; + case 0x90 : + return GRN_CHAR_ALPHA; + case 0x91 : + return GRN_CHAR_ALPHA; + case 0x92 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xa9) { + return grn_nfkc50_char_type_table_f09092[utf8[3] - 0x80]; + } + break; + case 0xa0 : + return grn_nfkc50_char_type_table_f090a0[utf8[3] - 0x80]; + case 0xa4 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x9f) { + return grn_nfkc50_char_type_table_f090a4[utf8[3] - 0x80]; + } + break; + case 0xa8 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xb3) { + return grn_nfkc50_char_type_table_f090a8[utf8[3] - 0x80]; + } + break; + case 0xa9 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x98) { + return grn_nfkc50_char_type_table_f090a9[utf8[3] - 0x80]; + } + break; + default : + break; + } + break; + case 0x92 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_ALPHA; + case 0x81 : + return GRN_CHAR_ALPHA; + case 0x82 : + return GRN_CHAR_ALPHA; + case 0x83 : + return GRN_CHAR_ALPHA; + case 0x84 : + return GRN_CHAR_ALPHA; + case 0x85 : + return GRN_CHAR_ALPHA; + case 0x86 : + return GRN_CHAR_ALPHA; + case 0x87 : + return GRN_CHAR_ALPHA; + case 0x88 : + return GRN_CHAR_ALPHA; + case 0x89 : + return GRN_CHAR_ALPHA; + case 0x8a : + return GRN_CHAR_ALPHA; + case 0x8b : + return GRN_CHAR_ALPHA; + case 0x8c : + return GRN_CHAR_ALPHA; + case 0x8d : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xae) { + return GRN_CHAR_ALPHA; + } + break; + case 0x90 : + return GRN_CHAR_DIGIT; + case 0x91 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xb3) { + return grn_nfkc50_char_type_table_f09291[utf8[3] - 0x80]; + } + break; + default : + break; + } + break; + case 0x9d : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_SYMBOL; + case 0x81 : + return GRN_CHAR_SYMBOL; + case 0x82 : + return GRN_CHAR_SYMBOL; + case 0x83 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xb5) { + return GRN_CHAR_SYMBOL; + } + break; + case 0x84 : + return grn_nfkc50_char_type_table_f09d84[utf8[3] - 0x80]; + case 0x85 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xac) { + return grn_nfkc50_char_type_table_f09d85[utf8[3] - 0x80]; + } + break; + case 0x86 : + if (utf8[3] >= 0x83 && + utf8[3] <= 0xbf) { + return grn_nfkc50_char_type_table_f09d86[utf8[3] - 0x83]; + } + break; + case 0x87 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x9d) { + return GRN_CHAR_SYMBOL; + } + break; + case 0x88 : + return GRN_CHAR_SYMBOL; + case 0x89 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x85) { + return grn_nfkc50_char_type_table_f09d89[utf8[3] - 0x80]; + } + break; + case 0x8c : + return GRN_CHAR_SYMBOL; + case 0x8d : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xb1) { + return grn_nfkc50_char_type_table_f09d8d[utf8[3] - 0x80]; + } + break; + case 0x90 : + return GRN_CHAR_ALPHA; + case 0x91 : + return grn_nfkc50_char_type_table_f09d91[utf8[3] - 0x80]; + case 0x92 : + return grn_nfkc50_char_type_table_f09d92[utf8[3] - 0x80]; + case 0x93 : + return grn_nfkc50_char_type_table_f09d93[utf8[3] - 0x80]; + case 0x94 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xbe) { + return grn_nfkc50_char_type_table_f09d94[utf8[3] - 0x80]; + } + break; + case 0x95 : + return grn_nfkc50_char_type_table_f09d95[utf8[3] - 0x80]; + case 0x96 : + return GRN_CHAR_ALPHA; + case 0x97 : + return GRN_CHAR_ALPHA; + case 0x98 : + return GRN_CHAR_ALPHA; + case 0x99 : + return GRN_CHAR_ALPHA; + case 0x9a : + return grn_nfkc50_char_type_table_f09d9a[utf8[3] - 0x80]; + case 0x9b : + return grn_nfkc50_char_type_table_f09d9b[utf8[3] - 0x80]; + case 0x9c : + return grn_nfkc50_char_type_table_f09d9c[utf8[3] - 0x80]; + case 0x9d : + return grn_nfkc50_char_type_table_f09d9d[utf8[3] - 0x80]; + case 0x9e : + return grn_nfkc50_char_type_table_f09d9e[utf8[3] - 0x80]; + case 0x9f : + return grn_nfkc50_char_type_table_f09d9f[utf8[3] - 0x80]; + default : + break; + } + break; + case 0xa0 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xa1 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xa2 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xa3 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xa4 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xa5 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xa6 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xa7 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xa8 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xa9 : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + return GRN_CHAR_KANJI; + case 0x9c : + return GRN_CHAR_KANJI; + case 0x9d : + return GRN_CHAR_KANJI; + case 0x9e : + return GRN_CHAR_KANJI; + case 0x9f : + return GRN_CHAR_KANJI; + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + return GRN_CHAR_KANJI; + case 0xa9 : + return GRN_CHAR_KANJI; + case 0xaa : + return GRN_CHAR_KANJI; + case 0xab : + return GRN_CHAR_KANJI; + case 0xac : + return GRN_CHAR_KANJI; + case 0xad : + return GRN_CHAR_KANJI; + case 0xae : + return GRN_CHAR_KANJI; + case 0xaf : + return GRN_CHAR_KANJI; + case 0xb0 : + return GRN_CHAR_KANJI; + case 0xb1 : + return GRN_CHAR_KANJI; + case 0xb2 : + return GRN_CHAR_KANJI; + case 0xb3 : + return GRN_CHAR_KANJI; + case 0xb4 : + return GRN_CHAR_KANJI; + case 0xb5 : + return GRN_CHAR_KANJI; + case 0xb6 : + return GRN_CHAR_KANJI; + case 0xb7 : + return GRN_CHAR_KANJI; + case 0xb8 : + return GRN_CHAR_KANJI; + case 0xb9 : + return GRN_CHAR_KANJI; + case 0xba : + return GRN_CHAR_KANJI; + case 0xbb : + return GRN_CHAR_KANJI; + case 0xbc : + return GRN_CHAR_KANJI; + case 0xbd : + return GRN_CHAR_KANJI; + case 0xbe : + return GRN_CHAR_KANJI; + case 0xbf : + return GRN_CHAR_KANJI; + default : + break; + } + break; + case 0xaa : + switch (utf8[2]) { + case 0x80 : + return GRN_CHAR_KANJI; + case 0x81 : + return GRN_CHAR_KANJI; + case 0x82 : + return GRN_CHAR_KANJI; + case 0x83 : + return GRN_CHAR_KANJI; + case 0x84 : + return GRN_CHAR_KANJI; + case 0x85 : + return GRN_CHAR_KANJI; + case 0x86 : + return GRN_CHAR_KANJI; + case 0x87 : + return GRN_CHAR_KANJI; + case 0x88 : + return GRN_CHAR_KANJI; + case 0x89 : + return GRN_CHAR_KANJI; + case 0x8a : + return GRN_CHAR_KANJI; + case 0x8b : + return GRN_CHAR_KANJI; + case 0x8c : + return GRN_CHAR_KANJI; + case 0x8d : + return GRN_CHAR_KANJI; + case 0x8e : + return GRN_CHAR_KANJI; + case 0x8f : + return GRN_CHAR_KANJI; + case 0x90 : + return GRN_CHAR_KANJI; + case 0x91 : + return GRN_CHAR_KANJI; + case 0x92 : + return GRN_CHAR_KANJI; + case 0x93 : + return GRN_CHAR_KANJI; + case 0x94 : + return GRN_CHAR_KANJI; + case 0x95 : + return GRN_CHAR_KANJI; + case 0x96 : + return GRN_CHAR_KANJI; + case 0x97 : + return GRN_CHAR_KANJI; + case 0x98 : + return GRN_CHAR_KANJI; + case 0x99 : + return GRN_CHAR_KANJI; + case 0x9a : + return GRN_CHAR_KANJI; + case 0x9b : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x9f) { + return GRN_CHAR_KANJI; + } + break; + default : + break; + } + break; + case 0xaf : + switch (utf8[2]) { + case 0xa0 : + return GRN_CHAR_KANJI; + case 0xa1 : + return GRN_CHAR_KANJI; + case 0xa2 : + return GRN_CHAR_KANJI; + case 0xa3 : + return GRN_CHAR_KANJI; + case 0xa4 : + return GRN_CHAR_KANJI; + case 0xa5 : + return GRN_CHAR_KANJI; + case 0xa6 : + return GRN_CHAR_KANJI; + case 0xa7 : + return GRN_CHAR_KANJI; + case 0xa8 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x9f) { + return GRN_CHAR_KANJI; + } + break; + default : + break; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return GRN_CHAR_OTHERS; +} + +static const char *grn_nfkc50_decompose_table_[] = { + "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", + "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", + "\x79", "\x7a" +}; + +static const char *grn_nfkc50_decompose_table_c2[] = { + "\x20", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xcc\x88", NULL, "\x61", NULL, NULL, NULL, NULL, "\xcc\x84", + NULL, NULL, "\x32", "\x33", "\xcc\x81", "\xce\xbc", NULL, NULL, + "\xcc\xa7", "\x31", "\x6f", NULL, "\x31\xe2\x81\x84\x34", "\x31\xe2\x81\x84\x32", "\x33\xe2\x81\x84\x34" +}; + +static const char *grn_nfkc50_decompose_table_c3[] = { + "\xc3\xa0", "\xc3\xa1", "\xc3\xa2", "\xc3\xa3", "\xc3\xa4", "\xc3\xa5", NULL, "\xc3\xa7", + "\xc3\xa8", "\xc3\xa9", "\xc3\xaa", "\xc3\xab", "\xc3\xac", "\xc3\xad", "\xc3\xae", "\xc3\xaf", + NULL, "\xc3\xb1", "\xc3\xb2", "\xc3\xb3", "\xc3\xb4", "\xc3\xb5", "\xc3\xb6", NULL, + NULL, "\xc3\xb9", "\xc3\xba", "\xc3\xbb", "\xc3\xbc", "\xc3\xbd" +}; + +static const char *grn_nfkc50_decompose_table_c4[] = { + "\xc4\x81", NULL, "\xc4\x83", NULL, "\xc4\x85", NULL, "\xc4\x87", NULL, + "\xc4\x89", NULL, "\xc4\x8b", NULL, "\xc4\x8d", NULL, "\xc4\x8f", NULL, + NULL, NULL, "\xc4\x93", NULL, "\xc4\x95", NULL, "\xc4\x97", NULL, + "\xc4\x99", NULL, "\xc4\x9b", NULL, "\xc4\x9d", NULL, "\xc4\x9f", NULL, + "\xc4\xa1", NULL, "\xc4\xa3", NULL, "\xc4\xa5", NULL, NULL, NULL, + "\xc4\xa9", NULL, "\xc4\xab", NULL, "\xc4\xad", NULL, "\xc4\xaf", NULL, + "\x69\xcc\x87", NULL, "\x69\x6a", "\x69\x6a", "\xc4\xb5", NULL, "\xc4\xb7", NULL, + NULL, "\xc4\xba", NULL, "\xc4\xbc", NULL, "\xc4\xbe", NULL, "\x6c\xc2\xb7" +}; + +static const char *grn_nfkc50_decompose_table_c5[] = { + "\x6c\xc2\xb7", NULL, NULL, "\xc5\x84", NULL, "\xc5\x86", NULL, "\xc5\x88", + NULL, "\xca\xbc\x6e", NULL, NULL, "\xc5\x8d", NULL, "\xc5\x8f", NULL, + "\xc5\x91", NULL, NULL, NULL, "\xc5\x95", NULL, "\xc5\x97", NULL, + "\xc5\x99", NULL, "\xc5\x9b", NULL, "\xc5\x9d", NULL, "\xc5\x9f", NULL, + "\xc5\xa1", NULL, "\xc5\xa3", NULL, "\xc5\xa5", NULL, NULL, NULL, + "\xc5\xa9", NULL, "\xc5\xab", NULL, "\xc5\xad", NULL, "\xc5\xaf", NULL, + "\xc5\xb1", NULL, "\xc5\xb3", NULL, "\xc5\xb5", NULL, "\xc5\xb7", NULL, + "\xc3\xbf", "\xc5\xba", NULL, "\xc5\xbc", NULL, "\xc5\xbe", NULL, "\x73" +}; + +static const char *grn_nfkc50_decompose_table_c6[] = { + "\xc6\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\xc6\xb0" +}; + +static const char *grn_nfkc50_decompose_table_c7[] = { + "\x64\xc5\xbe", "\x64\xc5\xbe", "\x64\xc5\xbe", "\x6c\x6a", "\x6c\x6a", "\x6c\x6a", "\x6e\x6a", "\x6e\x6a", + "\x6e\x6a", "\xc7\x8e", NULL, "\xc7\x90", NULL, "\xc7\x92", NULL, "\xc7\x94", + NULL, "\xc7\x96", NULL, "\xc7\x98", NULL, "\xc7\x9a", NULL, "\xc7\x9c", + NULL, NULL, "\xc7\x9f", NULL, "\xc7\xa1", NULL, NULL, NULL, + NULL, NULL, "\xc7\xa7", NULL, "\xc7\xa9", NULL, "\xc7\xab", NULL, + "\xc7\xad", NULL, NULL, NULL, NULL, "\x64\x7a", "\x64\x7a", "\x64\x7a", + "\xc7\xb5", NULL, NULL, NULL, "\xc7\xb9", NULL, "\xc7\xbb" +}; + +static const char *grn_nfkc50_decompose_table_c8[] = { + "\xc8\x81", NULL, "\xc8\x83", NULL, "\xc8\x85", NULL, "\xc8\x87", NULL, + "\xc8\x89", NULL, "\xc8\x8b", NULL, "\xc8\x8d", NULL, "\xc8\x8f", NULL, + "\xc8\x91", NULL, "\xc8\x93", NULL, "\xc8\x95", NULL, "\xc8\x97", NULL, + "\xc8\x99", NULL, "\xc8\x9b", NULL, NULL, NULL, "\xc8\x9f", NULL, + NULL, NULL, NULL, NULL, NULL, NULL, "\xc8\xa7", NULL, + "\xc8\xa9", NULL, "\xc8\xab", NULL, "\xc8\xad", NULL, "\xc8\xaf", NULL, + "\xc8\xb1", NULL, "\xc8\xb3" +}; + +static const char *grn_nfkc50_decompose_table_ca[] = { + "\x68", "\xc9\xa6", "\x6a", "\x72", "\xc9\xb9", "\xc9\xbb", "\xca\x81", "\x77", + "\x79" +}; + +static const char *grn_nfkc50_decompose_table_cb[] = { + "\xcc\x86", "\xcc\x87", "\xcc\x8a", "\xcc\xa8", "\xcc\x83", "\xcc\x8b", NULL, NULL, + "\xc9\xa3", "\x6c", "\x73", "\x78", "\xca\x95" +}; + +static const char *grn_nfkc50_decompose_table_cd[] = { + "\xcc\x80", "\xcc\x81", NULL, "\xcc\x93", "\xcc\x88\xcc\x81", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xca\xb9", NULL, NULL, NULL, + NULL, NULL, "\xcd\x85", NULL, NULL, NULL, "\x3b" +}; + +static const char *grn_nfkc50_decompose_table_ce[] = { + "\xcc\x81", "\xcc\x88\xcc\x81", NULL, "\xc2\xb7" +}; + +static const char *grn_nfkc50_decompose_table_cf[] = { + "\xce\xb2", "\xce\xb8", "\xce\xa5", "\xce\x8e", "\xce\xab", "\xcf\x86", "\xcf\x80", NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xce\xba", "\xcf\x81", "\xcf\x82", NULL, "\xce\x98", "\xce\xb5", NULL, NULL, + NULL, "\xce\xa3" +}; + +static const char *grn_nfkc50_decompose_table_d9[] = { + "\xd8\xa7\xd9\xb4", "\xd9\x88\xd9\xb4", "\xdb\x87\xd9\xb4", "\xd9\x8a\xd9\xb4" +}; + +static const char *grn_nfkc50_decompose_table_e0a5[] = { + "\xe0\xa4\x95\xe0\xa4\xbc", "\xe0\xa4\x96\xe0\xa4\xbc", "\xe0\xa4\x97\xe0\xa4\xbc", "\xe0\xa4\x9c\xe0\xa4\xbc", "\xe0\xa4\xa1\xe0\xa4\xbc", "\xe0\xa4\xa2\xe0\xa4\xbc", "\xe0\xa4\xab\xe0\xa4\xbc", "\xe0\xa4\xaf\xe0\xa4\xbc" +}; + +static const char *grn_nfkc50_decompose_table_e0a7[] = { + "\xe0\xa6\xa1\xe0\xa6\xbc", "\xe0\xa6\xa2\xe0\xa6\xbc", NULL, "\xe0\xa6\xaf\xe0\xa6\xbc" +}; + +static const char *grn_nfkc50_decompose_table_e0a8[] = { + "\xe0\xa8\xb2\xe0\xa8\xbc", NULL, NULL, "\xe0\xa8\xb8\xe0\xa8\xbc" +}; + +static const char *grn_nfkc50_decompose_table_e0a9[] = { + "\xe0\xa8\x96\xe0\xa8\xbc", "\xe0\xa8\x97\xe0\xa8\xbc", "\xe0\xa8\x9c\xe0\xa8\xbc", NULL, NULL, "\xe0\xa8\xab\xe0\xa8\xbc" +}; + +static const char *grn_nfkc50_decompose_table_e0ad[] = { + "\xe0\xac\xa1\xe0\xac\xbc", "\xe0\xac\xa2\xe0\xac\xbc" +}; + +static const char *grn_nfkc50_decompose_table_e0bb[] = { + "\xe0\xba\xab\xe0\xba\x99", "\xe0\xba\xab\xe0\xba\xa1" +}; + +static const char *grn_nfkc50_decompose_table_e0bd[] = { + "\xe0\xbd\x82\xe0\xbe\xb7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "\xe0\xbd\x8c\xe0\xbe\xb7", NULL, NULL, NULL, NULL, "\xe0\xbd\x91\xe0\xbe\xb7", + NULL, NULL, NULL, NULL, "\xe0\xbd\x96\xe0\xbe\xb7", NULL, NULL, NULL, + NULL, "\xe0\xbd\x9b\xe0\xbe\xb7", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, "\xe0\xbd\x80\xe0\xbe\xb5", NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe0\xbd\xb1\xe0\xbd\xb2", NULL, "\xe0\xbd\xb1\xe0\xbd\xb4", "\xe0\xbe\xb2\xe0\xbe\x80", "\xe0\xbe\xb2\xe0\xbd\xb1\xe0\xbe\x80", "\xe0\xbe\xb3\xe0\xbe\x80", "\xe0\xbe\xb3\xe0\xbd\xb1\xe0\xbe\x80" +}; + +static const char *grn_nfkc50_decompose_table_e0be[] = { + "\xe0\xbd\xb1\xe0\xbe\x80", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "\xe0\xbe\x92\xe0\xbe\xb7", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xe0\xbe\x9c\xe0\xbe\xb7", NULL, NULL, NULL, + NULL, "\xe0\xbe\xa1\xe0\xbe\xb7", NULL, NULL, NULL, NULL, "\xe0\xbe\xa6\xe0\xbe\xb7", NULL, + NULL, NULL, NULL, "\xe0\xbe\xab\xe0\xbe\xb7", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe0\xbe\x90\xe0\xbe\xb5" +}; + +static const char *grn_nfkc50_decompose_table_e1b4[] = { + "\x61", "\xc3\x86", "\x62", NULL, "\x64", "\x65", "\xc6\x8e", "\x67", + "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", NULL, + "\x6f", "\xc8\xa2", "\x70", "\x72" +}; + +static const char *grn_nfkc50_decompose_table_e1b5[] = { + "\x74", "\x75", "\x77", "\x61", "\xc9\x90", "\xc9\x91", "\xe1\xb4\x82", "\x62", + "\x64", "\x65", "\xc9\x99", "\xc9\x9b", "\xc9\x9c", "\x67", NULL, "\x6b", + "\x6d", "\xc5\x8b", "\x6f", "\xc9\x94", "\xe1\xb4\x96", "\xe1\xb4\x97", "\x70", "\x74", + "\x75", "\xe1\xb4\x9d", "\xc9\xaf", "\x76", "\xe1\xb4\xa5", "\xce\xb2", "\xce\xb3", "\xce\xb4", + "\xcf\x86", "\xcf\x87", "\x69", "\x72", "\x75", "\x76", "\xce\xb2", "\xce\xb3", + "\xcf\x81", "\xcf\x86", "\xcf\x87", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xd0\xbd" +}; + +static const char *grn_nfkc50_decompose_table_e1b6[] = { + "\xc9\x92", "\x63", "\xc9\x95", "\xc3\xb0", "\xc9\x9c", "\x66", "\xc9\x9f", "\xc9\xa1", + "\xc9\xa5", "\xc9\xa8", "\xc9\xa9", "\xc9\xaa", "\xe1\xb5\xbb", "\xca\x9d", "\xc9\xad", "\xe1\xb6\x85", + "\xca\x9f", "\xc9\xb1", "\xc9\xb0", "\xc9\xb2", "\xc9\xb3", "\xc9\xb4", "\xc9\xb5", "\xc9\xb8", + "\xca\x82", "\xca\x83", "\xc6\xab", "\xca\x89", "\xca\x8a", "\xe1\xb4\x9c", "\xca\x8b", "\xca\x8c", + "\x7a", "\xca\x90", "\xca\x91", "\xca\x92", "\xce\xb8" +}; + +static const char *grn_nfkc50_decompose_table_e1b8[] = { + "\xe1\xb8\x81", NULL, "\xe1\xb8\x83", NULL, "\xe1\xb8\x85", NULL, "\xe1\xb8\x87", NULL, + "\xe1\xb8\x89", NULL, "\xe1\xb8\x8b", NULL, "\xe1\xb8\x8d", NULL, "\xe1\xb8\x8f", NULL, + "\xe1\xb8\x91", NULL, "\xe1\xb8\x93", NULL, "\xe1\xb8\x95", NULL, "\xe1\xb8\x97", NULL, + "\xe1\xb8\x99", NULL, "\xe1\xb8\x9b", NULL, "\xe1\xb8\x9d", NULL, "\xe1\xb8\x9f", NULL, + "\xe1\xb8\xa1", NULL, "\xe1\xb8\xa3", NULL, "\xe1\xb8\xa5", NULL, "\xe1\xb8\xa7", NULL, + "\xe1\xb8\xa9", NULL, "\xe1\xb8\xab", NULL, "\xe1\xb8\xad", NULL, "\xe1\xb8\xaf", NULL, + "\xe1\xb8\xb1", NULL, "\xe1\xb8\xb3", NULL, "\xe1\xb8\xb5", NULL, "\xe1\xb8\xb7", NULL, + "\xe1\xb8\xb9", NULL, "\xe1\xb8\xbb", NULL, "\xe1\xb8\xbd", NULL, "\xe1\xb8\xbf" +}; + +static const char *grn_nfkc50_decompose_table_e1b9[] = { + "\xe1\xb9\x81", NULL, "\xe1\xb9\x83", NULL, "\xe1\xb9\x85", NULL, "\xe1\xb9\x87", NULL, + "\xe1\xb9\x89", NULL, "\xe1\xb9\x8b", NULL, "\xe1\xb9\x8d", NULL, "\xe1\xb9\x8f", NULL, + "\xe1\xb9\x91", NULL, "\xe1\xb9\x93", NULL, "\xe1\xb9\x95", NULL, "\xe1\xb9\x97", NULL, + "\xe1\xb9\x99", NULL, "\xe1\xb9\x9b", NULL, "\xe1\xb9\x9d", NULL, "\xe1\xb9\x9f", NULL, + "\xe1\xb9\xa1", NULL, "\xe1\xb9\xa3", NULL, "\xe1\xb9\xa5", NULL, "\xe1\xb9\xa7", NULL, + "\xe1\xb9\xa9", NULL, "\xe1\xb9\xab", NULL, "\xe1\xb9\xad", NULL, "\xe1\xb9\xaf", NULL, + "\xe1\xb9\xb1", NULL, "\xe1\xb9\xb3", NULL, "\xe1\xb9\xb5", NULL, "\xe1\xb9\xb7", NULL, + "\xe1\xb9\xb9", NULL, "\xe1\xb9\xbb", NULL, "\xe1\xb9\xbd", NULL, "\xe1\xb9\xbf" +}; + +static const char *grn_nfkc50_decompose_table_e1ba[] = { + "\xe1\xba\x81", NULL, "\xe1\xba\x83", NULL, "\xe1\xba\x85", NULL, "\xe1\xba\x87", NULL, + "\xe1\xba\x89", NULL, "\xe1\xba\x8b", NULL, "\xe1\xba\x8d", NULL, "\xe1\xba\x8f", NULL, + "\xe1\xba\x91", NULL, "\xe1\xba\x93", NULL, "\xe1\xba\x95", NULL, NULL, NULL, + NULL, NULL, "\x61\xca\xbe", "\xe1\xb9\xa1", NULL, NULL, NULL, NULL, + "\xe1\xba\xa1", NULL, "\xe1\xba\xa3", NULL, "\xe1\xba\xa5", NULL, "\xe1\xba\xa7", NULL, + "\xe1\xba\xa9", NULL, "\xe1\xba\xab", NULL, "\xe1\xba\xad", NULL, "\xe1\xba\xaf", NULL, + "\xe1\xba\xb1", NULL, "\xe1\xba\xb3", NULL, "\xe1\xba\xb5", NULL, "\xe1\xba\xb7", NULL, + "\xe1\xba\xb9", NULL, "\xe1\xba\xbb", NULL, "\xe1\xba\xbd", NULL, "\xe1\xba\xbf" +}; + +static const char *grn_nfkc50_decompose_table_e1bb[] = { + "\xe1\xbb\x81", NULL, "\xe1\xbb\x83", NULL, "\xe1\xbb\x85", NULL, "\xe1\xbb\x87", NULL, + "\xe1\xbb\x89", NULL, "\xe1\xbb\x8b", NULL, "\xe1\xbb\x8d", NULL, "\xe1\xbb\x8f", NULL, + "\xe1\xbb\x91", NULL, "\xe1\xbb\x93", NULL, "\xe1\xbb\x95", NULL, "\xe1\xbb\x97", NULL, + "\xe1\xbb\x99", NULL, "\xe1\xbb\x9b", NULL, "\xe1\xbb\x9d", NULL, "\xe1\xbb\x9f", NULL, + "\xe1\xbb\xa1", NULL, "\xe1\xbb\xa3", NULL, "\xe1\xbb\xa5", NULL, "\xe1\xbb\xa7", NULL, + "\xe1\xbb\xa9", NULL, "\xe1\xbb\xab", NULL, "\xe1\xbb\xad", NULL, "\xe1\xbb\xaf", NULL, + "\xe1\xbb\xb1", NULL, "\xe1\xbb\xb3", NULL, "\xe1\xbb\xb5", NULL, "\xe1\xbb\xb7", NULL, + "\xe1\xbb\xb9" +}; + +static const char *grn_nfkc50_decompose_table_e1bd[] = { + "\xce\xac", NULL, "\xce\xad", NULL, "\xce\xae", NULL, "\xce\xaf", NULL, + "\xcf\x8c", NULL, "\xcf\x8d", NULL, "\xcf\x8e" +}; + +static const char *grn_nfkc50_decompose_table_e1be[] = { + "\xce\x86", NULL, "\xcc\x93", "\xce\xb9", "\xcc\x93" +}; + +static const char *grn_nfkc50_decompose_table_e1bf[] = { + "\xcd\x82", "\xcc\x88\xcd\x82", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "\xce\x88", NULL, "\xce\x89", NULL, "\xcc\x93\xcc\x80", "\xcc\x93\xcc\x81", "\xcc\x93\xcd\x82", + NULL, NULL, NULL, "\xce\x90", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "\xce\x8a", NULL, "\xcc\x94\xcc\x80", "\xcc\x94\xcc\x81", "\xcc\x94\xcd\x82", + NULL, NULL, NULL, "\xce\xb0", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "\xce\x8e", NULL, "\xcc\x88\xcc\x80", "\xcc\x88\xcc\x81", "\x60", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "\xce\x8c", NULL, "\xce\x8f", NULL, "\xcc\x81", "\xcc\x94" +}; + +static const char *grn_nfkc50_decompose_table_e280[] = { + "\x20", "\x20", "\x20", "\x20", "\x20", "\x20", "\x20", "\x20", + "\x20", "\x20", "\x20", NULL, NULL, NULL, NULL, NULL, + NULL, "\xe2\x80\x90", NULL, NULL, NULL, NULL, NULL, "\xcc\xb3", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\x2e", "\x2e\x2e", "\x2e\x2e\x2e", NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\x20", + NULL, NULL, NULL, "\xe2\x80\xb2\xe2\x80\xb2", "\xe2\x80\xb2\xe2\x80\xb2\xe2\x80\xb2", NULL, "\xe2\x80\xb5\xe2\x80\xb5", "\xe2\x80\xb5\xe2\x80\xb5\xe2\x80\xb5", + NULL, NULL, NULL, NULL, "\x21\x21", NULL, "\xcc\x85" +}; + +static const char *grn_nfkc50_decompose_table_e281[] = { + "\x3f\x3f", "\x3f\x21", "\x21\x3f", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe2\x80\xb2\xe2\x80\xb2\xe2\x80\xb2\xe2\x80\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\x20", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "\x30", "\x69", NULL, NULL, "\x34", "\x35", "\x36", + "\x37", "\x38", "\x39", "\x2b", "\xe2\x88\x92", "\x3d", "\x28", "\x29", + "\x6e" +}; + +static const char *grn_nfkc50_decompose_table_e282[] = { + "\x30", "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", + "\x38", "\x39", "\x2b", "\xe2\x88\x92", "\x3d", "\x28", "\x29", NULL, + "\x61", "\x65", "\x6f", "\x78", "\xc9\x99", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\x72\x73" +}; + +static const char *grn_nfkc50_decompose_table_e284[] = { + "\x61\x2f\x63", "\x61\x2f\x73", "\x63", "\xc2\xb0\x63", NULL, "\x63\x2f\x6f", "\x63\x2f\x75", "\xc6\x90", + NULL, "\xc2\xb0\x66", "\x67", "\x68", "\x68", "\x68", "\x68", "\xc4\xa7", + "\x69", "\x69", "\x6c", "\x6c", NULL, "\x6e", "\x6e\x6f", NULL, + NULL, "\x70", "\x71", "\x72", "\x72", "\x72", NULL, NULL, + "\x73\x6d", "\x74\x65\x6c", "\x74\x6d", NULL, "\x7a", NULL, "\xce\xa9", NULL, + "\x7a", NULL, "\x6b", "\xc3\xa5", "\x62", "\x63", NULL, "\x65", + "\x65", "\x66", NULL, "\x6d", "\x6f", "\xd7\x90", "\xd7\x91", "\xd7\x92", + "\xd7\x93", "\x69", NULL, "\x66\x61\x78", "\xcf\x80", "\xce\xb3", "\xce\x93", "\xce\xa0" +}; + +static const char *grn_nfkc50_decompose_table_e285[] = { + "\xe2\x88\x91", NULL, NULL, NULL, NULL, "\x64", "\x64", "\x65", + "\x69", "\x6a", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "\x31\xe2\x81\x84\x33", "\x32\xe2\x81\x84\x33", "\x31\xe2\x81\x84\x35", "\x32\xe2\x81\x84\x35", "\x33\xe2\x81\x84\x35", + "\x34\xe2\x81\x84\x35", "\x31\xe2\x81\x84\x36", "\x35\xe2\x81\x84\x36", "\x31\xe2\x81\x84\x38", "\x33\xe2\x81\x84\x38", "\x35\xe2\x81\x84\x38", "\x37\xe2\x81\x84\x38", "\x31\xe2\x81\x84", + "\x69", "\x69\x69", "\x69\x69\x69", "\x69\x76", "\x76", "\x76\x69", "\x76\x69\x69", "\x76\x69\x69\x69", + "\x69\x78", "\x78", "\x78\x69", "\x78\x69\x69", "\x6c", "\x63", "\x64", "\x6d", + "\x69", "\x69\x69", "\x69\x69\x69", "\x69\x76", "\x76", "\x76\x69", "\x76\x69\x69", "\x76\x69\x69\x69", + "\x69\x78", "\x78", "\x78\x69", "\x78\x69\x69", "\x6c", "\x63", "\x64", "\x6d" +}; + +static const char *grn_nfkc50_decompose_table_e288[] = { + "\xe2\x88\xab\xe2\x88\xab", "\xe2\x88\xab\xe2\x88\xab\xe2\x88\xab", NULL, "\xe2\x88\xae\xe2\x88\xae", "\xe2\x88\xae\xe2\x88\xae\xe2\x88\xae" +}; + +static const char *grn_nfkc50_decompose_table_e28c[] = { + "\xe3\x80\x88", "\xe3\x80\x89" +}; + +static const char *grn_nfkc50_decompose_table_e291[] = { + "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", "\x38", + "\x39", "\x31\x30", "\x31\x31", "\x31\x32", "\x31\x33", "\x31\x34", "\x31\x35", "\x31\x36", + "\x31\x37", "\x31\x38", "\x31\x39", "\x32\x30", "\x28\x31\x29", "\x28\x32\x29", "\x28\x33\x29", "\x28\x34\x29", + "\x28\x35\x29", "\x28\x36\x29", "\x28\x37\x29", "\x28\x38\x29", "\x28\x39\x29", "\x28\x31\x30\x29", "\x28\x31\x31\x29", "\x28\x31\x32\x29" +}; + +static const char *grn_nfkc50_decompose_table_e292[] = { + "\x28\x31\x33\x29", "\x28\x31\x34\x29", "\x28\x31\x35\x29", "\x28\x31\x36\x29", "\x28\x31\x37\x29", "\x28\x31\x38\x29", "\x28\x31\x39\x29", "\x28\x32\x30\x29", + "\x31\x2e", "\x32\x2e", "\x33\x2e", "\x34\x2e", "\x35\x2e", "\x36\x2e", "\x37\x2e", "\x38\x2e", + "\x39\x2e", "\x31\x30\x2e", "\x31\x31\x2e", "\x31\x32\x2e", "\x31\x33\x2e", "\x31\x34\x2e", "\x31\x35\x2e", "\x31\x36\x2e", + "\x31\x37\x2e", "\x31\x38\x2e", "\x31\x39\x2e", "\x32\x30\x2e", "\x28\x61\x29", "\x28\x62\x29", "\x28\x63\x29", "\x28\x64\x29", + "\x28\x65\x29", "\x28\x66\x29", "\x28\x67\x29", "\x28\x68\x29", "\x28\x69\x29", "\x28\x6a\x29", "\x28\x6b\x29", "\x28\x6c\x29", + "\x28\x6d\x29", "\x28\x6e\x29", "\x28\x6f\x29", "\x28\x70\x29", "\x28\x71\x29", "\x28\x72\x29", "\x28\x73\x29", "\x28\x74\x29", + "\x28\x75\x29", "\x28\x76\x29", "\x28\x77\x29", "\x28\x78\x29", "\x28\x79\x29", "\x28\x7a\x29", "\x61", "\x62", + "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", "\x69", "\x6a" +}; + +static const char *grn_nfkc50_decompose_table_e293[] = { + "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72", + "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", + "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", + "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", + "\x79", "\x7a", "\x30" +}; + +static const char *grn_nfkc50_decompose_table_e2a9[] = { + "\x3a\x3a\x3d", "\x3d\x3d", "\x3d\x3d\x3d" +}; + +static const char *grn_nfkc50_decompose_table_e2bc[] = { + "\xe4\xb8\x80", "\xe4\xb8\xa8", "\xe4\xb8\xb6", "\xe4\xb8\xbf", "\xe4\xb9\x99", "\xe4\xba\x85", "\xe4\xba\x8c", "\xe4\xba\xa0", + "\xe4\xba\xba", "\xe5\x84\xbf", "\xe5\x85\xa5", "\xe5\x85\xab", "\xe5\x86\x82", "\xe5\x86\x96", "\xe5\x86\xab", "\xe5\x87\xa0", + "\xe5\x87\xb5", "\xe5\x88\x80", "\xe5\x8a\x9b", "\xe5\x8b\xb9", "\xe5\x8c\x95", "\xe5\x8c\x9a", "\xe5\x8c\xb8", "\xe5\x8d\x81", + "\xe5\x8d\x9c", "\xe5\x8d\xa9", "\xe5\x8e\x82", "\xe5\x8e\xb6", "\xe5\x8f\x88", "\xe5\x8f\xa3", "\xe5\x9b\x97", "\xe5\x9c\x9f", + "\xe5\xa3\xab", "\xe5\xa4\x82", "\xe5\xa4\x8a", "\xe5\xa4\x95", "\xe5\xa4\xa7", "\xe5\xa5\xb3", "\xe5\xad\x90", "\xe5\xae\x80", + "\xe5\xaf\xb8", "\xe5\xb0\x8f", "\xe5\xb0\xa2", "\xe5\xb0\xb8", "\xe5\xb1\xae", "\xe5\xb1\xb1", "\xe5\xb7\x9b", "\xe5\xb7\xa5", + "\xe5\xb7\xb1", "\xe5\xb7\xbe", "\xe5\xb9\xb2", "\xe5\xb9\xba", "\xe5\xb9\xbf", "\xe5\xbb\xb4", "\xe5\xbb\xbe", "\xe5\xbc\x8b", + "\xe5\xbc\x93", "\xe5\xbd\x90", "\xe5\xbd\xa1", "\xe5\xbd\xb3", "\xe5\xbf\x83", "\xe6\x88\x88", "\xe6\x88\xb6", "\xe6\x89\x8b" +}; + +static const char *grn_nfkc50_decompose_table_e2bd[] = { + "\xe6\x94\xaf", "\xe6\x94\xb4", "\xe6\x96\x87", "\xe6\x96\x97", "\xe6\x96\xa4", "\xe6\x96\xb9", "\xe6\x97\xa0", "\xe6\x97\xa5", + "\xe6\x9b\xb0", "\xe6\x9c\x88", "\xe6\x9c\xa8", "\xe6\xac\xa0", "\xe6\xad\xa2", "\xe6\xad\xb9", "\xe6\xae\xb3", "\xe6\xaf\x8b", + "\xe6\xaf\x94", "\xe6\xaf\x9b", "\xe6\xb0\x8f", "\xe6\xb0\x94", "\xe6\xb0\xb4", "\xe7\x81\xab", "\xe7\x88\xaa", "\xe7\x88\xb6", + "\xe7\x88\xbb", "\xe7\x88\xbf", "\xe7\x89\x87", "\xe7\x89\x99", "\xe7\x89\x9b", "\xe7\x8a\xac", "\xe7\x8e\x84", "\xe7\x8e\x89", + "\xe7\x93\x9c", "\xe7\x93\xa6", "\xe7\x94\x98", "\xe7\x94\x9f", "\xe7\x94\xa8", "\xe7\x94\xb0", "\xe7\x96\x8b", "\xe7\x96\x92", + "\xe7\x99\xb6", "\xe7\x99\xbd", "\xe7\x9a\xae", "\xe7\x9a\xbf", "\xe7\x9b\xae", "\xe7\x9f\x9b", "\xe7\x9f\xa2", "\xe7\x9f\xb3", + "\xe7\xa4\xba", "\xe7\xa6\xb8", "\xe7\xa6\xbe", "\xe7\xa9\xb4", "\xe7\xab\x8b", "\xe7\xab\xb9", "\xe7\xb1\xb3", "\xe7\xb3\xb8", + "\xe7\xbc\xb6", "\xe7\xbd\x91", "\xe7\xbe\x8a", "\xe7\xbe\xbd", "\xe8\x80\x81", "\xe8\x80\x8c", "\xe8\x80\x92", "\xe8\x80\xb3" +}; + +static const char *grn_nfkc50_decompose_table_e2be[] = { + "\xe8\x81\xbf", "\xe8\x82\x89", "\xe8\x87\xa3", "\xe8\x87\xaa", "\xe8\x87\xb3", "\xe8\x87\xbc", "\xe8\x88\x8c", "\xe8\x88\x9b", + "\xe8\x88\x9f", "\xe8\x89\xae", "\xe8\x89\xb2", "\xe8\x89\xb8", "\xe8\x99\x8d", "\xe8\x99\xab", "\xe8\xa1\x80", "\xe8\xa1\x8c", + "\xe8\xa1\xa3", "\xe8\xa5\xbe", "\xe8\xa6\x8b", "\xe8\xa7\x92", "\xe8\xa8\x80", "\xe8\xb0\xb7", "\xe8\xb1\x86", "\xe8\xb1\x95", + "\xe8\xb1\xb8", "\xe8\xb2\x9d", "\xe8\xb5\xa4", "\xe8\xb5\xb0", "\xe8\xb6\xb3", "\xe8\xba\xab", "\xe8\xbb\x8a", "\xe8\xbe\x9b", + "\xe8\xbe\xb0", "\xe8\xbe\xb5", "\xe9\x82\x91", "\xe9\x85\x89", "\xe9\x87\x86", "\xe9\x87\x8c", "\xe9\x87\x91", "\xe9\x95\xb7", + "\xe9\x96\x80", "\xe9\x98\x9c", "\xe9\x9a\xb6", "\xe9\x9a\xb9", "\xe9\x9b\xa8", "\xe9\x9d\x91", "\xe9\x9d\x9e", "\xe9\x9d\xa2", + "\xe9\x9d\xa9", "\xe9\x9f\x8b", "\xe9\x9f\xad", "\xe9\x9f\xb3", "\xe9\xa0\x81", "\xe9\xa2\xa8", "\xe9\xa3\x9b", "\xe9\xa3\x9f", + "\xe9\xa6\x96", "\xe9\xa6\x99", "\xe9\xa6\xac", "\xe9\xaa\xa8", "\xe9\xab\x98", "\xe9\xab\x9f", "\xe9\xac\xa5", "\xe9\xac\xaf" +}; + +static const char *grn_nfkc50_decompose_table_e2bf[] = { + "\xe9\xac\xb2", "\xe9\xac\xbc", "\xe9\xad\x9a", "\xe9\xb3\xa5", "\xe9\xb9\xb5", "\xe9\xb9\xbf", "\xe9\xba\xa5", "\xe9\xba\xbb", + "\xe9\xbb\x83", "\xe9\xbb\x8d", "\xe9\xbb\x91", "\xe9\xbb\xb9", "\xe9\xbb\xbd", "\xe9\xbc\x8e", "\xe9\xbc\x93", "\xe9\xbc\xa0", + "\xe9\xbc\xbb", "\xe9\xbd\x8a", "\xe9\xbd\x92", "\xe9\xbe\x8d", "\xe9\xbe\x9c", "\xe9\xbe\xa0" +}; + +static const char *grn_nfkc50_decompose_table_e380[] = { + "\x20", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\x7e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, "\xe3\x80\x92", NULL, + "\xe5\x8d\x81", "\xe5\x8d\x84", "\xe5\x8d\x85" +}; + +static const char *grn_nfkc50_decompose_table_e382[] = { + "\xe3\x82\x99", "\xe3\x82\x9a", NULL, NULL, "\xe3\x82\x88\xe3\x82\x8a" +}; + +static const char *grn_nfkc50_decompose_table_e384[] = { + "\xe1\x84\x80", "\xe1\x84\x81", "\xe1\x86\xaa", "\xe1\x84\x82", "\xe1\x86\xac", "\xe1\x86\xad", "\xe1\x84\x83", "\xe1\x84\x84", + "\xe1\x84\x85", "\xe1\x86\xb0", "\xe1\x86\xb1", "\xe1\x86\xb2", "\xe1\x86\xb3", "\xe1\x86\xb4", "\xe1\x86\xb5" +}; + +static const char *grn_nfkc50_decompose_table_e385[] = { + "\xe1\x84\x9a", "\xe1\x84\x86", "\xe1\x84\x87", "\xe1\x84\x88", "\xe1\x84\xa1", "\xe1\x84\x89", "\xe1\x84\x8a", "\xe1\x84\x8b", + "\xe1\x84\x8c", "\xe1\x84\x8d", "\xe1\x84\x8e", "\xe1\x84\x8f", "\xe1\x84\x90", "\xe1\x84\x91", "\xe1\x84\x92", "\xe1\x85\xa1", + "\xe1\x85\xa2", "\xe1\x85\xa3", "\xe1\x85\xa4", "\xe1\x85\xa5", "\xe1\x85\xa6", "\xe1\x85\xa7", "\xe1\x85\xa8", "\xe1\x85\xa9", + "\xe1\x85\xaa", "\xe1\x85\xab", "\xe1\x85\xac", "\xe1\x85\xad", "\xe1\x85\xae", "\xe1\x85\xaf", "\xe1\x85\xb0", "\xe1\x85\xb1", + "\xe1\x85\xb2", "\xe1\x85\xb3", "\xe1\x85\xb4", "\xe1\x85\xb5", "\xe1\x85\xa0", "\xe1\x84\x94", "\xe1\x84\x95", "\xe1\x87\x87", + "\xe1\x87\x88", "\xe1\x87\x8c", "\xe1\x87\x8e", "\xe1\x87\x93", "\xe1\x87\x97", "\xe1\x87\x99", "\xe1\x84\x9c", "\xe1\x87\x9d", + "\xe1\x87\x9f", "\xe1\x84\x9d", "\xe1\x84\x9e", "\xe1\x84\xa0", "\xe1\x84\xa2", "\xe1\x84\xa3", "\xe1\x84\xa7", "\xe1\x84\xa9", + "\xe1\x84\xab", "\xe1\x84\xac", "\xe1\x84\xad", "\xe1\x84\xae", "\xe1\x84\xaf", "\xe1\x84\xb2", "\xe1\x84\xb6", "\xe1\x85\x80" +}; + +static const char *grn_nfkc50_decompose_table_e386[] = { + "\xe1\x85\x87", "\xe1\x85\x8c", "\xe1\x87\xb1", "\xe1\x87\xb2", "\xe1\x85\x97", "\xe1\x85\x98", "\xe1\x85\x99", "\xe1\x86\x84", + "\xe1\x86\x85", "\xe1\x86\x88", "\xe1\x86\x91", "\xe1\x86\x92", "\xe1\x86\x94", "\xe1\x86\x9e", "\xe1\x86\xa1", NULL, + NULL, NULL, "\xe4\xb8\x80", "\xe4\xba\x8c", "\xe4\xb8\x89", "\xe5\x9b\x9b", "\xe4\xb8\x8a", "\xe4\xb8\xad", + "\xe4\xb8\x8b", "\xe7\x94\xb2", "\xe4\xb9\x99", "\xe4\xb8\x99", "\xe4\xb8\x81", "\xe5\xa4\xa9", "\xe5\x9c\xb0", "\xe4\xba\xba" +}; + +static const char *grn_nfkc50_decompose_table_e388[] = { + "\x28\xe1\x84\x80\x29", "\x28\xe1\x84\x82\x29", "\x28\xe1\x84\x83\x29", "\x28\xe1\x84\x85\x29", "\x28\xe1\x84\x86\x29", "\x28\xe1\x84\x87\x29", "\x28\xe1\x84\x89\x29", "\x28\xe1\x84\x8b\x29", + "\x28\xe1\x84\x8c\x29", "\x28\xe1\x84\x8e\x29", "\x28\xe1\x84\x8f\x29", "\x28\xe1\x84\x90\x29", "\x28\xe1\x84\x91\x29", "\x28\xe1\x84\x92\x29", "\x28\xea\xb0\x80\x29", "\x28\xeb\x82\x98\x29", + "\x28\xeb\x8b\xa4\x29", "\x28\xeb\x9d\xbc\x29", "\x28\xeb\xa7\x88\x29", "\x28\xeb\xb0\x94\x29", "\x28\xec\x82\xac\x29", "\x28\xec\x95\x84\x29", "\x28\xec\x9e\x90\x29", "\x28\xec\xb0\xa8\x29", + "\x28\xec\xb9\xb4\x29", "\x28\xed\x83\x80\x29", "\x28\xed\x8c\x8c\x29", "\x28\xed\x95\x98\x29", "\x28\xec\xa3\xbc\x29", "\x28\xec\x98\xa4\xec\xa0\x84\x29", "\x28\xec\x98\xa4\xed\x9b\x84\x29", NULL, + "\x28\xe4\xb8\x80\x29", "\x28\xe4\xba\x8c\x29", "\x28\xe4\xb8\x89\x29", "\x28\xe5\x9b\x9b\x29", "\x28\xe4\xba\x94\x29", "\x28\xe5\x85\xad\x29", "\x28\xe4\xb8\x83\x29", "\x28\xe5\x85\xab\x29", + "\x28\xe4\xb9\x9d\x29", "\x28\xe5\x8d\x81\x29", "\x28\xe6\x9c\x88\x29", "\x28\xe7\x81\xab\x29", "\x28\xe6\xb0\xb4\x29", "\x28\xe6\x9c\xa8\x29", "\x28\xe9\x87\x91\x29", "\x28\xe5\x9c\x9f\x29", + "\x28\xe6\x97\xa5\x29", "\x28\xe6\xa0\xaa\x29", "\x28\xe6\x9c\x89\x29", "\x28\xe7\xa4\xbe\x29", "\x28\xe5\x90\x8d\x29", "\x28\xe7\x89\xb9\x29", "\x28\xe8\xb2\xa1\x29", "\x28\xe7\xa5\x9d\x29", + "\x28\xe5\x8a\xb4\x29", "\x28\xe4\xbb\xa3\x29", "\x28\xe5\x91\xbc\x29", "\x28\xe5\xad\xa6\x29", "\x28\xe7\x9b\xa3\x29", "\x28\xe4\xbc\x81\x29", "\x28\xe8\xb3\x87\x29", "\x28\xe5\x8d\x94\x29" +}; + +static const char *grn_nfkc50_decompose_table_e389[] = { + "\x28\xe7\xa5\xad\x29", "\x28\xe4\xbc\x91\x29", "\x28\xe8\x87\xaa\x29", "\x28\xe8\x87\xb3\x29", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\x70\x74\x65", "\x32\x31", "\x32\x32", "\x32\x33", "\x32\x34", "\x32\x35", "\x32\x36", "\x32\x37", + "\x32\x38", "\x32\x39", "\x33\x30", "\x33\x31", "\x33\x32", "\x33\x33", "\x33\x34", "\x33\x35", + "\xe1\x84\x80", "\xe1\x84\x82", "\xe1\x84\x83", "\xe1\x84\x85", "\xe1\x84\x86", "\xe1\x84\x87", "\xe1\x84\x89", "\xe1\x84\x8b", + "\xe1\x84\x8c", "\xe1\x84\x8e", "\xe1\x84\x8f", "\xe1\x84\x90", "\xe1\x84\x91", "\xe1\x84\x92", "\xea\xb0\x80", "\xeb\x82\x98", + "\xeb\x8b\xa4", "\xeb\x9d\xbc", "\xeb\xa7\x88", "\xeb\xb0\x94", "\xec\x82\xac", "\xec\x95\x84", "\xec\x9e\x90", "\xec\xb0\xa8", + "\xec\xb9\xb4", "\xed\x83\x80", "\xed\x8c\x8c", "\xed\x95\x98", "\xec\xb0\xb8\xea\xb3\xa0", "\xec\xa3\xbc\xec\x9d\x98", "\xec\x9a\xb0" +}; + +static const char *grn_nfkc50_decompose_table_e38a[] = { + "\xe4\xb8\x80", "\xe4\xba\x8c", "\xe4\xb8\x89", "\xe5\x9b\x9b", "\xe4\xba\x94", "\xe5\x85\xad", "\xe4\xb8\x83", "\xe5\x85\xab", + "\xe4\xb9\x9d", "\xe5\x8d\x81", "\xe6\x9c\x88", "\xe7\x81\xab", "\xe6\xb0\xb4", "\xe6\x9c\xa8", "\xe9\x87\x91", "\xe5\x9c\x9f", + "\xe6\x97\xa5", "\xe6\xa0\xaa", "\xe6\x9c\x89", "\xe7\xa4\xbe", "\xe5\x90\x8d", "\xe7\x89\xb9", "\xe8\xb2\xa1", "\xe7\xa5\x9d", + "\xe5\x8a\xb4", "\xe7\xa7\x98", "\xe7\x94\xb7", "\xe5\xa5\xb3", "\xe9\x81\xa9", "\xe5\x84\xaa", "\xe5\x8d\xb0", "\xe6\xb3\xa8", + "\xe9\xa0\x85", "\xe4\xbc\x91", "\xe5\x86\x99", "\xe6\xad\xa3", "\xe4\xb8\x8a", "\xe4\xb8\xad", "\xe4\xb8\x8b", "\xe5\xb7\xa6", + "\xe5\x8f\xb3", "\xe5\x8c\xbb", "\xe5\xae\x97", "\xe5\xad\xa6", "\xe7\x9b\xa3", "\xe4\xbc\x81", "\xe8\xb3\x87", "\xe5\x8d\x94", + "\xe5\xa4\x9c", "\x33\x36", "\x33\x37", "\x33\x38", "\x33\x39", "\x34\x30", "\x34\x31", "\x34\x32", + "\x34\x33", "\x34\x34", "\x34\x35", "\x34\x36", "\x34\x37", "\x34\x38", "\x34\x39", "\x35\x30" +}; + +static const char *grn_nfkc50_decompose_table_e38b[] = { + "\x31\xe6\x9c\x88", "\x32\xe6\x9c\x88", "\x33\xe6\x9c\x88", "\x34\xe6\x9c\x88", "\x35\xe6\x9c\x88", "\x36\xe6\x9c\x88", "\x37\xe6\x9c\x88", "\x38\xe6\x9c\x88", + "\x39\xe6\x9c\x88", "\x31\x30\xe6\x9c\x88", "\x31\x31\xe6\x9c\x88", "\x31\x32\xe6\x9c\x88", "\x68\x67", "\x65\x72\x67", "\x65\x76", "\x6c\x74\x64", + "\xe3\x82\xa2", "\xe3\x82\xa4", "\xe3\x82\xa6", "\xe3\x82\xa8", "\xe3\x82\xaa", "\xe3\x82\xab", "\xe3\x82\xad", "\xe3\x82\xaf", + "\xe3\x82\xb1", "\xe3\x82\xb3", "\xe3\x82\xb5", "\xe3\x82\xb7", "\xe3\x82\xb9", "\xe3\x82\xbb", "\xe3\x82\xbd", "\xe3\x82\xbf", + "\xe3\x83\x81", "\xe3\x83\x84", "\xe3\x83\x86", "\xe3\x83\x88", "\xe3\x83\x8a", "\xe3\x83\x8b", "\xe3\x83\x8c", "\xe3\x83\x8d", + "\xe3\x83\x8e", "\xe3\x83\x8f", "\xe3\x83\x92", "\xe3\x83\x95", "\xe3\x83\x98", "\xe3\x83\x9b", "\xe3\x83\x9e", "\xe3\x83\x9f", + "\xe3\x83\xa0", "\xe3\x83\xa1", "\xe3\x83\xa2", "\xe3\x83\xa4", "\xe3\x83\xa6", "\xe3\x83\xa8", "\xe3\x83\xa9", "\xe3\x83\xaa", + "\xe3\x83\xab", "\xe3\x83\xac", "\xe3\x83\xad", "\xe3\x83\xaf", "\xe3\x83\xb0", "\xe3\x83\xb1", "\xe3\x83\xb2" +}; + +static const char *grn_nfkc50_decompose_table_e38c[] = { + "\xe3\x82\xa2\xe3\x83\x91\xe3\x83\xbc\xe3\x83\x88", "\xe3\x82\xa2\xe3\x83\xab\xe3\x83\x95\xe3\x82\xa1", "\xe3\x82\xa2\xe3\x83\xb3\xe3\x83\x9a\xe3\x82\xa2", "\xe3\x82\xa2\xe3\x83\xbc\xe3\x83\xab", "\xe3\x82\xa4\xe3\x83\x8b\xe3\x83\xb3\xe3\x82\xb0", "\xe3\x82\xa4\xe3\x83\xb3\xe3\x83\x81", "\xe3\x82\xa6\xe3\x82\xa9\xe3\x83\xb3", "\xe3\x82\xa8\xe3\x82\xb9\xe3\x82\xaf\xe3\x83\xbc\xe3\x83\x89", + "\xe3\x82\xa8\xe3\x83\xbc\xe3\x82\xab\xe3\x83\xbc", "\xe3\x82\xaa\xe3\x83\xb3\xe3\x82\xb9", "\xe3\x82\xaa\xe3\x83\xbc\xe3\x83\xa0", "\xe3\x82\xab\xe3\x82\xa4\xe3\x83\xaa", "\xe3\x82\xab\xe3\x83\xa9\xe3\x83\x83\xe3\x83\x88", "\xe3\x82\xab\xe3\x83\xad\xe3\x83\xaa\xe3\x83\xbc", "\xe3\x82\xac\xe3\x83\xad\xe3\x83\xb3", "\xe3\x82\xac\xe3\x83\xb3\xe3\x83\x9e", + "\xe3\x82\xae\xe3\x82\xac", "\xe3\x82\xae\xe3\x83\x8b\xe3\x83\xbc", "\xe3\x82\xad\xe3\x83\xa5\xe3\x83\xaa\xe3\x83\xbc", "\xe3\x82\xae\xe3\x83\xab\xe3\x83\x80\xe3\x83\xbc", "\xe3\x82\xad\xe3\x83\xad", "\xe3\x82\xad\xe3\x83\xad\xe3\x82\xb0\xe3\x83\xa9\xe3\x83\xa0", "\xe3\x82\xad\xe3\x83\xad\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\x88\xe3\x83\xab", "\xe3\x82\xad\xe3\x83\xad\xe3\x83\xaf\xe3\x83\x83\xe3\x83\x88", + "\xe3\x82\xb0\xe3\x83\xa9\xe3\x83\xa0", "\xe3\x82\xb0\xe3\x83\xa9\xe3\x83\xa0\xe3\x83\x88\xe3\x83\xb3", "\xe3\x82\xaf\xe3\x83\xab\xe3\x82\xbc\xe3\x82\xa4\xe3\x83\xad", "\xe3\x82\xaf\xe3\x83\xad\xe3\x83\xbc\xe3\x83\x8d", "\xe3\x82\xb1\xe3\x83\xbc\xe3\x82\xb9", "\xe3\x82\xb3\xe3\x83\xab\xe3\x83\x8a", "\xe3\x82\xb3\xe3\x83\xbc\xe3\x83\x9d", "\xe3\x82\xb5\xe3\x82\xa4\xe3\x82\xaf\xe3\x83\xab", + "\xe3\x82\xb5\xe3\x83\xb3\xe3\x83\x81\xe3\x83\xbc\xe3\x83\xa0", "\xe3\x82\xb7\xe3\x83\xaa\xe3\x83\xb3\xe3\x82\xb0", "\xe3\x82\xbb\xe3\x83\xb3\xe3\x83\x81", "\xe3\x82\xbb\xe3\x83\xb3\xe3\x83\x88", "\xe3\x83\x80\xe3\x83\xbc\xe3\x82\xb9", "\xe3\x83\x87\xe3\x82\xb7", "\xe3\x83\x89\xe3\x83\xab", "\xe3\x83\x88\xe3\x83\xb3", + "\xe3\x83\x8a\xe3\x83\x8e", "\xe3\x83\x8e\xe3\x83\x83\xe3\x83\x88", "\xe3\x83\x8f\xe3\x82\xa4\xe3\x83\x84", "\xe3\x83\x91\xe3\x83\xbc\xe3\x82\xbb\xe3\x83\xb3\xe3\x83\x88", "\xe3\x83\x91\xe3\x83\xbc\xe3\x83\x84", "\xe3\x83\x90\xe3\x83\xbc\xe3\x83\xac\xe3\x83\xab", "\xe3\x83\x94\xe3\x82\xa2\xe3\x82\xb9\xe3\x83\x88\xe3\x83\xab", "\xe3\x83\x94\xe3\x82\xaf\xe3\x83\xab", + "\xe3\x83\x94\xe3\x82\xb3", "\xe3\x83\x93\xe3\x83\xab", "\xe3\x83\x95\xe3\x82\xa1\xe3\x83\xa9\xe3\x83\x83\xe3\x83\x89", "\xe3\x83\x95\xe3\x82\xa3\xe3\x83\xbc\xe3\x83\x88", "\xe3\x83\x96\xe3\x83\x83\xe3\x82\xb7\xe3\x82\xa7\xe3\x83\xab", "\xe3\x83\x95\xe3\x83\xa9\xe3\x83\xb3", "\xe3\x83\x98\xe3\x82\xaf\xe3\x82\xbf\xe3\x83\xbc\xe3\x83\xab", "\xe3\x83\x9a\xe3\x82\xbd", + "\xe3\x83\x9a\xe3\x83\x8b\xe3\x83\x92", "\xe3\x83\x98\xe3\x83\xab\xe3\x83\x84", "\xe3\x83\x9a\xe3\x83\xb3\xe3\x82\xb9", "\xe3\x83\x9a\xe3\x83\xbc\xe3\x82\xb8", "\xe3\x83\x99\xe3\x83\xbc\xe3\x82\xbf", "\xe3\x83\x9d\xe3\x82\xa4\xe3\x83\xb3\xe3\x83\x88", "\xe3\x83\x9c\xe3\x83\xab\xe3\x83\x88", "\xe3\x83\x9b\xe3\x83\xb3" +}; + +static const char *grn_nfkc50_decompose_table_e38d[] = { + "\xe3\x83\x9d\xe3\x83\xb3\xe3\x83\x89", "\xe3\x83\x9b\xe3\x83\xbc\xe3\x83\xab", "\xe3\x83\x9b\xe3\x83\xbc\xe3\x83\xb3", "\xe3\x83\x9e\xe3\x82\xa4\xe3\x82\xaf\xe3\x83\xad", "\xe3\x83\x9e\xe3\x82\xa4\xe3\x83\xab", "\xe3\x83\x9e\xe3\x83\x83\xe3\x83\x8f", "\xe3\x83\x9e\xe3\x83\xab\xe3\x82\xaf", "\xe3\x83\x9e\xe3\x83\xb3\xe3\x82\xb7\xe3\x83\xa7\xe3\x83\xb3", + "\xe3\x83\x9f\xe3\x82\xaf\xe3\x83\xad\xe3\x83\xb3", "\xe3\x83\x9f\xe3\x83\xaa", "\xe3\x83\x9f\xe3\x83\xaa\xe3\x83\x90\xe3\x83\xbc\xe3\x83\xab", "\xe3\x83\xa1\xe3\x82\xac", "\xe3\x83\xa1\xe3\x82\xac\xe3\x83\x88\xe3\x83\xb3", "\xe3\x83\xa1\xe3\x83\xbc\xe3\x83\x88\xe3\x83\xab", "\xe3\x83\xa4\xe3\x83\xbc\xe3\x83\x89", "\xe3\x83\xa4\xe3\x83\xbc\xe3\x83\xab", + "\xe3\x83\xa6\xe3\x82\xa2\xe3\x83\xb3", "\xe3\x83\xaa\xe3\x83\x83\xe3\x83\x88\xe3\x83\xab", "\xe3\x83\xaa\xe3\x83\xa9", "\xe3\x83\xab\xe3\x83\x94\xe3\x83\xbc", "\xe3\x83\xab\xe3\x83\xbc\xe3\x83\x96\xe3\x83\xab", "\xe3\x83\xac\xe3\x83\xa0", "\xe3\x83\xac\xe3\x83\xb3\xe3\x83\x88\xe3\x82\xb2\xe3\x83\xb3", "\xe3\x83\xaf\xe3\x83\x83\xe3\x83\x88", + "\x30\xe7\x82\xb9", "\x31\xe7\x82\xb9", "\x32\xe7\x82\xb9", "\x33\xe7\x82\xb9", "\x34\xe7\x82\xb9", "\x35\xe7\x82\xb9", "\x36\xe7\x82\xb9", "\x37\xe7\x82\xb9", + "\x38\xe7\x82\xb9", "\x39\xe7\x82\xb9", "\x31\x30\xe7\x82\xb9", "\x31\x31\xe7\x82\xb9", "\x31\x32\xe7\x82\xb9", "\x31\x33\xe7\x82\xb9", "\x31\x34\xe7\x82\xb9", "\x31\x35\xe7\x82\xb9", + "\x31\x36\xe7\x82\xb9", "\x31\x37\xe7\x82\xb9", "\x31\x38\xe7\x82\xb9", "\x31\x39\xe7\x82\xb9", "\x32\x30\xe7\x82\xb9", "\x32\x31\xe7\x82\xb9", "\x32\x32\xe7\x82\xb9", "\x32\x33\xe7\x82\xb9", + "\x32\x34\xe7\x82\xb9", "\x68\x70\x61", "\x64\x61", "\x61\x75", "\x62\x61\x72", "\x6f\x76", "\x70\x63", "\x64\x6d", + "\x64\x6d\x32", "\x64\x6d\x33", "\x69\x75", "\xe5\xb9\xb3\xe6\x88\x90", "\xe6\x98\xad\xe5\x92\x8c", "\xe5\xa4\xa7\xe6\xad\xa3", "\xe6\x98\x8e\xe6\xb2\xbb", "\xe6\xa0\xaa\xe5\xbc\x8f\xe4\xbc\x9a\xe7\xa4\xbe" +}; + +static const char *grn_nfkc50_decompose_table_e38e[] = { + "\x70\x61", "\x6e\x61", "\xce\xbc\x61", "\x6d\x61", "\x6b\x61", "\x6b\x62", "\x6d\x62", "\x67\x62", + "\x63\x61\x6c", "\x6b\x63\x61\x6c", "\x70\x66", "\x6e\x66", "\xce\xbc\x66", "\xce\xbc\x67", "\x6d\x67", "\x6b\x67", + "\x68\x7a", "\x6b\x68\x7a", "\x6d\x68\x7a", "\x67\x68\x7a", "\x74\x68\x7a", "\xce\xbc\x6c", "\x6d\x6c", "\x64\x6c", + "\x6b\x6c", "\x66\x6d", "\x6e\x6d", "\xce\xbc\x6d", "\x6d\x6d", "\x63\x6d", "\x6b\x6d", "\x6d\x6d\x32", + "\x63\x6d\x32", "\x6d\x32", "\x6b\x6d\x32", "\x6d\x6d\x33", "\x63\x6d\x33", "\x6d\x33", "\x6b\x6d\x33", "\x6d\xe2\x88\x95\x73", + "\x6d\xe2\x88\x95\x73\x32", "\x70\x61", "\x6b\x70\x61", "\x6d\x70\x61", "\x67\x70\x61", "\x72\x61\x64", "\x72\x61\x64\xe2\x88\x95\x73", "\x72\x61\x64\xe2\x88\x95\x73\x32", + "\x70\x73", "\x6e\x73", "\xce\xbc\x73", "\x6d\x73", "\x70\x76", "\x6e\x76", "\xce\xbc\x76", "\x6d\x76", + "\x6b\x76", "\x6d\x76", "\x70\x77", "\x6e\x77", "\xce\xbc\x77", "\x6d\x77", "\x6b\x77", "\x6d\x77" +}; + +static const char *grn_nfkc50_decompose_table_e38f[] = { + "\x6b\xce\xa9", "\x6d\xce\xa9", "\x61\x2e\x6d\x2e", "\x62\x71", "\x63\x63", "\x63\x64", "\x63\xe2\x88\x95\x6b\x67", "\x63\x6f\x2e", + "\x64\x62", "\x67\x79", "\x68\x61", "\x68\x70", "\x69\x6e", "\x6b\x6b", "\x6b\x6d", "\x6b\x74", + "\x6c\x6d", "\x6c\x6e", "\x6c\x6f\x67", "\x6c\x78", "\x6d\x62", "\x6d\x69\x6c", "\x6d\x6f\x6c", "\x70\x68", + "\x70\x2e\x6d\x2e", "\x70\x70\x6d", "\x70\x72", "\x73\x72", "\x73\x76", "\x77\x62", "\x76\xe2\x88\x95\x6d", "\x61\xe2\x88\x95\x6d", + "\x31\xe6\x97\xa5", "\x32\xe6\x97\xa5", "\x33\xe6\x97\xa5", "\x34\xe6\x97\xa5", "\x35\xe6\x97\xa5", "\x36\xe6\x97\xa5", "\x37\xe6\x97\xa5", "\x38\xe6\x97\xa5", + "\x39\xe6\x97\xa5", "\x31\x30\xe6\x97\xa5", "\x31\x31\xe6\x97\xa5", "\x31\x32\xe6\x97\xa5", "\x31\x33\xe6\x97\xa5", "\x31\x34\xe6\x97\xa5", "\x31\x35\xe6\x97\xa5", "\x31\x36\xe6\x97\xa5", + "\x31\x37\xe6\x97\xa5", "\x31\x38\xe6\x97\xa5", "\x31\x39\xe6\x97\xa5", "\x32\x30\xe6\x97\xa5", "\x32\x31\xe6\x97\xa5", "\x32\x32\xe6\x97\xa5", "\x32\x33\xe6\x97\xa5", "\x32\x34\xe6\x97\xa5", + "\x32\x35\xe6\x97\xa5", "\x32\x36\xe6\x97\xa5", "\x32\x37\xe6\x97\xa5", "\x32\x38\xe6\x97\xa5", "\x32\x39\xe6\x97\xa5", "\x33\x30\xe6\x97\xa5", "\x33\x31\xe6\x97\xa5", "\x67\x61\x6c" +}; + +static const char *grn_nfkc50_decompose_table_efa4[] = { + "\xe8\xb1\x88", "\xe6\x9b\xb4", "\xe8\xbb\x8a", "\xe8\xb3\x88", "\xe6\xbb\x91", "\xe4\xb8\xb2", "\xe5\x8f\xa5", "\xe9\xbe\x9c", + "\xe9\xbe\x9c", "\xe5\xa5\x91", "\xe9\x87\x91", "\xe5\x96\x87", "\xe5\xa5\x88", "\xe6\x87\xb6", "\xe7\x99\xa9", "\xe7\xbe\x85", + "\xe8\x98\xbf", "\xe8\x9e\xba", "\xe8\xa3\xb8", "\xe9\x82\x8f", "\xe6\xa8\x82", "\xe6\xb4\x9b", "\xe7\x83\x99", "\xe7\x8f\x9e", + "\xe8\x90\xbd", "\xe9\x85\xaa", "\xe9\xa7\xb1", "\xe4\xba\x82", "\xe5\x8d\xb5", "\xe6\xac\x84", "\xe7\x88\x9b", "\xe8\x98\xad", + "\xe9\xb8\x9e", "\xe5\xb5\x90", "\xe6\xbf\xab", "\xe8\x97\x8d", "\xe8\xa5\xa4", "\xe6\x8b\x89", "\xe8\x87\x98", "\xe8\xa0\x9f", + "\xe5\xbb\x8a", "\xe6\x9c\x97", "\xe6\xb5\xaa", "\xe7\x8b\xbc", "\xe9\x83\x8e", "\xe4\xbe\x86", "\xe5\x86\xb7", "\xe5\x8b\x9e", + "\xe6\x93\x84", "\xe6\xab\x93", "\xe7\x88\x90", "\xe7\x9b\xa7", "\xe8\x80\x81", "\xe8\x98\x86", "\xe8\x99\x9c", "\xe8\xb7\xaf", + "\xe9\x9c\xb2", "\xe9\xad\xaf", "\xe9\xb7\xba", "\xe7\xa2\x8c", "\xe7\xa5\xbf", "\xe7\xb6\xa0", "\xe8\x8f\x89", "\xe9\x8c\x84" +}; + +static const char *grn_nfkc50_decompose_table_efa5[] = { + "\xe9\xb9\xbf", "\xe8\xab\x96", "\xe5\xa3\x9f", "\xe5\xbc\x84", "\xe7\xb1\xa0", "\xe8\x81\xbe", "\xe7\x89\xa2", "\xe7\xa3\x8a", + "\xe8\xb3\x82", "\xe9\x9b\xb7", "\xe5\xa3\x98", "\xe5\xb1\xa2", "\xe6\xa8\x93", "\xe6\xb7\x9a", "\xe6\xbc\x8f", "\xe7\xb4\xaf", + "\xe7\xb8\xb7", "\xe9\x99\x8b", "\xe5\x8b\x92", "\xe8\x82\x8b", "\xe5\x87\x9c", "\xe5\x87\x8c", "\xe7\xa8\x9c", "\xe7\xb6\xbe", + "\xe8\x8f\xb1", "\xe9\x99\xb5", "\xe8\xae\x80", "\xe6\x8b\x8f", "\xe6\xa8\x82", "\xe8\xab\xbe", "\xe4\xb8\xb9", "\xe5\xaf\xa7", + "\xe6\x80\x92", "\xe7\x8e\x87", "\xe7\x95\xb0", "\xe5\x8c\x97", "\xe7\xa3\xbb", "\xe4\xbe\xbf", "\xe5\xbe\xa9", "\xe4\xb8\x8d", + "\xe6\xb3\x8c", "\xe6\x95\xb8", "\xe7\xb4\xa2", "\xe5\x8f\x83", "\xe5\xa1\x9e", "\xe7\x9c\x81", "\xe8\x91\x89", "\xe8\xaa\xaa", + "\xe6\xae\xba", "\xe8\xbe\xb0", "\xe6\xb2\x88", "\xe6\x8b\xbe", "\xe8\x8b\xa5", "\xe6\x8e\xa0", "\xe7\x95\xa5", "\xe4\xba\xae", + "\xe5\x85\xa9", "\xe5\x87\x89", "\xe6\xa2\x81", "\xe7\xb3\xa7", "\xe8\x89\xaf", "\xe8\xab\x92", "\xe9\x87\x8f", "\xe5\x8b\xb5" +}; + +static const char *grn_nfkc50_decompose_table_efa6[] = { + "\xe5\x91\x82", "\xe5\xa5\xb3", "\xe5\xbb\xac", "\xe6\x97\x85", "\xe6\xbf\xbe", "\xe7\xa4\xaa", "\xe9\x96\xad", "\xe9\xa9\xaa", + "\xe9\xba\x97", "\xe9\xbb\x8e", "\xe5\x8a\x9b", "\xe6\x9b\x86", "\xe6\xad\xb7", "\xe8\xbd\xa2", "\xe5\xb9\xb4", "\xe6\x86\x90", + "\xe6\x88\x80", "\xe6\x92\x9a", "\xe6\xbc\xa3", "\xe7\x85\x89", "\xe7\x92\x89", "\xe7\xa7\x8a", "\xe7\xb7\xb4", "\xe8\x81\xaf", + "\xe8\xbc\xa6", "\xe8\x93\xae", "\xe9\x80\xa3", "\xe9\x8d\x8a", "\xe5\x88\x97", "\xe5\x8a\xa3", "\xe5\x92\xbd", "\xe7\x83\x88", + "\xe8\xa3\x82", "\xe8\xaa\xaa", "\xe5\xbb\x89", "\xe5\xbf\xb5", "\xe6\x8d\xbb", "\xe6\xae\xae", "\xe7\xb0\xbe", "\xe7\x8d\xb5", + "\xe4\xbb\xa4", "\xe5\x9b\xb9", "\xe5\xaf\xa7", "\xe5\xb6\xba", "\xe6\x80\x9c", "\xe7\x8e\xb2", "\xe7\x91\xa9", "\xe7\xbe\x9a", + "\xe8\x81\x86", "\xe9\x88\xb4", "\xe9\x9b\xb6", "\xe9\x9d\x88", "\xe9\xa0\x98", "\xe4\xbe\x8b", "\xe7\xa6\xae", "\xe9\x86\xb4", + "\xe9\x9a\xb8", "\xe6\x83\xa1", "\xe4\xba\x86", "\xe5\x83\x9a", "\xe5\xaf\xae", "\xe5\xb0\xbf", "\xe6\x96\x99", "\xe6\xa8\x82" +}; + +static const char *grn_nfkc50_decompose_table_efa7[] = { + "\xe7\x87\x8e", "\xe7\x99\x82", "\xe8\x93\xbc", "\xe9\x81\xbc", "\xe9\xbe\x8d", "\xe6\x9a\x88", "\xe9\x98\xae", "\xe5\x8a\x89", + "\xe6\x9d\xbb", "\xe6\x9f\xb3", "\xe6\xb5\x81", "\xe6\xba\x9c", "\xe7\x90\x89", "\xe7\x95\x99", "\xe7\xa1\xab", "\xe7\xb4\x90", + "\xe9\xa1\x9e", "\xe5\x85\xad", "\xe6\x88\xae", "\xe9\x99\xb8", "\xe5\x80\xab", "\xe5\xb4\x99", "\xe6\xb7\xaa", "\xe8\xbc\xaa", + "\xe5\xbe\x8b", "\xe6\x85\x84", "\xe6\xa0\x97", "\xe7\x8e\x87", "\xe9\x9a\x86", "\xe5\x88\xa9", "\xe5\x90\x8f", "\xe5\xb1\xa5", + "\xe6\x98\x93", "\xe6\x9d\x8e", "\xe6\xa2\xa8", "\xe6\xb3\xa5", "\xe7\x90\x86", "\xe7\x97\xa2", "\xe7\xbd\xb9", "\xe8\xa3\x8f", + "\xe8\xa3\xa1", "\xe9\x87\x8c", "\xe9\x9b\xa2", "\xe5\x8c\xbf", "\xe6\xba\xba", "\xe5\x90\x9d", "\xe7\x87\x90", "\xe7\x92\x98", + "\xe8\x97\xba", "\xe9\x9a\xa3", "\xe9\xb1\x97", "\xe9\xba\x9f", "\xe6\x9e\x97", "\xe6\xb7\x8b", "\xe8\x87\xa8", "\xe7\xab\x8b", + "\xe7\xac\xa0", "\xe7\xb2\x92", "\xe7\x8b\x80", "\xe7\x82\x99", "\xe8\xad\x98", "\xe4\xbb\x80", "\xe8\x8c\xb6", "\xe5\x88\xba" +}; + +static const char *grn_nfkc50_decompose_table_efa8[] = { + "\xe5\x88\x87", "\xe5\xba\xa6", "\xe6\x8b\x93", "\xe7\xb3\x96", "\xe5\xae\x85", "\xe6\xb4\x9e", "\xe6\x9a\xb4", "\xe8\xbc\xbb", + "\xe8\xa1\x8c", "\xe9\x99\x8d", "\xe8\xa6\x8b", "\xe5\xbb\x93", "\xe5\x85\x80", "\xe5\x97\x80", NULL, NULL, + "\xe5\xa1\x9a", NULL, "\xe6\x99\xb4", NULL, NULL, "\xe5\x87\x9e", "\xe7\x8c\xaa", "\xe7\x9b\x8a", + "\xe7\xa4\xbc", "\xe7\xa5\x9e", "\xe7\xa5\xa5", "\xe7\xa6\x8f", "\xe9\x9d\x96", "\xe7\xb2\xbe", "\xe7\xbe\xbd", NULL, + "\xe8\x98\x92", NULL, "\xe8\xab\xb8", NULL, NULL, "\xe9\x80\xb8", "\xe9\x83\xbd", NULL, + NULL, NULL, "\xe9\xa3\xaf", "\xe9\xa3\xbc", "\xe9\xa4\xa8", "\xe9\xb6\xb4", NULL, NULL, + "\xe4\xbe\xae", "\xe5\x83\xa7", "\xe5\x85\x8d", "\xe5\x8b\x89", "\xe5\x8b\xa4", "\xe5\x8d\x91", "\xe5\x96\x9d", "\xe5\x98\x86", + "\xe5\x99\xa8", "\xe5\xa1\x80", "\xe5\xa2\xa8", "\xe5\xb1\xa4", "\xe5\xb1\xae", "\xe6\x82\x94", "\xe6\x85\xa8", "\xe6\x86\x8e" +}; + +static const char *grn_nfkc50_decompose_table_efa9[] = { + "\xe6\x87\xb2", "\xe6\x95\x8f", "\xe6\x97\xa2", "\xe6\x9a\x91", "\xe6\xa2\x85", "\xe6\xb5\xb7", "\xe6\xb8\x9a", "\xe6\xbc\xa2", + "\xe7\x85\xae", "\xe7\x88\xab", "\xe7\x90\xa2", "\xe7\xa2\x91", "\xe7\xa4\xbe", "\xe7\xa5\x89", "\xe7\xa5\x88", "\xe7\xa5\x90", + "\xe7\xa5\x96", "\xe7\xa5\x9d", "\xe7\xa6\x8d", "\xe7\xa6\x8e", "\xe7\xa9\x80", "\xe7\xaa\x81", "\xe7\xaf\x80", "\xe7\xb7\xb4", + "\xe7\xb8\x89", "\xe7\xb9\x81", "\xe7\xbd\xb2", "\xe8\x80\x85", "\xe8\x87\xad", "\xe8\x89\xb9", "\xe8\x89\xb9", "\xe8\x91\x97", + "\xe8\xa4\x90", "\xe8\xa6\x96", "\xe8\xac\x81", "\xe8\xac\xb9", "\xe8\xb3\x93", "\xe8\xb4\x88", "\xe8\xbe\xb6", "\xe9\x80\xb8", + "\xe9\x9b\xa3", "\xe9\x9f\xbf", "\xe9\xa0\xbb", NULL, NULL, NULL, NULL, NULL, + "\xe4\xb8\xa6", "\xe5\x86\xb5", "\xe5\x85\xa8", "\xe4\xbe\x80", "\xe5\x85\x85", "\xe5\x86\x80", "\xe5\x8b\x87", "\xe5\x8b\xba", + "\xe5\x96\x9d", "\xe5\x95\x95", "\xe5\x96\x99", "\xe5\x97\xa2", "\xe5\xa1\x9a", "\xe5\xa2\xb3", "\xe5\xa5\x84", "\xe5\xa5\x94" +}; + +static const char *grn_nfkc50_decompose_table_efaa[] = { + "\xe5\xa9\xa2", "\xe5\xac\xa8", "\xe5\xbb\x92", "\xe5\xbb\x99", "\xe5\xbd\xa9", "\xe5\xbe\xad", "\xe6\x83\x98", "\xe6\x85\x8e", + "\xe6\x84\x88", "\xe6\x86\x8e", "\xe6\x85\xa0", "\xe6\x87\xb2", "\xe6\x88\xb4", "\xe6\x8f\x84", "\xe6\x90\x9c", "\xe6\x91\x92", + "\xe6\x95\x96", "\xe6\x99\xb4", "\xe6\x9c\x97", "\xe6\x9c\x9b", "\xe6\x9d\x96", "\xe6\xad\xb9", "\xe6\xae\xba", "\xe6\xb5\x81", + "\xe6\xbb\x9b", "\xe6\xbb\x8b", "\xe6\xbc\xa2", "\xe7\x80\x9e", "\xe7\x85\xae", "\xe7\x9e\xa7", "\xe7\x88\xb5", "\xe7\x8a\xaf", + "\xe7\x8c\xaa", "\xe7\x91\xb1", "\xe7\x94\x86", "\xe7\x94\xbb", "\xe7\x98\x9d", "\xe7\x98\x9f", "\xe7\x9b\x8a", "\xe7\x9b\x9b", + "\xe7\x9b\xb4", "\xe7\x9d\x8a", "\xe7\x9d\x80", "\xe7\xa3\x8c", "\xe7\xaa\xb1", "\xe7\xaf\x80", "\xe7\xb1\xbb", "\xe7\xb5\x9b", + "\xe7\xb7\xb4", "\xe7\xbc\xbe", "\xe8\x80\x85", "\xe8\x8d\x92", "\xe8\x8f\xaf", "\xe8\x9d\xb9", "\xe8\xa5\x81", "\xe8\xa6\x86", + "\xe8\xa6\x96", "\xe8\xaa\xbf", "\xe8\xab\xb8", "\xe8\xab\x8b", "\xe8\xac\x81", "\xe8\xab\xbe", "\xe8\xab\xad", "\xe8\xac\xb9" +}; + +static const char *grn_nfkc50_decompose_table_efab[] = { + "\xe8\xae\x8a", "\xe8\xb4\x88", "\xe8\xbc\xb8", "\xe9\x81\xb2", "\xe9\x86\x99", "\xe9\x89\xb6", "\xe9\x99\xbc", "\xe9\x9b\xa3", + "\xe9\x9d\x96", "\xe9\x9f\x9b", "\xe9\x9f\xbf", "\xe9\xa0\x8b", "\xe9\xa0\xbb", "\xe9\xac\x92", "\xe9\xbe\x9c", "\xf0\xa2\xa1\x8a", + "\xf0\xa2\xa1\x84", "\xf0\xa3\x8f\x95", "\xe3\xae\x9d", "\xe4\x80\x98", "\xe4\x80\xb9", "\xf0\xa5\x89\x89", "\xf0\xa5\xb3\x90", "\xf0\xa7\xbb\x93", + "\xe9\xbd\x83", "\xe9\xbe\x8e" +}; + +static const char *grn_nfkc50_decompose_table_efac[] = { + "\x66\x66", "\x66\x69", "\x66\x6c", "\x66\x66\x69", "\x66\x66\x6c", "\x73\x74", "\x73\x74", NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "\xd5\xb4\xd5\xb6", "\xd5\xb4\xd5\xa5", "\xd5\xb4\xd5\xab", "\xd5\xbe\xd5\xb6", "\xd5\xb4\xd5\xad", + NULL, NULL, NULL, NULL, NULL, "\xd7\x99\xd6\xb4", NULL, "\xd7\xb2\xd6\xb7", + "\xd7\xa2", "\xd7\x90", "\xd7\x93", "\xd7\x94", "\xd7\x9b", "\xd7\x9c", "\xd7\x9d", "\xd7\xa8", + "\xd7\xaa", "\x2b", "\xd7\xa9\xd7\x81", "\xd7\xa9\xd7\x82", "\xd7\xa9\xd6\xbc\xd7\x81", "\xd7\xa9\xd6\xbc\xd7\x82", "\xd7\x90\xd6\xb7", "\xd7\x90\xd6\xb8", + "\xd7\x90\xd6\xbc", "\xd7\x91\xd6\xbc", "\xd7\x92\xd6\xbc", "\xd7\x93\xd6\xbc", "\xd7\x94\xd6\xbc", "\xd7\x95\xd6\xbc", "\xd7\x96\xd6\xbc", NULL, + "\xd7\x98\xd6\xbc", "\xd7\x99\xd6\xbc", "\xd7\x9a\xd6\xbc", "\xd7\x9b\xd6\xbc", "\xd7\x9c\xd6\xbc", NULL, "\xd7\x9e\xd6\xbc" +}; + +static const char *grn_nfkc50_decompose_table_efad[] = { + "\xd7\xa0\xd6\xbc", "\xd7\xa1\xd6\xbc", NULL, "\xd7\xa3\xd6\xbc", "\xd7\xa4\xd6\xbc", NULL, "\xd7\xa6\xd6\xbc", "\xd7\xa7\xd6\xbc", + "\xd7\xa8\xd6\xbc", "\xd7\xa9\xd6\xbc", "\xd7\xaa\xd6\xbc", "\xd7\x95\xd6\xb9", "\xd7\x91\xd6\xbf", "\xd7\x9b\xd6\xbf", "\xd7\xa4\xd6\xbf", "\xd7\x90\xd7\x9c", + "\xd9\xb1", "\xd9\xb1", "\xd9\xbb", "\xd9\xbb", "\xd9\xbb", "\xd9\xbb", "\xd9\xbe", "\xd9\xbe", + "\xd9\xbe", "\xd9\xbe", "\xda\x80", "\xda\x80", "\xda\x80", "\xda\x80", "\xd9\xba", "\xd9\xba", + "\xd9\xba", "\xd9\xba", "\xd9\xbf", "\xd9\xbf", "\xd9\xbf", "\xd9\xbf", "\xd9\xb9", "\xd9\xb9", + "\xd9\xb9", "\xd9\xb9", "\xda\xa4", "\xda\xa4", "\xda\xa4", "\xda\xa4", "\xda\xa6", "\xda\xa6", + "\xda\xa6", "\xda\xa6", "\xda\x84", "\xda\x84", "\xda\x84", "\xda\x84", "\xda\x83", "\xda\x83", + "\xda\x83", "\xda\x83", "\xda\x86", "\xda\x86", "\xda\x86", "\xda\x86", "\xda\x87", "\xda\x87" +}; + +static const char *grn_nfkc50_decompose_table_efae[] = { + "\xda\x87", "\xda\x87", "\xda\x8d", "\xda\x8d", "\xda\x8c", "\xda\x8c", "\xda\x8e", "\xda\x8e", + "\xda\x88", "\xda\x88", "\xda\x98", "\xda\x98", "\xda\x91", "\xda\x91", "\xda\xa9", "\xda\xa9", + "\xda\xa9", "\xda\xa9", "\xda\xaf", "\xda\xaf", "\xda\xaf", "\xda\xaf", "\xda\xb3", "\xda\xb3", + "\xda\xb3", "\xda\xb3", "\xda\xb1", "\xda\xb1", "\xda\xb1", "\xda\xb1", "\xda\xba", "\xda\xba", + "\xda\xbb", "\xda\xbb", "\xda\xbb", "\xda\xbb", "\xdb\x80", "\xdb\x80", "\xdb\x81", "\xdb\x81", + "\xdb\x81", "\xdb\x81", "\xda\xbe", "\xda\xbe", "\xda\xbe", "\xda\xbe", "\xdb\x92", "\xdb\x92", + "\xdb\x93", "\xdb\x93" +}; + +static const char *grn_nfkc50_decompose_table_efaf[] = { + "\xda\xad", "\xda\xad", "\xda\xad", "\xda\xad", "\xdb\x87", "\xdb\x87", "\xdb\x86", "\xdb\x86", + "\xdb\x88", "\xdb\x88", "\xdb\x87\xd9\xb4", "\xdb\x8b", "\xdb\x8b", "\xdb\x85", "\xdb\x85", "\xdb\x89", + "\xdb\x89", "\xdb\x90", "\xdb\x90", "\xdb\x90", "\xdb\x90", "\xd9\x89", "\xd9\x89", "\xd8\xa6\xd8\xa7", + "\xd8\xa6\xd8\xa7", "\xd8\xa6\xdb\x95", "\xd8\xa6\xdb\x95", "\xd8\xa6\xd9\x88", "\xd8\xa6\xd9\x88", "\xd8\xa6\xdb\x87", "\xd8\xa6\xdb\x87", "\xd8\xa6\xdb\x86", + "\xd8\xa6\xdb\x86", "\xd8\xa6\xdb\x88", "\xd8\xa6\xdb\x88", "\xd8\xa6\xdb\x90", "\xd8\xa6\xdb\x90", "\xd8\xa6\xdb\x90", "\xd8\xa6\xd9\x89", "\xd8\xa6\xd9\x89", + "\xd8\xa6\xd9\x89", "\xdb\x8c", "\xdb\x8c", "\xdb\x8c", "\xdb\x8c" +}; + +static const char *grn_nfkc50_decompose_table_efb0[] = { + "\xd8\xa6\xd8\xac", "\xd8\xa6\xd8\xad", "\xd8\xa6\xd9\x85", "\xd8\xa6\xd9\x89", "\xd8\xa6\xd9\x8a", "\xd8\xa8\xd8\xac", "\xd8\xa8\xd8\xad", "\xd8\xa8\xd8\xae", + "\xd8\xa8\xd9\x85", "\xd8\xa8\xd9\x89", "\xd8\xa8\xd9\x8a", "\xd8\xaa\xd8\xac", "\xd8\xaa\xd8\xad", "\xd8\xaa\xd8\xae", "\xd8\xaa\xd9\x85", "\xd8\xaa\xd9\x89", + "\xd8\xaa\xd9\x8a", "\xd8\xab\xd8\xac", "\xd8\xab\xd9\x85", "\xd8\xab\xd9\x89", "\xd8\xab\xd9\x8a", "\xd8\xac\xd8\xad", "\xd8\xac\xd9\x85", "\xd8\xad\xd8\xac", + "\xd8\xad\xd9\x85", "\xd8\xae\xd8\xac", "\xd8\xae\xd8\xad", "\xd8\xae\xd9\x85", "\xd8\xb3\xd8\xac", "\xd8\xb3\xd8\xad", "\xd8\xb3\xd8\xae", "\xd8\xb3\xd9\x85", + "\xd8\xb5\xd8\xad", "\xd8\xb5\xd9\x85", "\xd8\xb6\xd8\xac", "\xd8\xb6\xd8\xad", "\xd8\xb6\xd8\xae", "\xd8\xb6\xd9\x85", "\xd8\xb7\xd8\xad", "\xd8\xb7\xd9\x85", + "\xd8\xb8\xd9\x85", "\xd8\xb9\xd8\xac", "\xd8\xb9\xd9\x85", "\xd8\xba\xd8\xac", "\xd8\xba\xd9\x85", "\xd9\x81\xd8\xac", "\xd9\x81\xd8\xad", "\xd9\x81\xd8\xae", + "\xd9\x81\xd9\x85", "\xd9\x81\xd9\x89", "\xd9\x81\xd9\x8a", "\xd9\x82\xd8\xad", "\xd9\x82\xd9\x85", "\xd9\x82\xd9\x89", "\xd9\x82\xd9\x8a", "\xd9\x83\xd8\xa7", + "\xd9\x83\xd8\xac", "\xd9\x83\xd8\xad", "\xd9\x83\xd8\xae", "\xd9\x83\xd9\x84", "\xd9\x83\xd9\x85", "\xd9\x83\xd9\x89", "\xd9\x83\xd9\x8a", "\xd9\x84\xd8\xac" +}; + +static const char *grn_nfkc50_decompose_table_efb1[] = { + "\xd9\x84\xd8\xad", "\xd9\x84\xd8\xae", "\xd9\x84\xd9\x85", "\xd9\x84\xd9\x89", "\xd9\x84\xd9\x8a", "\xd9\x85\xd8\xac", "\xd9\x85\xd8\xad", "\xd9\x85\xd8\xae", + "\xd9\x85\xd9\x85", "\xd9\x85\xd9\x89", "\xd9\x85\xd9\x8a", "\xd9\x86\xd8\xac", "\xd9\x86\xd8\xad", "\xd9\x86\xd8\xae", "\xd9\x86\xd9\x85", "\xd9\x86\xd9\x89", + "\xd9\x86\xd9\x8a", "\xd9\x87\xd8\xac", "\xd9\x87\xd9\x85", "\xd9\x87\xd9\x89", "\xd9\x87\xd9\x8a", "\xd9\x8a\xd8\xac", "\xd9\x8a\xd8\xad", "\xd9\x8a\xd8\xae", + "\xd9\x8a\xd9\x85", "\xd9\x8a\xd9\x89", "\xd9\x8a\xd9\x8a", "\xd8\xb0\xd9\xb0", "\xd8\xb1\xd9\xb0", "\xd9\x89\xd9\xb0", "\xd9\x8c\xd9\x91", "\xd9\x8d\xd9\x91", + "\xd9\x8e\xd9\x91", "\xd9\x8f\xd9\x91", "\xd9\x90\xd9\x91", "\xd9\x91\xd9\xb0", "\xd8\xa6\xd8\xb1", "\xd8\xa6\xd8\xb2", "\xd8\xa6\xd9\x85", "\xd8\xa6\xd9\x86", + "\xd8\xa6\xd9\x89", "\xd8\xa6\xd9\x8a", "\xd8\xa8\xd8\xb1", "\xd8\xa8\xd8\xb2", "\xd8\xa8\xd9\x85", "\xd8\xa8\xd9\x86", "\xd8\xa8\xd9\x89", "\xd8\xa8\xd9\x8a", + "\xd8\xaa\xd8\xb1", "\xd8\xaa\xd8\xb2", "\xd8\xaa\xd9\x85", "\xd8\xaa\xd9\x86", "\xd8\xaa\xd9\x89", "\xd8\xaa\xd9\x8a", "\xd8\xab\xd8\xb1", "\xd8\xab\xd8\xb2", + "\xd8\xab\xd9\x85", "\xd8\xab\xd9\x86", "\xd8\xab\xd9\x89", "\xd8\xab\xd9\x8a", "\xd9\x81\xd9\x89", "\xd9\x81\xd9\x8a", "\xd9\x82\xd9\x89", "\xd9\x82\xd9\x8a" +}; + +static const char *grn_nfkc50_decompose_table_efb2[] = { + "\xd9\x83\xd8\xa7", "\xd9\x83\xd9\x84", "\xd9\x83\xd9\x85", "\xd9\x83\xd9\x89", "\xd9\x83\xd9\x8a", "\xd9\x84\xd9\x85", "\xd9\x84\xd9\x89", "\xd9\x84\xd9\x8a", + "\xd9\x85\xd8\xa7", "\xd9\x85\xd9\x85", "\xd9\x86\xd8\xb1", "\xd9\x86\xd8\xb2", "\xd9\x86\xd9\x85", "\xd9\x86\xd9\x86", "\xd9\x86\xd9\x89", "\xd9\x86\xd9\x8a", + "\xd9\x89\xd9\xb0", "\xd9\x8a\xd8\xb1", "\xd9\x8a\xd8\xb2", "\xd9\x8a\xd9\x85", "\xd9\x8a\xd9\x86", "\xd9\x8a\xd9\x89", "\xd9\x8a\xd9\x8a", "\xd8\xa6\xd8\xac", + "\xd8\xa6\xd8\xad", "\xd8\xa6\xd8\xae", "\xd8\xa6\xd9\x85", "\xd8\xa6\xd9\x87", "\xd8\xa8\xd8\xac", "\xd8\xa8\xd8\xad", "\xd8\xa8\xd8\xae", "\xd8\xa8\xd9\x85", + "\xd8\xa8\xd9\x87", "\xd8\xaa\xd8\xac", "\xd8\xaa\xd8\xad", "\xd8\xaa\xd8\xae", "\xd8\xaa\xd9\x85", "\xd8\xaa\xd9\x87", "\xd8\xab\xd9\x85", "\xd8\xac\xd8\xad", + "\xd8\xac\xd9\x85", "\xd8\xad\xd8\xac", "\xd8\xad\xd9\x85", "\xd8\xae\xd8\xac", "\xd8\xae\xd9\x85", "\xd8\xb3\xd8\xac", "\xd8\xb3\xd8\xad", "\xd8\xb3\xd8\xae", + "\xd8\xb3\xd9\x85", "\xd8\xb5\xd8\xad", "\xd8\xb5\xd8\xae", "\xd8\xb5\xd9\x85", "\xd8\xb6\xd8\xac", "\xd8\xb6\xd8\xad", "\xd8\xb6\xd8\xae", "\xd8\xb6\xd9\x85", + "\xd8\xb7\xd8\xad", "\xd8\xb8\xd9\x85", "\xd8\xb9\xd8\xac", "\xd8\xb9\xd9\x85", "\xd8\xba\xd8\xac", "\xd8\xba\xd9\x85", "\xd9\x81\xd8\xac", "\xd9\x81\xd8\xad" +}; + +static const char *grn_nfkc50_decompose_table_efb3[] = { + "\xd9\x81\xd8\xae", "\xd9\x81\xd9\x85", "\xd9\x82\xd8\xad", "\xd9\x82\xd9\x85", "\xd9\x83\xd8\xac", "\xd9\x83\xd8\xad", "\xd9\x83\xd8\xae", "\xd9\x83\xd9\x84", + "\xd9\x83\xd9\x85", "\xd9\x84\xd8\xac", "\xd9\x84\xd8\xad", "\xd9\x84\xd8\xae", "\xd9\x84\xd9\x85", "\xd9\x84\xd9\x87", "\xd9\x85\xd8\xac", "\xd9\x85\xd8\xad", + "\xd9\x85\xd8\xae", "\xd9\x85\xd9\x85", "\xd9\x86\xd8\xac", "\xd9\x86\xd8\xad", "\xd9\x86\xd8\xae", "\xd9\x86\xd9\x85", "\xd9\x86\xd9\x87", "\xd9\x87\xd8\xac", + "\xd9\x87\xd9\x85", "\xd9\x87\xd9\xb0", "\xd9\x8a\xd8\xac", "\xd9\x8a\xd8\xad", "\xd9\x8a\xd8\xae", "\xd9\x8a\xd9\x85", "\xd9\x8a\xd9\x87", "\xd8\xa6\xd9\x85", + "\xd8\xa6\xd9\x87", "\xd8\xa8\xd9\x85", "\xd8\xa8\xd9\x87", "\xd8\xaa\xd9\x85", "\xd8\xaa\xd9\x87", "\xd8\xab\xd9\x85", "\xd8\xab\xd9\x87", "\xd8\xb3\xd9\x85", + "\xd8\xb3\xd9\x87", "\xd8\xb4\xd9\x85", "\xd8\xb4\xd9\x87", "\xd9\x83\xd9\x84", "\xd9\x83\xd9\x85", "\xd9\x84\xd9\x85", "\xd9\x86\xd9\x85", "\xd9\x86\xd9\x87", + "\xd9\x8a\xd9\x85", "\xd9\x8a\xd9\x87", "\xd9\x80\xd9\x8e\xd9\x91", "\xd9\x80\xd9\x8f\xd9\x91", "\xd9\x80\xd9\x90\xd9\x91", "\xd8\xb7\xd9\x89", "\xd8\xb7\xd9\x8a", "\xd8\xb9\xd9\x89", + "\xd8\xb9\xd9\x8a", "\xd8\xba\xd9\x89", "\xd8\xba\xd9\x8a", "\xd8\xb3\xd9\x89", "\xd8\xb3\xd9\x8a", "\xd8\xb4\xd9\x89", "\xd8\xb4\xd9\x8a", "\xd8\xad\xd9\x89" +}; + +static const char *grn_nfkc50_decompose_table_efb4[] = { + "\xd8\xad\xd9\x8a", "\xd8\xac\xd9\x89", "\xd8\xac\xd9\x8a", "\xd8\xae\xd9\x89", "\xd8\xae\xd9\x8a", "\xd8\xb5\xd9\x89", "\xd8\xb5\xd9\x8a", "\xd8\xb6\xd9\x89", + "\xd8\xb6\xd9\x8a", "\xd8\xb4\xd8\xac", "\xd8\xb4\xd8\xad", "\xd8\xb4\xd8\xae", "\xd8\xb4\xd9\x85", "\xd8\xb4\xd8\xb1", "\xd8\xb3\xd8\xb1", "\xd8\xb5\xd8\xb1", + "\xd8\xb6\xd8\xb1", "\xd8\xb7\xd9\x89", "\xd8\xb7\xd9\x8a", "\xd8\xb9\xd9\x89", "\xd8\xb9\xd9\x8a", "\xd8\xba\xd9\x89", "\xd8\xba\xd9\x8a", "\xd8\xb3\xd9\x89", + "\xd8\xb3\xd9\x8a", "\xd8\xb4\xd9\x89", "\xd8\xb4\xd9\x8a", "\xd8\xad\xd9\x89", "\xd8\xad\xd9\x8a", "\xd8\xac\xd9\x89", "\xd8\xac\xd9\x8a", "\xd8\xae\xd9\x89", + "\xd8\xae\xd9\x8a", "\xd8\xb5\xd9\x89", "\xd8\xb5\xd9\x8a", "\xd8\xb6\xd9\x89", "\xd8\xb6\xd9\x8a", "\xd8\xb4\xd8\xac", "\xd8\xb4\xd8\xad", "\xd8\xb4\xd8\xae", + "\xd8\xb4\xd9\x85", "\xd8\xb4\xd8\xb1", "\xd8\xb3\xd8\xb1", "\xd8\xb5\xd8\xb1", "\xd8\xb6\xd8\xb1", "\xd8\xb4\xd8\xac", "\xd8\xb4\xd8\xad", "\xd8\xb4\xd8\xae", + "\xd8\xb4\xd9\x85", "\xd8\xb3\xd9\x87", "\xd8\xb4\xd9\x87", "\xd8\xb7\xd9\x85", "\xd8\xb3\xd8\xac", "\xd8\xb3\xd8\xad", "\xd8\xb3\xd8\xae", "\xd8\xb4\xd8\xac", + "\xd8\xb4\xd8\xad", "\xd8\xb4\xd8\xae", "\xd8\xb7\xd9\x85", "\xd8\xb8\xd9\x85", "\xd8\xa7\xd9\x8b", "\xd8\xa7\xd9\x8b" +}; + +static const char *grn_nfkc50_decompose_table_efb5[] = { + "\xd8\xaa\xd8\xac\xd9\x85", "\xd8\xaa\xd8\xad\xd8\xac", "\xd8\xaa\xd8\xad\xd8\xac", "\xd8\xaa\xd8\xad\xd9\x85", "\xd8\xaa\xd8\xae\xd9\x85", "\xd8\xaa\xd9\x85\xd8\xac", "\xd8\xaa\xd9\x85\xd8\xad", "\xd8\xaa\xd9\x85\xd8\xae", + "\xd8\xac\xd9\x85\xd8\xad", "\xd8\xac\xd9\x85\xd8\xad", "\xd8\xad\xd9\x85\xd9\x8a", "\xd8\xad\xd9\x85\xd9\x89", "\xd8\xb3\xd8\xad\xd8\xac", "\xd8\xb3\xd8\xac\xd8\xad", "\xd8\xb3\xd8\xac\xd9\x89", "\xd8\xb3\xd9\x85\xd8\xad", + "\xd8\xb3\xd9\x85\xd8\xad", "\xd8\xb3\xd9\x85\xd8\xac", "\xd8\xb3\xd9\x85\xd9\x85", "\xd8\xb3\xd9\x85\xd9\x85", "\xd8\xb5\xd8\xad\xd8\xad", "\xd8\xb5\xd8\xad\xd8\xad", "\xd8\xb5\xd9\x85\xd9\x85", "\xd8\xb4\xd8\xad\xd9\x85", + "\xd8\xb4\xd8\xad\xd9\x85", "\xd8\xb4\xd8\xac\xd9\x8a", "\xd8\xb4\xd9\x85\xd8\xae", "\xd8\xb4\xd9\x85\xd8\xae", "\xd8\xb4\xd9\x85\xd9\x85", "\xd8\xb4\xd9\x85\xd9\x85", "\xd8\xb6\xd8\xad\xd9\x89", "\xd8\xb6\xd8\xae\xd9\x85", + "\xd8\xb6\xd8\xae\xd9\x85", "\xd8\xb7\xd9\x85\xd8\xad", "\xd8\xb7\xd9\x85\xd8\xad", "\xd8\xb7\xd9\x85\xd9\x85", "\xd8\xb7\xd9\x85\xd9\x8a", "\xd8\xb9\xd8\xac\xd9\x85", "\xd8\xb9\xd9\x85\xd9\x85", "\xd8\xb9\xd9\x85\xd9\x85", + "\xd8\xb9\xd9\x85\xd9\x89", "\xd8\xba\xd9\x85\xd9\x85", "\xd8\xba\xd9\x85\xd9\x8a", "\xd8\xba\xd9\x85\xd9\x89", "\xd9\x81\xd8\xae\xd9\x85", "\xd9\x81\xd8\xae\xd9\x85", "\xd9\x82\xd9\x85\xd8\xad", "\xd9\x82\xd9\x85\xd9\x85" +}; + +static const char *grn_nfkc50_decompose_table_efb6[] = { + "\xd9\x84\xd8\xad\xd9\x85", "\xd9\x84\xd8\xad\xd9\x8a", "\xd9\x84\xd8\xad\xd9\x89", "\xd9\x84\xd8\xac\xd8\xac", "\xd9\x84\xd8\xac\xd8\xac", "\xd9\x84\xd8\xae\xd9\x85", "\xd9\x84\xd8\xae\xd9\x85", "\xd9\x84\xd9\x85\xd8\xad", + "\xd9\x84\xd9\x85\xd8\xad", "\xd9\x85\xd8\xad\xd8\xac", "\xd9\x85\xd8\xad\xd9\x85", "\xd9\x85\xd8\xad\xd9\x8a", "\xd9\x85\xd8\xac\xd8\xad", "\xd9\x85\xd8\xac\xd9\x85", "\xd9\x85\xd8\xae\xd8\xac", "\xd9\x85\xd8\xae\xd9\x85", + NULL, NULL, "\xd9\x85\xd8\xac\xd8\xae", "\xd9\x87\xd9\x85\xd8\xac", "\xd9\x87\xd9\x85\xd9\x85", "\xd9\x86\xd8\xad\xd9\x85", "\xd9\x86\xd8\xad\xd9\x89", "\xd9\x86\xd8\xac\xd9\x85", + "\xd9\x86\xd8\xac\xd9\x85", "\xd9\x86\xd8\xac\xd9\x89", "\xd9\x86\xd9\x85\xd9\x8a", "\xd9\x86\xd9\x85\xd9\x89", "\xd9\x8a\xd9\x85\xd9\x85", "\xd9\x8a\xd9\x85\xd9\x85", "\xd8\xa8\xd8\xae\xd9\x8a", "\xd8\xaa\xd8\xac\xd9\x8a", + "\xd8\xaa\xd8\xac\xd9\x89", "\xd8\xaa\xd8\xae\xd9\x8a", "\xd8\xaa\xd8\xae\xd9\x89", "\xd8\xaa\xd9\x85\xd9\x8a", "\xd8\xaa\xd9\x85\xd9\x89", "\xd8\xac\xd9\x85\xd9\x8a", "\xd8\xac\xd8\xad\xd9\x89", "\xd8\xac\xd9\x85\xd9\x89", + "\xd8\xb3\xd8\xae\xd9\x89", "\xd8\xb5\xd8\xad\xd9\x8a", "\xd8\xb4\xd8\xad\xd9\x8a", "\xd8\xb6\xd8\xad\xd9\x8a", "\xd9\x84\xd8\xac\xd9\x8a", "\xd9\x84\xd9\x85\xd9\x8a", "\xd9\x8a\xd8\xad\xd9\x8a", "\xd9\x8a\xd8\xac\xd9\x8a", + "\xd9\x8a\xd9\x85\xd9\x8a", "\xd9\x85\xd9\x85\xd9\x8a", "\xd9\x82\xd9\x85\xd9\x8a", "\xd9\x86\xd8\xad\xd9\x8a", "\xd9\x82\xd9\x85\xd8\xad", "\xd9\x84\xd8\xad\xd9\x85", "\xd8\xb9\xd9\x85\xd9\x8a", "\xd9\x83\xd9\x85\xd9\x8a", + "\xd9\x86\xd8\xac\xd8\xad", "\xd9\x85\xd8\xae\xd9\x8a", "\xd9\x84\xd8\xac\xd9\x85", "\xd9\x83\xd9\x85\xd9\x85", "\xd9\x84\xd8\xac\xd9\x85", "\xd9\x86\xd8\xac\xd8\xad", "\xd8\xac\xd8\xad\xd9\x8a", "\xd8\xad\xd8\xac\xd9\x8a" +}; + +static const char *grn_nfkc50_decompose_table_efb7[] = { + "\xd9\x85\xd8\xac\xd9\x8a", "\xd9\x81\xd9\x85\xd9\x8a", "\xd8\xa8\xd8\xad\xd9\x8a", "\xd9\x83\xd9\x85\xd9\x85", "\xd8\xb9\xd8\xac\xd9\x85", "\xd8\xb5\xd9\x85\xd9\x85", "\xd8\xb3\xd8\xae\xd9\x8a", "\xd9\x86\xd8\xac\xd9\x8a", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xd8\xb5\xd9\x84\xdb\x92", "\xd9\x82\xd9\x84\xdb\x92", "\xd8\xa7\xd9\x84\xd9\x84\xd9\x87", "\xd8\xa7\xd9\x83\xd8\xa8\xd8\xb1", "\xd9\x85\xd8\xad\xd9\x85\xd8\xaf", "\xd8\xb5\xd9\x84\xd8\xb9\xd9\x85", "\xd8\xb1\xd8\xb3\xd9\x88\xd9\x84", "\xd8\xb9\xd9\x84\xd9\x8a\xd9\x87", + "\xd9\x88\xd8\xb3\xd9\x84\xd9\x85", "\xd8\xb5\xd9\x84\xd9\x89", "\xd8\xb5\xd9\x84\xd9\x89\x20\xd8\xa7\xd9\x84\xd9\x84\xd9\x87\x20\xd8\xb9\xd9\x84\xd9\x8a\xd9\x87\x20\xd9\x88\xd8\xb3\xd9\x84\xd9\x85", "\xd8\xac\xd9\x84\x20\xd8\xac\xd9\x84\xd8\xa7\xd9\x84\xd9\x87", "\xd8\xb1\xdb\x8c\xd8\xa7\xd9\x84" +}; + +static const char *grn_nfkc50_decompose_table_efb8[] = { + "\x2c", "\xe3\x80\x81", "\xe3\x80\x82", "\x3a", "\x3b", "\x21", "\x3f", "\xe3\x80\x96", + "\xe3\x80\x97", "\x2e\x2e\x2e", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\x2e\x2e", "\xe2\x80\x94", "\xe2\x80\x93", "\x5f", "\x5f", "\x28", "\x29", "\x7b", + "\x7d", "\xe3\x80\x94", "\xe3\x80\x95", "\xe3\x80\x90", "\xe3\x80\x91", "\xe3\x80\x8a", "\xe3\x80\x8b", "\xe3\x80\x88" +}; + +static const char *grn_nfkc50_decompose_table_efb9[] = { + "\xe3\x80\x89", "\xe3\x80\x8c", "\xe3\x80\x8d", "\xe3\x80\x8e", "\xe3\x80\x8f", NULL, NULL, "\x5b", + "\x5d", "\xcc\x85", "\xcc\x85", "\xcc\x85", "\xcc\x85", "\x5f", "\x5f", "\x5f", + "\x2c", "\xe3\x80\x81", "\x2e", NULL, "\x3b", "\x3a", "\x3f", "\x21", + "\xe2\x80\x94", "\x28", "\x29", "\x7b", "\x7d", "\xe3\x80\x94", "\xe3\x80\x95", "\x23", + "\x26", "\x2a", "\x2b", "\x2d", "\x3c", "\x3e", "\x3d", NULL, + "\x5c", "\x24", "\x25", "\x40", NULL, NULL, NULL, NULL, + "\xd9\x8b", "\xd9\x80\xd9\x8b", "\xd9\x8c", NULL, "\xd9\x8d", NULL, "\xd9\x8e", "\xd9\x80\xd9\x8e", + "\xd9\x8f", "\xd9\x80\xd9\x8f", "\xd9\x90", "\xd9\x80\xd9\x90", "\xd9\x91", "\xd9\x80\xd9\x91", "\xd9\x92", "\xd9\x80\xd9\x92" +}; + +static const char *grn_nfkc50_decompose_table_efba[] = { + "\xd8\xa1", "\xd8\xa2", "\xd8\xa2", "\xd8\xa3", "\xd8\xa3", "\xd8\xa4", "\xd8\xa4", "\xd8\xa5", + "\xd8\xa5", "\xd8\xa6", "\xd8\xa6", "\xd8\xa6", "\xd8\xa6", "\xd8\xa7", "\xd8\xa7", "\xd8\xa8", + "\xd8\xa8", "\xd8\xa8", "\xd8\xa8", "\xd8\xa9", "\xd8\xa9", "\xd8\xaa", "\xd8\xaa", "\xd8\xaa", + "\xd8\xaa", "\xd8\xab", "\xd8\xab", "\xd8\xab", "\xd8\xab", "\xd8\xac", "\xd8\xac", "\xd8\xac", + "\xd8\xac", "\xd8\xad", "\xd8\xad", "\xd8\xad", "\xd8\xad", "\xd8\xae", "\xd8\xae", "\xd8\xae", + "\xd8\xae", "\xd8\xaf", "\xd8\xaf", "\xd8\xb0", "\xd8\xb0", "\xd8\xb1", "\xd8\xb1", "\xd8\xb2", + "\xd8\xb2", "\xd8\xb3", "\xd8\xb3", "\xd8\xb3", "\xd8\xb3", "\xd8\xb4", "\xd8\xb4", "\xd8\xb4", + "\xd8\xb4", "\xd8\xb5", "\xd8\xb5", "\xd8\xb5", "\xd8\xb5", "\xd8\xb6", "\xd8\xb6", "\xd8\xb6" +}; + +static const char *grn_nfkc50_decompose_table_efbb[] = { + "\xd8\xb6", "\xd8\xb7", "\xd8\xb7", "\xd8\xb7", "\xd8\xb7", "\xd8\xb8", "\xd8\xb8", "\xd8\xb8", + "\xd8\xb8", "\xd8\xb9", "\xd8\xb9", "\xd8\xb9", "\xd8\xb9", "\xd8\xba", "\xd8\xba", "\xd8\xba", + "\xd8\xba", "\xd9\x81", "\xd9\x81", "\xd9\x81", "\xd9\x81", "\xd9\x82", "\xd9\x82", "\xd9\x82", + "\xd9\x82", "\xd9\x83", "\xd9\x83", "\xd9\x83", "\xd9\x83", "\xd9\x84", "\xd9\x84", "\xd9\x84", + "\xd9\x84", "\xd9\x85", "\xd9\x85", "\xd9\x85", "\xd9\x85", "\xd9\x86", "\xd9\x86", "\xd9\x86", + "\xd9\x86", "\xd9\x87", "\xd9\x87", "\xd9\x87", "\xd9\x87", "\xd9\x88", "\xd9\x88", "\xd9\x89", + "\xd9\x89", "\xd9\x8a", "\xd9\x8a", "\xd9\x8a", "\xd9\x8a", "\xd9\x84\xd8\xa2", "\xd9\x84\xd8\xa2", "\xd9\x84\xd8\xa3", + "\xd9\x84\xd8\xa3", "\xd9\x84\xd8\xa5", "\xd9\x84\xd8\xa5", "\xd9\x84\xd8\xa7", "\xd9\x84\xd8\xa7" +}; + +static const char *grn_nfkc50_decompose_table_efbc[] = { + "\x21", "\x22", "\x23", "\x24", "\x25", "\x26", "\x27", "\x28", + "\x29", "\x2a", "\x2b", "\x2c", "\x2d", "\x2e", "\x2f", "\x30", + "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", "\x38", + "\x39", "\x3a", "\x3b", "\x3c", "\x3d", "\x3e", "\x3f", "\x40", + "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", + "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", + "\x79", "\x7a", "\x5b", "\x5c", "\x5d", "\x5e", "\x5f" +}; + +static const char *grn_nfkc50_decompose_table_efbd[] = { + "\x60", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", + "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", + "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", + "\x78", "\x79", "\x7a", "\x7b", "\x7c", "\x7d", "\x7e", "\xe2\xa6\x85", + "\xe2\xa6\x86", "\xe3\x80\x82", "\xe3\x80\x8c", "\xe3\x80\x8d", "\xe3\x80\x81", "\xe3\x83\xbb", "\xe3\x83\xb2", "\xe3\x82\xa1", + "\xe3\x82\xa3", "\xe3\x82\xa5", "\xe3\x82\xa7", "\xe3\x82\xa9", "\xe3\x83\xa3", "\xe3\x83\xa5", "\xe3\x83\xa7", "\xe3\x83\x83", + "\xe3\x83\xbc", "\xe3\x82\xa2", "\xe3\x82\xa4", "\xe3\x82\xa6", "\xe3\x82\xa8", "\xe3\x82\xaa", "\xe3\x82\xab", "\xe3\x82\xad", + "\xe3\x82\xaf", "\xe3\x82\xb1", "\xe3\x82\xb3", "\xe3\x82\xb5", "\xe3\x82\xb7", "\xe3\x82\xb9", "\xe3\x82\xbb", "\xe3\x82\xbd" +}; + +static const char *grn_nfkc50_decompose_table_efbe[] = { + "\xe3\x82\xbf", "\xe3\x83\x81", "\xe3\x83\x84", "\xe3\x83\x86", "\xe3\x83\x88", "\xe3\x83\x8a", "\xe3\x83\x8b", "\xe3\x83\x8c", + "\xe3\x83\x8d", "\xe3\x83\x8e", "\xe3\x83\x8f", "\xe3\x83\x92", "\xe3\x83\x95", "\xe3\x83\x98", "\xe3\x83\x9b", "\xe3\x83\x9e", + "\xe3\x83\x9f", "\xe3\x83\xa0", "\xe3\x83\xa1", "\xe3\x83\xa2", "\xe3\x83\xa4", "\xe3\x83\xa6", "\xe3\x83\xa8", "\xe3\x83\xa9", + "\xe3\x83\xaa", "\xe3\x83\xab", "\xe3\x83\xac", "\xe3\x83\xad", "\xe3\x83\xaf", "\xe3\x83\xb3", "\xe3\x82\x99", "\xe3\x82\x9a", + "\xe1\x85\xa0", "\xe1\x84\x80", "\xe1\x84\x81", "\xe1\x86\xaa", "\xe1\x84\x82", "\xe1\x86\xac", "\xe1\x86\xad", "\xe1\x84\x83", + "\xe1\x84\x84", "\xe1\x84\x85", "\xe1\x86\xb0", "\xe1\x86\xb1", "\xe1\x86\xb2", "\xe1\x86\xb3", "\xe1\x86\xb4", "\xe1\x86\xb5", + "\xe1\x84\x9a", "\xe1\x84\x86", "\xe1\x84\x87", "\xe1\x84\x88", "\xe1\x84\xa1", "\xe1\x84\x89", "\xe1\x84\x8a", "\xe1\x84\x8b", + "\xe1\x84\x8c", "\xe1\x84\x8d", "\xe1\x84\x8e", "\xe1\x84\x8f", "\xe1\x84\x90", "\xe1\x84\x91", "\xe1\x84\x92" +}; + +static const char *grn_nfkc50_decompose_table_efbf[] = { + "\xe1\x85\xa1", "\xe1\x85\xa2", "\xe1\x85\xa3", "\xe1\x85\xa4", "\xe1\x85\xa5", "\xe1\x85\xa6", NULL, NULL, + "\xe1\x85\xa7", "\xe1\x85\xa8", "\xe1\x85\xa9", "\xe1\x85\xaa", "\xe1\x85\xab", "\xe1\x85\xac", NULL, NULL, + "\xe1\x85\xad", "\xe1\x85\xae", "\xe1\x85\xaf", "\xe1\x85\xb0", "\xe1\x85\xb1", "\xe1\x85\xb2", NULL, NULL, + "\xe1\x85\xb3", "\xe1\x85\xb4", "\xe1\x85\xb5", NULL, NULL, NULL, "\xc2\xa2", "\xc2\xa3", + "\xc2\xac", "\xcc\x84", "\xc2\xa6", "\xc2\xa5", "\xe2\x82\xa9", NULL, "\xe2\x94\x82", "\xe2\x86\x90", + "\xe2\x86\x91", "\xe2\x86\x92", "\xe2\x86\x93", "\xe2\x96\xa0", "\xe2\x97\x8b" +}; + +static const char *grn_nfkc50_decompose_table_f09d85[] = { + "\xf0\x9d\x85\x97\xf0\x9d\x85\xa5", "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5", "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xae", "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xaf", "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xb0", "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xb1", "\xf0\x9d\x85\x98\xf0\x9d\x85\xa5\xf0\x9d\x85\xb2" +}; + +static const char *grn_nfkc50_decompose_table_f09d86[] = { + "\xf0\x9d\x86\xb9\xf0\x9d\x85\xa5", "\xf0\x9d\x86\xba\xf0\x9d\x85\xa5", "\xf0\x9d\x86\xb9\xf0\x9d\x85\xa5\xf0\x9d\x85\xae", "\xf0\x9d\x86\xba\xf0\x9d\x85\xa5\xf0\x9d\x85\xae", "\xf0\x9d\x86\xb9\xf0\x9d\x85\xa5\xf0\x9d\x85\xaf" +}; + +static const char *grn_nfkc50_decompose_table_f09d90[] = { + "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", + "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", + "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", + "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", + "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", + "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64", + "\x65", "\x66", "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c" +}; + +static const char *grn_nfkc50_decompose_table_f09d91[] = { + "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", + "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", + "\x63", "\x64", "\x65", "\x66", "\x67", NULL, "\x69", "\x6a", + "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72", + "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", + "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", + "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78" +}; + +static const char *grn_nfkc50_decompose_table_f09d92[] = { + "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", + "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", + "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", + "\x77", "\x78", "\x79", "\x7a", "\x61", NULL, "\x63", "\x64", + NULL, NULL, "\x67", NULL, NULL, "\x6a", "\x6b", NULL, + NULL, "\x6e", "\x6f", "\x70", "\x71", NULL, "\x73", "\x74", + "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", + "\x63", "\x64", NULL, "\x66", NULL, "\x68", "\x69", "\x6a" +}; + +static const char *grn_nfkc50_decompose_table_f09d93[] = { + "\x6b", "\x6c", "\x6d", "\x6e", NULL, "\x70", "\x71", "\x72", + "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", + "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", + "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", + "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", + "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", + "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76" +}; + +static const char *grn_nfkc50_decompose_table_f09d94[] = { + "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", NULL, "\x64", + "\x65", "\x66", "\x67", NULL, NULL, "\x6a", "\x6b", "\x6c", + "\x6d", "\x6e", "\x6f", "\x70", "\x71", NULL, "\x73", "\x74", + "\x75", "\x76", "\x77", "\x78", "\x79", NULL, "\x61", "\x62", + "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", "\x69", "\x6a", + "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72", + "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", + "\x61", "\x62", NULL, "\x64", "\x65", "\x66", "\x67" +}; + +static const char *grn_nfkc50_decompose_table_f09d95[] = { + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", NULL, "\x6f", NULL, + NULL, NULL, "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", + "\x79", NULL, "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", + "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", + "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", + "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64", + "\x65", "\x66", "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", + "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74" +}; + +static const char *grn_nfkc50_decompose_table_f09d96[] = { + "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", + "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", "\x69", "\x6a", + "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72", + "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", + "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", + "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", + "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66" +}; + +static const char *grn_nfkc50_decompose_table_f09d97[] = { + "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", + "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", + "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64", + "\x65", "\x66", "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", + "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", + "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", + "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", "\x69", "\x6a", + "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72" +}; + +static const char *grn_nfkc50_decompose_table_f09d98[] = { + "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", + "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", + "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", + "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", + "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", + "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", + "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64" +}; + +static const char *grn_nfkc50_decompose_table_f09d99[] = { + "\x65", "\x66", "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", + "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", + "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", "\x61", "\x62", + "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", "\x69", "\x6a", + "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70", "\x71", "\x72", + "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", "\x79", "\x7a", + "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", "\x67", "\x68", + "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", "\x6f", "\x70" +}; + +static const char *grn_nfkc50_decompose_table_f09d9a[] = { + "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", "\x77", "\x78", + "\x79", "\x7a", "\x61", "\x62", "\x63", "\x64", "\x65", "\x66", + "\x67", "\x68", "\x69", "\x6a", "\x6b", "\x6c", "\x6d", "\x6e", + "\x6f", "\x70", "\x71", "\x72", "\x73", "\x74", "\x75", "\x76", + "\x77", "\x78", "\x79", "\x7a", "\xc4\xb1", "\xc8\xb7", NULL, NULL, + "\xce\x91", "\xce\x92", "\xce\x93", "\xce\x94", "\xce\x95", "\xce\x96", "\xce\x97", "\xce\x98", + "\xce\x99", "\xce\x9a", "\xce\x9b", "\xce\x9c", "\xce\x9d", "\xce\x9e", "\xce\x9f", "\xce\xa0", + "\xce\xa1", "\xce\x98", "\xce\xa3", "\xce\xa4", "\xce\xa5", "\xce\xa6", "\xce\xa7", "\xce\xa8" +}; + +static const char *grn_nfkc50_decompose_table_f09d9b[] = { + "\xce\xa9", "\xe2\x88\x87", "\xce\xb1", "\xce\xb2", "\xce\xb3", "\xce\xb4", "\xce\xb5", "\xce\xb6", + "\xce\xb7", "\xce\xb8", "\xce\xb9", "\xce\xba", "\xce\xbb", "\xce\xbc", "\xce\xbd", "\xce\xbe", + "\xce\xbf", "\xcf\x80", "\xcf\x81", "\xcf\x82", "\xcf\x83", "\xcf\x84", "\xcf\x85", "\xcf\x86", + "\xcf\x87", "\xcf\x88", "\xcf\x89", "\xe2\x88\x82", "\xce\xb5", "\xce\xb8", "\xce\xba", "\xcf\x86", + "\xcf\x81", "\xcf\x80", "\xce\x91", "\xce\x92", "\xce\x93", "\xce\x94", "\xce\x95", "\xce\x96", + "\xce\x97", "\xce\x98", "\xce\x99", "\xce\x9a", "\xce\x9b", "\xce\x9c", "\xce\x9d", "\xce\x9e", + "\xce\x9f", "\xce\xa0", "\xce\xa1", "\xce\x98", "\xce\xa3", "\xce\xa4", "\xce\xa5", "\xce\xa6", + "\xce\xa7", "\xce\xa8", "\xce\xa9", "\xe2\x88\x87", "\xce\xb1", "\xce\xb2", "\xce\xb3", "\xce\xb4" +}; + +static const char *grn_nfkc50_decompose_table_f09d9c[] = { + "\xce\xb5", "\xce\xb6", "\xce\xb7", "\xce\xb8", "\xce\xb9", "\xce\xba", "\xce\xbb", "\xce\xbc", + "\xce\xbd", "\xce\xbe", "\xce\xbf", "\xcf\x80", "\xcf\x81", "\xcf\x82", "\xcf\x83", "\xcf\x84", + "\xcf\x85", "\xcf\x86", "\xcf\x87", "\xcf\x88", "\xcf\x89", "\xe2\x88\x82", "\xce\xb5", "\xce\xb8", + "\xce\xba", "\xcf\x86", "\xcf\x81", "\xcf\x80", "\xce\x91", "\xce\x92", "\xce\x93", "\xce\x94", + "\xce\x95", "\xce\x96", "\xce\x97", "\xce\x98", "\xce\x99", "\xce\x9a", "\xce\x9b", "\xce\x9c", + "\xce\x9d", "\xce\x9e", "\xce\x9f", "\xce\xa0", "\xce\xa1", "\xce\x98", "\xce\xa3", "\xce\xa4", + "\xce\xa5", "\xce\xa6", "\xce\xa7", "\xce\xa8", "\xce\xa9", "\xe2\x88\x87", "\xce\xb1", "\xce\xb2", + "\xce\xb3", "\xce\xb4", "\xce\xb5", "\xce\xb6", "\xce\xb7", "\xce\xb8", "\xce\xb9", "\xce\xba" +}; + +static const char *grn_nfkc50_decompose_table_f09d9d[] = { + "\xce\xbb", "\xce\xbc", "\xce\xbd", "\xce\xbe", "\xce\xbf", "\xcf\x80", "\xcf\x81", "\xcf\x82", + "\xcf\x83", "\xcf\x84", "\xcf\x85", "\xcf\x86", "\xcf\x87", "\xcf\x88", "\xcf\x89", "\xe2\x88\x82", + "\xce\xb5", "\xce\xb8", "\xce\xba", "\xcf\x86", "\xcf\x81", "\xcf\x80", "\xce\x91", "\xce\x92", + "\xce\x93", "\xce\x94", "\xce\x95", "\xce\x96", "\xce\x97", "\xce\x98", "\xce\x99", "\xce\x9a", + "\xce\x9b", "\xce\x9c", "\xce\x9d", "\xce\x9e", "\xce\x9f", "\xce\xa0", "\xce\xa1", "\xce\x98", + "\xce\xa3", "\xce\xa4", "\xce\xa5", "\xce\xa6", "\xce\xa7", "\xce\xa8", "\xce\xa9", "\xe2\x88\x87", + "\xce\xb1", "\xce\xb2", "\xce\xb3", "\xce\xb4", "\xce\xb5", "\xce\xb6", "\xce\xb7", "\xce\xb8", + "\xce\xb9", "\xce\xba", "\xce\xbb", "\xce\xbc", "\xce\xbd", "\xce\xbe", "\xce\xbf", "\xcf\x80" +}; + +static const char *grn_nfkc50_decompose_table_f09d9e[] = { + "\xcf\x81", "\xcf\x82", "\xcf\x83", "\xcf\x84", "\xcf\x85", "\xcf\x86", "\xcf\x87", "\xcf\x88", + "\xcf\x89", "\xe2\x88\x82", "\xce\xb5", "\xce\xb8", "\xce\xba", "\xcf\x86", "\xcf\x81", "\xcf\x80", + "\xce\x91", "\xce\x92", "\xce\x93", "\xce\x94", "\xce\x95", "\xce\x96", "\xce\x97", "\xce\x98", + "\xce\x99", "\xce\x9a", "\xce\x9b", "\xce\x9c", "\xce\x9d", "\xce\x9e", "\xce\x9f", "\xce\xa0", + "\xce\xa1", "\xce\x98", "\xce\xa3", "\xce\xa4", "\xce\xa5", "\xce\xa6", "\xce\xa7", "\xce\xa8", + "\xce\xa9", "\xe2\x88\x87", "\xce\xb1", "\xce\xb2", "\xce\xb3", "\xce\xb4", "\xce\xb5", "\xce\xb6", + "\xce\xb7", "\xce\xb8", "\xce\xb9", "\xce\xba", "\xce\xbb", "\xce\xbc", "\xce\xbd", "\xce\xbe", + "\xce\xbf", "\xcf\x80", "\xcf\x81", "\xcf\x82", "\xcf\x83", "\xcf\x84", "\xcf\x85", "\xcf\x86" +}; + +static const char *grn_nfkc50_decompose_table_f09d9f[] = { + "\xcf\x87", "\xcf\x88", "\xcf\x89", "\xe2\x88\x82", "\xce\xb5", "\xce\xb8", "\xce\xba", "\xcf\x86", + "\xcf\x81", "\xcf\x80", "\xcf\x9c", "\xcf\x9d", NULL, NULL, "\x30", "\x31", + "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", "\x38", "\x39", + "\x30", "\x31", "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", + "\x38", "\x39", "\x30", "\x31", "\x32", "\x33", "\x34", "\x35", + "\x36", "\x37", "\x38", "\x39", "\x30", "\x31", "\x32", "\x33", + "\x34", "\x35", "\x36", "\x37", "\x38", "\x39", "\x30", "\x31", + "\x32", "\x33", "\x34", "\x35", "\x36", "\x37", "\x38", "\x39" +}; + +static const char *grn_nfkc50_decompose_table_f0afa0[] = { + "\xe4\xb8\xbd", "\xe4\xb8\xb8", "\xe4\xb9\x81", "\xf0\xa0\x84\xa2", "\xe4\xbd\xa0", "\xe4\xbe\xae", "\xe4\xbe\xbb", "\xe5\x80\x82", + "\xe5\x81\xba", "\xe5\x82\x99", "\xe5\x83\xa7", "\xe5\x83\x8f", "\xe3\x92\x9e", "\xf0\xa0\x98\xba", "\xe5\x85\x8d", "\xe5\x85\x94", + "\xe5\x85\xa4", "\xe5\x85\xb7", "\xf0\xa0\x94\x9c", "\xe3\x92\xb9", "\xe5\x85\xa7", "\xe5\x86\x8d", "\xf0\xa0\x95\x8b", "\xe5\x86\x97", + "\xe5\x86\xa4", "\xe4\xbb\x8c", "\xe5\x86\xac", "\xe5\x86\xb5", "\xf0\xa9\x87\x9f", "\xe5\x87\xb5", "\xe5\x88\x83", "\xe3\x93\x9f", + "\xe5\x88\xbb", "\xe5\x89\x86", "\xe5\x89\xb2", "\xe5\x89\xb7", "\xe3\x94\x95", "\xe5\x8b\x87", "\xe5\x8b\x89", "\xe5\x8b\xa4", + "\xe5\x8b\xba", "\xe5\x8c\x85", "\xe5\x8c\x86", "\xe5\x8c\x97", "\xe5\x8d\x89", "\xe5\x8d\x91", "\xe5\x8d\x9a", "\xe5\x8d\xb3", + "\xe5\x8d\xbd", "\xe5\x8d\xbf", "\xe5\x8d\xbf", "\xe5\x8d\xbf", "\xf0\xa0\xa8\xac", "\xe7\x81\xb0", "\xe5\x8f\x8a", "\xe5\x8f\x9f", + "\xf0\xa0\xad\xa3", "\xe5\x8f\xab", "\xe5\x8f\xb1", "\xe5\x90\x86", "\xe5\x92\x9e", "\xe5\x90\xb8", "\xe5\x91\x88", "\xe5\x91\xa8" +}; + +static const char *grn_nfkc50_decompose_table_f0afa1[] = { + "\xe5\x92\xa2", "\xe5\x93\xb6", "\xe5\x94\x90", "\xe5\x95\x93", "\xe5\x95\xa3", "\xe5\x96\x84", "\xe5\x96\x84", "\xe5\x96\x99", + "\xe5\x96\xab", "\xe5\x96\xb3", "\xe5\x97\x82", "\xe5\x9c\x96", "\xe5\x98\x86", "\xe5\x9c\x97", "\xe5\x99\x91", "\xe5\x99\xb4", + "\xe5\x88\x87", "\xe5\xa3\xae", "\xe5\x9f\x8e", "\xe5\x9f\xb4", "\xe5\xa0\x8d", "\xe5\x9e\x8b", "\xe5\xa0\xb2", "\xe5\xa0\xb1", + "\xe5\xa2\xac", "\xf0\xa1\x93\xa4", "\xe5\xa3\xb2", "\xe5\xa3\xb7", "\xe5\xa4\x86", "\xe5\xa4\x9a", "\xe5\xa4\xa2", "\xe5\xa5\xa2", + "\xf0\xa1\x9a\xa8", "\xf0\xa1\x9b\xaa", "\xe5\xa7\xac", "\xe5\xa8\x9b", "\xe5\xa8\xa7", "\xe5\xa7\x98", "\xe5\xa9\xa6", "\xe3\x9b\xae", + "\xe3\x9b\xbc", "\xe5\xac\x88", "\xe5\xac\xbe", "\xe5\xac\xbe", "\xf0\xa1\xa7\x88", "\xe5\xaf\x83", "\xe5\xaf\x98", "\xe5\xaf\xa7", + "\xe5\xaf\xb3", "\xf0\xa1\xac\x98", "\xe5\xaf\xbf", "\xe5\xb0\x86", "\xe5\xbd\x93", "\xe5\xb0\xa2", "\xe3\x9e\x81", "\xe5\xb1\xa0", + "\xe5\xb1\xae", "\xe5\xb3\x80", "\xe5\xb2\x8d", "\xf0\xa1\xb7\xa4", "\xe5\xb5\x83", "\xf0\xa1\xb7\xa6", "\xe5\xb5\xae", "\xe5\xb5\xab" +}; + +static const char *grn_nfkc50_decompose_table_f0afa2[] = { + "\xe5\xb5\xbc", "\xe5\xb7\xa1", "\xe5\xb7\xa2", "\xe3\xa0\xaf", "\xe5\xb7\xbd", "\xe5\xb8\xa8", "\xe5\xb8\xbd", "\xe5\xb9\xa9", + "\xe3\xa1\xa2", "\xf0\xa2\x86\x83", "\xe3\xa1\xbc", "\xe5\xba\xb0", "\xe5\xba\xb3", "\xe5\xba\xb6", "\xe5\xbb\x8a", "\xf0\xaa\x8e\x92", + "\xe5\xbb\xbe", "\xf0\xa2\x8c\xb1", "\xf0\xa2\x8c\xb1", "\xe8\x88\x81", "\xe5\xbc\xa2", "\xe5\xbc\xa2", "\xe3\xa3\x87", "\xf0\xa3\x8a\xb8", + "\xf0\xa6\x87\x9a", "\xe5\xbd\xa2", "\xe5\xbd\xab", "\xe3\xa3\xa3", "\xe5\xbe\x9a", "\xe5\xbf\x8d", "\xe5\xbf\x97", "\xe5\xbf\xb9", + "\xe6\x82\x81", "\xe3\xa4\xba", "\xe3\xa4\x9c", "\xe6\x82\x94", "\xf0\xa2\x9b\x94", "\xe6\x83\x87", "\xe6\x85\x88", "\xe6\x85\x8c", + "\xe6\x85\x8e", "\xe6\x85\x8c", "\xe6\x85\xba", "\xe6\x86\x8e", "\xe6\x86\xb2", "\xe6\x86\xa4", "\xe6\x86\xaf", "\xe6\x87\x9e", + "\xe6\x87\xb2", "\xe6\x87\xb6", "\xe6\x88\x90", "\xe6\x88\x9b", "\xe6\x89\x9d", "\xe6\x8a\xb1", "\xe6\x8b\x94", "\xe6\x8d\x90", + "\xf0\xa2\xac\x8c", "\xe6\x8c\xbd", "\xe6\x8b\xbc", "\xe6\x8d\xa8", "\xe6\x8e\x83", "\xe6\x8f\xa4", "\xf0\xa2\xaf\xb1", "\xe6\x90\xa2" +}; + +static const char *grn_nfkc50_decompose_table_f0afa3[] = { + "\xe6\x8f\x85", "\xe6\x8e\xa9", "\xe3\xa8\xae", "\xe6\x91\xa9", "\xe6\x91\xbe", "\xe6\x92\x9d", "\xe6\x91\xb7", "\xe3\xa9\xac", + "\xe6\x95\x8f", "\xe6\x95\xac", "\xf0\xa3\x80\x8a", "\xe6\x97\xa3", "\xe6\x9b\xb8", "\xe6\x99\x89", "\xe3\xac\x99", "\xe6\x9a\x91", + "\xe3\xac\x88", "\xe3\xab\xa4", "\xe5\x86\x92", "\xe5\x86\x95", "\xe6\x9c\x80", "\xe6\x9a\x9c", "\xe8\x82\xad", "\xe4\x8f\x99", + "\xe6\x9c\x97", "\xe6\x9c\x9b", "\xe6\x9c\xa1", "\xe6\x9d\x9e", "\xe6\x9d\x93", "\xf0\xa3\x8f\x83", "\xe3\xad\x89", "\xe6\x9f\xba", + "\xe6\x9e\x85", "\xe6\xa1\x92", "\xe6\xa2\x85", "\xf0\xa3\x91\xad", "\xe6\xa2\x8e", "\xe6\xa0\x9f", "\xe6\xa4\x94", "\xe3\xae\x9d", + "\xe6\xa5\x82", "\xe6\xa6\xa3", "\xe6\xa7\xaa", "\xe6\xaa\xa8", "\xf0\xa3\x9a\xa3", "\xe6\xab\x9b", "\xe3\xb0\x98", "\xe6\xac\xa1", + "\xf0\xa3\xa2\xa7", "\xe6\xad\x94", "\xe3\xb1\x8e", "\xe6\xad\xb2", "\xe6\xae\x9f", "\xe6\xae\xba", "\xe6\xae\xbb", "\xf0\xa3\xaa\x8d", + "\xf0\xa1\xb4\x8b", "\xf0\xa3\xab\xba", "\xe6\xb1\x8e", "\xf0\xa3\xb2\xbc", "\xe6\xb2\xbf", "\xe6\xb3\x8d", "\xe6\xb1\xa7", "\xe6\xb4\x96" +}; + +static const char *grn_nfkc50_decompose_table_f0afa4[] = { + "\xe6\xb4\xbe", "\xe6\xb5\xb7", "\xe6\xb5\x81", "\xe6\xb5\xa9", "\xe6\xb5\xb8", "\xe6\xb6\x85", "\xf0\xa3\xb4\x9e", "\xe6\xb4\xb4", + "\xe6\xb8\xaf", "\xe6\xb9\xae", "\xe3\xb4\xb3", "\xe6\xbb\x8b", "\xe6\xbb\x87", "\xf0\xa3\xbb\x91", "\xe6\xb7\xb9", "\xe6\xbd\xae", + "\xf0\xa3\xbd\x9e", "\xf0\xa3\xbe\x8e", "\xe6\xbf\x86", "\xe7\x80\xb9", "\xe7\x80\x9e", "\xe7\x80\x9b", "\xe3\xb6\x96", "\xe7\x81\x8a", + "\xe7\x81\xbd", "\xe7\x81\xb7", "\xe7\x82\xad", "\xf0\xa0\x94\xa5", "\xe7\x85\x85", "\xf0\xa4\x89\xa3", "\xe7\x86\x9c", "\xf0\xa4\x8e\xab", + "\xe7\x88\xa8", "\xe7\x88\xb5", "\xe7\x89\x90", "\xf0\xa4\x98\x88", "\xe7\x8a\x80", "\xe7\x8a\x95", "\xf0\xa4\x9c\xb5", "\xf0\xa4\xa0\x94", + "\xe7\x8d\xba", "\xe7\x8e\x8b", "\xe3\xba\xac", "\xe7\x8e\xa5", "\xe3\xba\xb8", "\xe3\xba\xb8", "\xe7\x91\x87", "\xe7\x91\x9c", + "\xe7\x91\xb1", "\xe7\x92\x85", "\xe7\x93\x8a", "\xe3\xbc\x9b", "\xe7\x94\xa4", "\xf0\xa4\xb0\xb6", "\xe7\x94\xbe", "\xf0\xa4\xb2\x92", + "\xe7\x95\xb0", "\xf0\xa2\x86\x9f", "\xe7\x98\x90", "\xf0\xa4\xbe\xa1", "\xf0\xa4\xbe\xb8", "\xf0\xa5\x81\x84", "\xe3\xbf\xbc", "\xe4\x80\x88" +}; + +static const char *grn_nfkc50_decompose_table_f0afa5[] = { + "\xe7\x9b\xb4", "\xf0\xa5\x83\xb3", "\xf0\xa5\x83\xb2", "\xf0\xa5\x84\x99", "\xf0\xa5\x84\xb3", "\xe7\x9c\x9e", "\xe7\x9c\x9f", "\xe7\x9c\x9f", + "\xe7\x9d\x8a", "\xe4\x80\xb9", "\xe7\x9e\x8b", "\xe4\x81\x86", "\xe4\x82\x96", "\xf0\xa5\x90\x9d", "\xe7\xa1\x8e", "\xe7\xa2\x8c", + "\xe7\xa3\x8c", "\xe4\x83\xa3", "\xf0\xa5\x98\xa6", "\xe7\xa5\x96", "\xf0\xa5\x9a\x9a", "\xf0\xa5\x9b\x85", "\xe7\xa6\x8f", "\xe7\xa7\xab", + "\xe4\x84\xaf", "\xe7\xa9\x80", "\xe7\xa9\x8a", "\xe7\xa9\x8f", "\xf0\xa5\xa5\xbc", "\xf0\xa5\xaa\xa7", "\xf0\xa5\xaa\xa7", "\xe7\xab\xae", + "\xe4\x88\x82", "\xf0\xa5\xae\xab", "\xe7\xaf\x86", "\xe7\xaf\x89", "\xe4\x88\xa7", "\xf0\xa5\xb2\x80", "\xe7\xb3\x92", "\xe4\x8a\xa0", + "\xe7\xb3\xa8", "\xe7\xb3\xa3", "\xe7\xb4\x80", "\xf0\xa5\xbe\x86", "\xe7\xb5\xa3", "\xe4\x8c\x81", "\xe7\xb7\x87", "\xe7\xb8\x82", + "\xe7\xb9\x85", "\xe4\x8c\xb4", "\xf0\xa6\x88\xa8", "\xf0\xa6\x89\x87", "\xe4\x8d\x99", "\xf0\xa6\x8b\x99", "\xe7\xbd\xba", "\xf0\xa6\x8c\xbe", + "\xe7\xbe\x95", "\xe7\xbf\xba", "\xe8\x80\x85", "\xf0\xa6\x93\x9a", "\xf0\xa6\x94\xa3", "\xe8\x81\xa0", "\xf0\xa6\x96\xa8", "\xe8\x81\xb0" +}; + +static const char *grn_nfkc50_decompose_table_f0afa6[] = { + "\xf0\xa3\x8d\x9f", "\xe4\x8f\x95", "\xe8\x82\xb2", "\xe8\x84\x83", "\xe4\x90\x8b", "\xe8\x84\xbe", "\xe5\xaa\xb5", "\xf0\xa6\x9e\xa7", + "\xf0\xa6\x9e\xb5", "\xf0\xa3\x8e\x93", "\xf0\xa3\x8e\x9c", "\xe8\x88\x81", "\xe8\x88\x84", "\xe8\xbe\x9e", "\xe4\x91\xab", "\xe8\x8a\x91", + "\xe8\x8a\x8b", "\xe8\x8a\x9d", "\xe5\x8a\xb3", "\xe8\x8a\xb1", "\xe8\x8a\xb3", "\xe8\x8a\xbd", "\xe8\x8b\xa6", "\xf0\xa6\xac\xbc", + "\xe8\x8b\xa5", "\xe8\x8c\x9d", "\xe8\x8d\xa3", "\xe8\x8e\xad", "\xe8\x8c\xa3", "\xe8\x8e\xbd", "\xe8\x8f\xa7", "\xe8\x91\x97", + "\xe8\x8d\x93", "\xe8\x8f\x8a", "\xe8\x8f\x8c", "\xe8\x8f\x9c", "\xf0\xa6\xb0\xb6", "\xf0\xa6\xb5\xab", "\xf0\xa6\xb3\x95", "\xe4\x94\xab", + "\xe8\x93\xb1", "\xe8\x93\xb3", "\xe8\x94\x96", "\xf0\xa7\x8f\x8a", "\xe8\x95\xa4", "\xf0\xa6\xbc\xac", "\xe4\x95\x9d", "\xe4\x95\xa1", + "\xf0\xa6\xbe\xb1", "\xf0\xa7\x83\x92", "\xe4\x95\xab", "\xe8\x99\x90", "\xe8\x99\x9c", "\xe8\x99\xa7", "\xe8\x99\xa9", "\xe8\x9a\xa9", + "\xe8\x9a\x88", "\xe8\x9c\x8e", "\xe8\x9b\xa2", "\xe8\x9d\xb9", "\xe8\x9c\xa8", "\xe8\x9d\xab", "\xe8\x9e\x86", "\xe4\x97\x97" +}; + +static const char *grn_nfkc50_decompose_table_f0afa7[] = { + "\xe8\x9f\xa1", "\xe8\xa0\x81", "\xe4\x97\xb9", "\xe8\xa1\xa0", "\xe8\xa1\xa3", "\xf0\xa7\x99\xa7", "\xe8\xa3\x97", "\xe8\xa3\x9e", + "\xe4\x98\xb5", "\xe8\xa3\xba", "\xe3\x92\xbb", "\xf0\xa7\xa2\xae", "\xf0\xa7\xa5\xa6", "\xe4\x9a\xbe", "\xe4\x9b\x87", "\xe8\xaa\xa0", + "\xe8\xab\xad", "\xe8\xae\x8a", "\xe8\xb1\x95", "\xf0\xa7\xb2\xa8", "\xe8\xb2\xab", "\xe8\xb3\x81", "\xe8\xb4\x9b", "\xe8\xb5\xb7", + "\xf0\xa7\xbc\xaf", "\xf0\xa0\xa0\x84", "\xe8\xb7\x8b", "\xe8\xb6\xbc", "\xe8\xb7\xb0", "\xf0\xa0\xa3\x9e", "\xe8\xbb\x94", "\xe8\xbc\xb8", + "\xf0\xa8\x97\x92", "\xf0\xa8\x97\xad", "\xe9\x82\x94", "\xe9\x83\xb1", "\xe9\x84\x91", "\xf0\xa8\x9c\xae", "\xe9\x84\x9b", "\xe9\x88\xb8", + "\xe9\x8b\x97", "\xe9\x8b\x98", "\xe9\x89\xbc", "\xe9\x8f\xb9", "\xe9\x90\x95", "\xf0\xa8\xaf\xba", "\xe9\x96\x8b", "\xe4\xa6\x95", + "\xe9\x96\xb7", "\xf0\xa8\xb5\xb7", "\xe4\xa7\xa6", "\xe9\x9b\x83", "\xe5\xb6\xb2", "\xe9\x9c\xa3", "\xf0\xa9\x85\x85", "\xf0\xa9\x88\x9a", + "\xe4\xa9\xae", "\xe4\xa9\xb6", "\xe9\x9f\xa0", "\xf0\xa9\x90\x8a", "\xe4\xaa\xb2", "\xf0\xa9\x92\x96", "\xe9\xa0\x8b", "\xe9\xa0\x8b" +}; + +static const char *grn_nfkc50_decompose_table_f0afa8[] = { + "\xe9\xa0\xa9", "\xf0\xa9\x96\xb6", "\xe9\xa3\xa2", "\xe4\xac\xb3", "\xe9\xa4\xa9", "\xe9\xa6\xa7", "\xe9\xa7\x82", "\xe9\xa7\xbe", + "\xe4\xaf\x8e", "\xf0\xa9\xac\xb0", "\xe9\xac\x92", "\xe9\xb1\x80", "\xe9\xb3\xbd", "\xe4\xb3\x8e", "\xe4\xb3\xad", "\xe9\xb5\xa7", + "\xf0\xaa\x83\x8e", "\xe4\xb3\xb8", "\xf0\xaa\x84\x85", "\xf0\xaa\x88\x8e", "\xf0\xaa\x8a\x91", "\xe9\xba\xbb", "\xe4\xb5\x96", "\xe9\xbb\xb9", + "\xe9\xbb\xbe", "\xe9\xbc\x85", "\xe9\xbc\x8f", "\xe9\xbc\x96", "\xe9\xbc\xbb", "\xf0\xaa\x98\x80" +}; + +const char * +grn_nfkc50_decompose(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x41 && + utf8[0] <= 0x5a) { + return grn_nfkc50_decompose_table_[utf8[0] - 0x41]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc2 : + if (utf8[1] >= 0xa0 && + utf8[1] <= 0xbe) { + return grn_nfkc50_decompose_table_c2[utf8[1] - 0xa0]; + } + break; + case 0xc3 : + if (utf8[1] >= 0x80 && + utf8[1] <= 0x9d) { + return grn_nfkc50_decompose_table_c3[utf8[1] - 0x80]; + } + break; + case 0xc4 : + return grn_nfkc50_decompose_table_c4[utf8[1] - 0x80]; + case 0xc5 : + return grn_nfkc50_decompose_table_c5[utf8[1] - 0x80]; + case 0xc6 : + if (utf8[1] >= 0xa0 && + utf8[1] <= 0xaf) { + return grn_nfkc50_decompose_table_c6[utf8[1] - 0xa0]; + } + break; + case 0xc7 : + if (utf8[1] >= 0x84 && + utf8[1] <= 0xba) { + return grn_nfkc50_decompose_table_c7[utf8[1] - 0x84]; + } + break; + case 0xc8 : + if (utf8[1] >= 0x80 && + utf8[1] <= 0xb2) { + return grn_nfkc50_decompose_table_c8[utf8[1] - 0x80]; + } + break; + case 0xca : + if (utf8[1] >= 0xb0 && + utf8[1] <= 0xb8) { + return grn_nfkc50_decompose_table_ca[utf8[1] - 0xb0]; + } + break; + case 0xcb : + if (utf8[1] >= 0x98 && + utf8[1] <= 0xa4) { + return grn_nfkc50_decompose_table_cb[utf8[1] - 0x98]; + } + break; + case 0xcd : + if (utf8[1] >= 0x80 && + utf8[1] <= 0xbe) { + return grn_nfkc50_decompose_table_cd[utf8[1] - 0x80]; + } + break; + case 0xce : + if (utf8[1] >= 0x84 && + utf8[1] <= 0x87) { + return grn_nfkc50_decompose_table_ce[utf8[1] - 0x84]; + } + break; + case 0xcf : + if (utf8[1] >= 0x90 && + utf8[1] <= 0xb9) { + return grn_nfkc50_decompose_table_cf[utf8[1] - 0x90]; + } + break; + case 0xd6 : + if (utf8[1] == 0x87) { + return "\xd5\xa5\xd6\x82"; + } + break; + case 0xd9 : + if (utf8[1] >= 0xb5 && + utf8[1] <= 0xb8) { + return grn_nfkc50_decompose_table_d9[utf8[1] - 0xb5]; + } + break; + case 0xe0 : + switch (utf8[1]) { + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0x9f) { + return grn_nfkc50_decompose_table_e0a5[utf8[2] - 0x98]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x9c && + utf8[2] <= 0x9f) { + return grn_nfkc50_decompose_table_e0a7[utf8[2] - 0x9c]; + } + break; + case 0xa8 : + if (utf8[2] >= 0xb3 && + utf8[2] <= 0xb6) { + return grn_nfkc50_decompose_table_e0a8[utf8[2] - 0xb3]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x99 && + utf8[2] <= 0x9e) { + return grn_nfkc50_decompose_table_e0a9[utf8[2] - 0x99]; + } + break; + case 0xad : + if (utf8[2] >= 0x9c && + utf8[2] <= 0x9d) { + return grn_nfkc50_decompose_table_e0ad[utf8[2] - 0x9c]; + } + break; + case 0xb8 : + if (utf8[2] == 0xb3) { + return "\xe0\xb9\x8d\xe0\xb8\xb2"; + } + break; + case 0xba : + if (utf8[2] == 0xb3) { + return "\xe0\xbb\x8d\xe0\xba\xb2"; + } + break; + case 0xbb : + if (utf8[2] >= 0x9c && + utf8[2] <= 0x9d) { + return grn_nfkc50_decompose_table_e0bb[utf8[2] - 0x9c]; + } + break; + case 0xbc : + if (utf8[2] == 0x8c) { + return "\xe0\xbc\x8b"; + } + break; + case 0xbd : + if (utf8[2] >= 0x83 && + utf8[2] <= 0xb9) { + return grn_nfkc50_decompose_table_e0bd[utf8[2] - 0x83]; + } + break; + case 0xbe : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xb9) { + return grn_nfkc50_decompose_table_e0be[utf8[2] - 0x81]; + } + break; + default : + break; + } + break; + case 0xe1 : + switch (utf8[1]) { + case 0x83 : + if (utf8[2] == 0xbc) { + return "\xe1\x83\x9c"; + } + break; + case 0xb4 : + if (utf8[2] >= 0xac && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_e1b4[utf8[2] - 0xac]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_decompose_table_e1b5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x9b && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_e1b6[utf8[2] - 0x9b]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_decompose_table_e1b8[utf8[2] - 0x80]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_decompose_table_e1b9[utf8[2] - 0x80]; + } + break; + case 0xba : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_decompose_table_e1ba[utf8[2] - 0x80]; + } + break; + case 0xbb : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_decompose_table_e1bb[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0xb1 && + utf8[2] <= 0xbd) { + return grn_nfkc50_decompose_table_e1bd[utf8[2] - 0xb1]; + } + break; + case 0xbe : + if (utf8[2] >= 0xbb && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_e1be[utf8[2] - 0xbb]; + } + break; + case 0xbf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_decompose_table_e1bf[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + case 0xe2 : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_decompose_table_e280[utf8[2] - 0x80]; + } + break; + case 0x81 : + if (utf8[2] >= 0x87 && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_e281[utf8[2] - 0x87]; + } + break; + case 0x82 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xa8) { + return grn_nfkc50_decompose_table_e282[utf8[2] - 0x80]; + } + break; + case 0x84 : + return grn_nfkc50_decompose_table_e284[utf8[2] - 0x80]; + case 0x85 : + return grn_nfkc50_decompose_table_e285[utf8[2] - 0x80]; + case 0x88 : + if (utf8[2] >= 0xac && + utf8[2] <= 0xb0) { + return grn_nfkc50_decompose_table_e288[utf8[2] - 0xac]; + } + break; + case 0x8c : + if (utf8[2] >= 0xa9 && + utf8[2] <= 0xaa) { + return grn_nfkc50_decompose_table_e28c[utf8[2] - 0xa9]; + } + break; + case 0x91 : + if (utf8[2] >= 0xa0 && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_e291[utf8[2] - 0xa0]; + } + break; + case 0x92 : + return grn_nfkc50_decompose_table_e292[utf8[2] - 0x80]; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xaa) { + return grn_nfkc50_decompose_table_e293[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] == 0x8c) { + return "\xe2\x88\xab\xe2\x88\xab\xe2\x88\xab\xe2\x88\xab"; + } + break; + case 0xa9 : + if (utf8[2] >= 0xb4 && + utf8[2] <= 0xb6) { + return grn_nfkc50_decompose_table_e2a9[utf8[2] - 0xb4]; + } + break; + case 0xab : + if (utf8[2] == 0x9c) { + return "\xe2\xab\x9d\xcc\xb8"; + } + break; + case 0xb5 : + if (utf8[2] == 0xaf) { + return "\xe2\xb5\xa1"; + } + break; + case 0xba : + if (utf8[2] == 0x9f) { + return "\xe6\xaf\x8d"; + } + break; + case 0xbb : + if (utf8[2] == 0xb3) { + return "\xe9\xbe\x9f"; + } + break; + case 0xbc : + return grn_nfkc50_decompose_table_e2bc[utf8[2] - 0x80]; + case 0xbd : + return grn_nfkc50_decompose_table_e2bd[utf8[2] - 0x80]; + case 0xbe : + return grn_nfkc50_decompose_table_e2be[utf8[2] - 0x80]; + case 0xbf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x95) { + return grn_nfkc50_decompose_table_e2bf[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + case 0xe3 : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xba) { + return grn_nfkc50_decompose_table_e380[utf8[2] - 0x80]; + } + break; + case 0x82 : + if (utf8[2] >= 0x9b && + utf8[2] <= 0x9f) { + return grn_nfkc50_decompose_table_e382[utf8[2] - 0x9b]; + } + break; + case 0x83 : + if (utf8[2] == 0xbf) { + return "\xe3\x82\xb3\xe3\x83\x88"; + } + break; + case 0x84 : + if (utf8[2] >= 0xb1 && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_e384[utf8[2] - 0xb1]; + } + break; + case 0x85 : + return grn_nfkc50_decompose_table_e385[utf8[2] - 0x80]; + case 0x86 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x9f) { + return grn_nfkc50_decompose_table_e386[utf8[2] - 0x80]; + } + break; + case 0x88 : + return grn_nfkc50_decompose_table_e388[utf8[2] - 0x80]; + case 0x89 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_decompose_table_e389[utf8[2] - 0x80]; + } + break; + case 0x8a : + return grn_nfkc50_decompose_table_e38a[utf8[2] - 0x80]; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_decompose_table_e38b[utf8[2] - 0x80]; + } + break; + case 0x8c : + return grn_nfkc50_decompose_table_e38c[utf8[2] - 0x80]; + case 0x8d : + return grn_nfkc50_decompose_table_e38d[utf8[2] - 0x80]; + case 0x8e : + return grn_nfkc50_decompose_table_e38e[utf8[2] - 0x80]; + case 0x8f : + return grn_nfkc50_decompose_table_e38f[utf8[2] - 0x80]; + default : + break; + } + break; + case 0xef : + switch (utf8[1]) { + case 0xa4 : + return grn_nfkc50_decompose_table_efa4[utf8[2] - 0x80]; + case 0xa5 : + return grn_nfkc50_decompose_table_efa5[utf8[2] - 0x80]; + case 0xa6 : + return grn_nfkc50_decompose_table_efa6[utf8[2] - 0x80]; + case 0xa7 : + return grn_nfkc50_decompose_table_efa7[utf8[2] - 0x80]; + case 0xa8 : + return grn_nfkc50_decompose_table_efa8[utf8[2] - 0x80]; + case 0xa9 : + return grn_nfkc50_decompose_table_efa9[utf8[2] - 0x80]; + case 0xaa : + return grn_nfkc50_decompose_table_efaa[utf8[2] - 0x80]; + case 0xab : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x99) { + return grn_nfkc50_decompose_table_efab[utf8[2] - 0x80]; + } + break; + case 0xac : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_decompose_table_efac[utf8[2] - 0x80]; + } + break; + case 0xad : + return grn_nfkc50_decompose_table_efad[utf8[2] - 0x80]; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb1) { + return grn_nfkc50_decompose_table_efae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x93 && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_efaf[utf8[2] - 0x93]; + } + break; + case 0xb0 : + return grn_nfkc50_decompose_table_efb0[utf8[2] - 0x80]; + case 0xb1 : + return grn_nfkc50_decompose_table_efb1[utf8[2] - 0x80]; + case 0xb2 : + return grn_nfkc50_decompose_table_efb2[utf8[2] - 0x80]; + case 0xb3 : + return grn_nfkc50_decompose_table_efb3[utf8[2] - 0x80]; + case 0xb4 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbd) { + return grn_nfkc50_decompose_table_efb4[utf8[2] - 0x80]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_efb5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + return grn_nfkc50_decompose_table_efb6[utf8[2] - 0x80]; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbc) { + return grn_nfkc50_decompose_table_efb7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_efb8[utf8[2] - 0x90]; + } + break; + case 0xb9 : + return grn_nfkc50_decompose_table_efb9[utf8[2] - 0x80]; + case 0xba : + return grn_nfkc50_decompose_table_efba[utf8[2] - 0x80]; + case 0xbb : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbc) { + return grn_nfkc50_decompose_table_efbb[utf8[2] - 0x80]; + } + break; + case 0xbc : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xbf) { + return grn_nfkc50_decompose_table_efbc[utf8[2] - 0x81]; + } + break; + case 0xbd : + return grn_nfkc50_decompose_table_efbd[utf8[2] - 0x80]; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xbe) { + return grn_nfkc50_decompose_table_efbe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x82 && + utf8[2] <= 0xae) { + return grn_nfkc50_decompose_table_efbf[utf8[2] - 0x82]; + } + break; + default : + break; + } + break; + case 0xf0 : + switch (utf8[1]) { + case 0x9d : + switch (utf8[2]) { + case 0x85 : + if (utf8[3] >= 0x9e && + utf8[3] <= 0xa4) { + return grn_nfkc50_decompose_table_f09d85[utf8[3] - 0x9e]; + } + break; + case 0x86 : + if (utf8[3] >= 0xbb && + utf8[3] <= 0xbf) { + return grn_nfkc50_decompose_table_f09d86[utf8[3] - 0xbb]; + } + break; + case 0x87 : + if (utf8[3] == 0x80) { + return "\xf0\x9d\x86\xba\xf0\x9d\x85\xa5\xf0\x9d\x85\xaf"; + } + break; + case 0x90 : + return grn_nfkc50_decompose_table_f09d90[utf8[3] - 0x80]; + case 0x91 : + return grn_nfkc50_decompose_table_f09d91[utf8[3] - 0x80]; + case 0x92 : + return grn_nfkc50_decompose_table_f09d92[utf8[3] - 0x80]; + case 0x93 : + return grn_nfkc50_decompose_table_f09d93[utf8[3] - 0x80]; + case 0x94 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0xbe) { + return grn_nfkc50_decompose_table_f09d94[utf8[3] - 0x80]; + } + break; + case 0x95 : + return grn_nfkc50_decompose_table_f09d95[utf8[3] - 0x80]; + case 0x96 : + return grn_nfkc50_decompose_table_f09d96[utf8[3] - 0x80]; + case 0x97 : + return grn_nfkc50_decompose_table_f09d97[utf8[3] - 0x80]; + case 0x98 : + return grn_nfkc50_decompose_table_f09d98[utf8[3] - 0x80]; + case 0x99 : + return grn_nfkc50_decompose_table_f09d99[utf8[3] - 0x80]; + case 0x9a : + return grn_nfkc50_decompose_table_f09d9a[utf8[3] - 0x80]; + case 0x9b : + return grn_nfkc50_decompose_table_f09d9b[utf8[3] - 0x80]; + case 0x9c : + return grn_nfkc50_decompose_table_f09d9c[utf8[3] - 0x80]; + case 0x9d : + return grn_nfkc50_decompose_table_f09d9d[utf8[3] - 0x80]; + case 0x9e : + return grn_nfkc50_decompose_table_f09d9e[utf8[3] - 0x80]; + case 0x9f : + return grn_nfkc50_decompose_table_f09d9f[utf8[3] - 0x80]; + default : + break; + } + break; + case 0xaf : + switch (utf8[2]) { + case 0xa0 : + return grn_nfkc50_decompose_table_f0afa0[utf8[3] - 0x80]; + case 0xa1 : + return grn_nfkc50_decompose_table_f0afa1[utf8[3] - 0x80]; + case 0xa2 : + return grn_nfkc50_decompose_table_f0afa2[utf8[3] - 0x80]; + case 0xa3 : + return grn_nfkc50_decompose_table_f0afa3[utf8[3] - 0x80]; + case 0xa4 : + return grn_nfkc50_decompose_table_f0afa4[utf8[3] - 0x80]; + case 0xa5 : + return grn_nfkc50_decompose_table_f0afa5[utf8[3] - 0x80]; + case 0xa6 : + return grn_nfkc50_decompose_table_f0afa6[utf8[3] - 0x80]; + case 0xa7 : + return grn_nfkc50_decompose_table_f0afa7[utf8[3] - 0x80]; + case 0xa8 : + if (utf8[3] >= 0x80 && + utf8[3] <= 0x9d) { + return grn_nfkc50_decompose_table_f0afa8[utf8[3] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc80_table_[] = { + "\xc3\xa0", NULL, NULL, NULL, "\xc3\xa8", NULL, NULL, NULL, + "\xc3\xac", NULL, NULL, NULL, NULL, "\xc7\xb9", "\xc3\xb2", NULL, + NULL, NULL, NULL, NULL, "\xc3\xb9", NULL, "\xe1\xba\x81", NULL, + "\xe1\xbb\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_cc80_table_c3[] = { + "\xe1\xba\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbb\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "\xe1\xbb\x93", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "\xc7\x9c" +}; + +static const char *grn_nfkc50_compose_prefix_cc80_table_c4[] = { + "\xe1\xba\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xb8\x95" +}; + +static const char *grn_nfkc50_compose_prefix_cc80_table_c6[] = { + "\xe1\xbb\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\xe1\xbb\xab" +}; + +static const char *grn_nfkc50_compose_prefix_cc80_table_ce[] = { + "\xe1\xbe\xba", NULL, NULL, NULL, "\xe1\xbf\x88", NULL, "\xe1\xbf\x8a", NULL, + "\xe1\xbf\x9a", NULL, NULL, NULL, NULL, NULL, "\xe1\xbf\xb8", NULL, + NULL, NULL, NULL, NULL, "\xe1\xbf\xaa", NULL, NULL, NULL, + "\xe1\xbf\xba", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\xb0", NULL, NULL, NULL, "\xe1\xbd\xb2", NULL, "\xe1\xbd\xb4", NULL, + "\xe1\xbd\xb6", NULL, NULL, NULL, NULL, NULL, "\xe1\xbd\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_cc80_table_cf[] = { + "\xe1\xbd\xba", NULL, NULL, NULL, "\xe1\xbd\xbc", "\xe1\xbf\x92", "\xe1\xbf\xa2" +}; + +static const char *grn_nfkc50_compose_prefix_cc80_table_d0[] = { + "\xd0\x80", NULL, NULL, "\xd0\x8d", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xd1\x90", NULL, NULL, "\xd1\x9d" +}; + +static const char *grn_nfkc50_compose_prefix_cc80_table_e1bc[] = { + "\xe1\xbc\x82", "\xe1\xbc\x83", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\x8a", "\xe1\xbc\x8b", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\x92", "\xe1\xbc\x93", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\x9a", "\xe1\xbc\x9b", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xa2", "\xe1\xbc\xa3", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xaa", "\xe1\xbc\xab", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xb2", "\xe1\xbc\xb3", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xba", "\xe1\xbc\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_cc80_table_e1bd[] = { + "\xe1\xbd\x82", "\xe1\xbd\x83", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\x8a", "\xe1\xbd\x8b", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\x92", "\xe1\xbd\x93", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "\xe1\xbd\x9b", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\xa2", "\xe1\xbd\xa3", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\xaa", "\xe1\xbd\xab" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc80(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x79) { + return grn_nfkc50_compose_prefix_cc80_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc3 : + if (utf8[1] >= 0xa2 && + utf8[1] <= 0xbc) { + return grn_nfkc50_compose_prefix_cc80_table_c3[utf8[1] - 0xa2]; + } + break; + case 0xc4 : + if (utf8[1] >= 0x83 && + utf8[1] <= 0x93) { + return grn_nfkc50_compose_prefix_cc80_table_c4[utf8[1] - 0x83]; + } + break; + case 0xc5 : + if (utf8[1] == 0x8d) { + return "\xe1\xb9\x91"; + } + break; + case 0xc6 : + if (utf8[1] >= 0xa1 && + utf8[1] <= 0xb0) { + return grn_nfkc50_compose_prefix_cc80_table_c6[utf8[1] - 0xa1]; + } + break; + case 0xce : + if (utf8[1] >= 0x91 && + utf8[1] <= 0xbf) { + return grn_nfkc50_compose_prefix_cc80_table_ce[utf8[1] - 0x91]; + } + break; + case 0xcf : + if (utf8[1] >= 0x85 && + utf8[1] <= 0x8b) { + return grn_nfkc50_compose_prefix_cc80_table_cf[utf8[1] - 0x85]; + } + break; + case 0xd0 : + if (utf8[1] >= 0x95 && + utf8[1] <= 0xb8) { + return grn_nfkc50_compose_prefix_cc80_table_d0[utf8[1] - 0x95]; + } + break; + case 0xe1 : + switch (utf8[1]) { + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb9) { + return grn_nfkc50_compose_prefix_cc80_table_e1bc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xa9) { + return grn_nfkc50_compose_prefix_cc80_table_e1bd[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc81_table_[] = { + "\xc3\xa1", NULL, "\xc4\x87", NULL, "\xc3\xa9", NULL, "\xc7\xb5", NULL, + "\xc3\xad", NULL, "\xe1\xb8\xb1", "\xc4\xba", "\xe1\xb8\xbf", "\xc5\x84", "\xc3\xb3", "\xe1\xb9\x95", + NULL, "\xc5\x95", "\xc5\x9b", NULL, "\xc3\xba", NULL, "\xe1\xba\x83", NULL, + "\xc3\xbd", "\xc5\xba" +}; + +static const char *grn_nfkc50_compose_prefix_cc81_table_c3[] = { + "\xc7\xbc", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "\xc7\xbe", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xe1\xba\xa5", NULL, NULL, "\xc7\xbb", + "\xc7\xbd", "\xe1\xb8\x89", NULL, NULL, "\xe1\xba\xbf", NULL, NULL, NULL, + NULL, "\xe1\xb8\xaf", NULL, NULL, NULL, NULL, "\xe1\xbb\x91", "\xe1\xb9\x8d", + NULL, NULL, "\xc7\xbf", NULL, NULL, NULL, "\xc7\x98" +}; + +static const char *grn_nfkc50_compose_prefix_cc81_table_c4[] = { + "\xe1\xba\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xb8\x97" +}; + +static const char *grn_nfkc50_compose_prefix_cc81_table_c5[] = { + "\xe1\xb9\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xe1\xb9\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_cc81_table_c6[] = { + "\xe1\xbb\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\xe1\xbb\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_cc81_table_ce[] = { + "\xce\x86", NULL, NULL, NULL, "\xce\x88", NULL, "\xce\x89", NULL, + "\xce\x8a", NULL, NULL, NULL, NULL, NULL, "\xce\x8c", NULL, + NULL, NULL, NULL, NULL, "\xce\x8e", NULL, NULL, NULL, + "\xce\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xce\xac", NULL, NULL, NULL, "\xce\xad", NULL, "\xce\xae", NULL, + "\xce\xaf", NULL, NULL, NULL, NULL, NULL, "\xcf\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_cc81_table_cf[] = { + "\xcf\x8d", NULL, NULL, NULL, "\xcf\x8e", "\xce\x90", "\xce\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_cc81_table_d0[] = { + "\xd0\x83", NULL, NULL, NULL, NULL, NULL, NULL, "\xd0\x8c", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xd1\x93", NULL, NULL, NULL, NULL, NULL, NULL, "\xd1\x9c" +}; + +static const char *grn_nfkc50_compose_prefix_cc81_table_e1bc[] = { + "\xe1\xbc\x84", "\xe1\xbc\x85", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\x8c", "\xe1\xbc\x8d", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\x94", "\xe1\xbc\x95", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\x9c", "\xe1\xbc\x9d", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xa4", "\xe1\xbc\xa5", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xac", "\xe1\xbc\xad", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xb4", "\xe1\xbc\xb5", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xbc", "\xe1\xbc\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_cc81_table_e1bd[] = { + "\xe1\xbd\x84", "\xe1\xbd\x85", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\x8c", "\xe1\xbd\x8d", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\x94", "\xe1\xbd\x95", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "\xe1\xbd\x9d", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\xa4", "\xe1\xbd\xa5", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\xac", "\xe1\xbd\xad" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc81(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x7a) { + return grn_nfkc50_compose_prefix_cc81_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc3 : + if (utf8[1] >= 0x86 && + utf8[1] <= 0xbc) { + return grn_nfkc50_compose_prefix_cc81_table_c3[utf8[1] - 0x86]; + } + break; + case 0xc4 : + if (utf8[1] >= 0x83 && + utf8[1] <= 0x93) { + return grn_nfkc50_compose_prefix_cc81_table_c4[utf8[1] - 0x83]; + } + break; + case 0xc5 : + if (utf8[1] >= 0x8d && + utf8[1] <= 0xa9) { + return grn_nfkc50_compose_prefix_cc81_table_c5[utf8[1] - 0x8d]; + } + break; + case 0xc6 : + if (utf8[1] >= 0xa1 && + utf8[1] <= 0xb0) { + return grn_nfkc50_compose_prefix_cc81_table_c6[utf8[1] - 0xa1]; + } + break; + case 0xce : + if (utf8[1] >= 0x91 && + utf8[1] <= 0xbf) { + return grn_nfkc50_compose_prefix_cc81_table_ce[utf8[1] - 0x91]; + } + break; + case 0xcf : + if (utf8[1] >= 0x85 && + utf8[1] <= 0x8b) { + return grn_nfkc50_compose_prefix_cc81_table_cf[utf8[1] - 0x85]; + } + break; + case 0xd0 : + if (utf8[1] >= 0x93 && + utf8[1] <= 0xba) { + return grn_nfkc50_compose_prefix_cc81_table_d0[utf8[1] - 0x93]; + } + break; + case 0xe1 : + switch (utf8[1]) { + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb9) { + return grn_nfkc50_compose_prefix_cc81_table_e1bc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xa9) { + return grn_nfkc50_compose_prefix_cc81_table_e1bd[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc82_table_[] = { + "\xc3\xa2", NULL, "\xc4\x89", NULL, "\xc3\xaa", NULL, "\xc4\x9d", "\xc4\xa5", + "\xc3\xae", "\xc4\xb5", NULL, NULL, NULL, NULL, "\xc3\xb4", NULL, + NULL, NULL, "\xc5\x9d", NULL, "\xc3\xbb", NULL, "\xc5\xb5", NULL, + "\xc5\xb7", "\xe1\xba\x91" +}; + +static const char *grn_nfkc50_compose_prefix_cc82_table_e1ba[] = { + "\xe1\xba\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbb\x87" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc82(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x7a) { + return grn_nfkc50_compose_prefix_cc82_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0xba : + if (utf8[2] >= 0xa1 && + utf8[2] <= 0xb9) { + return grn_nfkc50_compose_prefix_cc82_table_e1ba[utf8[2] - 0xa1]; + } + break; + case 0xbb : + if (utf8[2] == 0x8d) { + return "\xe1\xbb\x99"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc83_table_[] = { + "\xc3\xa3", NULL, NULL, NULL, "\xe1\xba\xbd", NULL, NULL, NULL, + "\xc4\xa9", NULL, NULL, NULL, NULL, "\xc3\xb1", "\xc3\xb5", NULL, + NULL, NULL, NULL, NULL, "\xc5\xa9", "\xe1\xb9\xbd", NULL, NULL, + "\xe1\xbb\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_cc83_table_c3[] = { + "\xe1\xba\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbb\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "\xe1\xbb\x97" +}; + +static const char *grn_nfkc50_compose_prefix_cc83_table_c6[] = { + "\xe1\xbb\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\xe1\xbb\xaf" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc83(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x79) { + return grn_nfkc50_compose_prefix_cc83_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc3 : + if (utf8[1] >= 0xa2 && + utf8[1] <= 0xb4) { + return grn_nfkc50_compose_prefix_cc83_table_c3[utf8[1] - 0xa2]; + } + break; + case 0xc4 : + if (utf8[1] == 0x83) { + return "\xe1\xba\xb5"; + } + break; + case 0xc6 : + if (utf8[1] >= 0xa1 && + utf8[1] <= 0xb0) { + return grn_nfkc50_compose_prefix_cc83_table_c6[utf8[1] - 0xa1]; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc88_table_[] = { + "\xc3\xa4", NULL, NULL, NULL, "\xc3\xab", NULL, NULL, "\xe1\xb8\xa7", + "\xc3\xaf", NULL, NULL, NULL, NULL, NULL, "\xc3\xb6", NULL, + NULL, NULL, NULL, "\xe1\xba\x97", "\xc3\xbc", NULL, "\xe1\xba\x85", "\xe1\xba\x8d", + "\xc3\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_cc88_table_ce[] = { + "\xce\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xce\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xcf\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_cc88_table_d0[] = { + "\xd0\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "\xd3\x92", NULL, NULL, NULL, NULL, "\xd0\x81", + "\xd3\x9c", "\xd3\x9e", "\xd3\xa4", NULL, NULL, NULL, NULL, NULL, + "\xd3\xa6", NULL, NULL, NULL, NULL, "\xd3\xb0", NULL, NULL, + NULL, "\xd3\xb4", NULL, NULL, NULL, "\xd3\xb8", NULL, "\xd3\xac", + NULL, NULL, "\xd3\x93", NULL, NULL, NULL, NULL, "\xd1\x91", + "\xd3\x9d", "\xd3\x9f", "\xd3\xa5", NULL, NULL, NULL, NULL, NULL, + "\xd3\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_cc88_table_d1[] = { + "\xd3\xb1", NULL, NULL, NULL, "\xd3\xb5", NULL, NULL, NULL, + "\xd3\xb9", NULL, "\xd3\xad", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "\xd1\x97" +}; + +static const char *grn_nfkc50_compose_prefix_cc88_table_d3[] = { + "\xd3\x9a", "\xd3\x9b", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xd3\xaa", "\xd3\xab" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc88(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x79) { + return grn_nfkc50_compose_prefix_cc88_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc3 : + if (utf8[1] == 0xb5) { + return "\xe1\xb9\x8f"; + } + break; + case 0xc5 : + if (utf8[1] == 0xab) { + return "\xe1\xb9\xbb"; + } + break; + case 0xce : + if (utf8[1] >= 0x99 && + utf8[1] <= 0xb9) { + return grn_nfkc50_compose_prefix_cc88_table_ce[utf8[1] - 0x99]; + } + break; + case 0xcf : + if (utf8[1] == 0x85) { + return "\xcf\x8b"; + } + break; + case 0xd0 : + if (utf8[1] >= 0x86 && + utf8[1] <= 0xbe) { + return grn_nfkc50_compose_prefix_cc88_table_d0[utf8[1] - 0x86]; + } + break; + case 0xd1 : + if (utf8[1] >= 0x83 && + utf8[1] <= 0x96) { + return grn_nfkc50_compose_prefix_cc88_table_d1[utf8[1] - 0x83]; + } + break; + case 0xd3 : + if (utf8[1] >= 0x98 && + utf8[1] <= 0xa9) { + return grn_nfkc50_compose_prefix_cc88_table_d3[utf8[1] - 0x98]; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc8a_table_[] = { + "\xc3\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xc5\xaf", NULL, "\xe1\xba\x98", NULL, + "\xe1\xba\x99" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc8a(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x79) { + return grn_nfkc50_compose_prefix_cc8a_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cca7_table_[] = { + "\xc3\xa7", "\xe1\xb8\x91", "\xc8\xa9", NULL, "\xc4\xa3", "\xe1\xb8\xa9", NULL, NULL, + "\xc4\xb7", "\xc4\xbc", NULL, "\xc5\x86", NULL, NULL, NULL, "\xc5\x97", + "\xc5\x9f", "\xc5\xa3" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cca7(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x63 && + utf8[0] <= 0x74) { + return grn_nfkc50_compose_prefix_cca7_table_[utf8[0] - 0x63]; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc84_table_[] = { + "\xc4\x81", NULL, NULL, NULL, "\xc4\x93", NULL, "\xe1\xb8\xa1", NULL, + "\xc4\xab", NULL, NULL, NULL, NULL, NULL, "\xc5\x8d", NULL, + NULL, NULL, NULL, NULL, "\xc5\xab", NULL, NULL, NULL, + "\xc8\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_cc84_table_c3[] = { + "\xc7\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, "\xc7\x9f", NULL, + "\xc7\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\xc8\xad", + "\xc8\xab", NULL, NULL, NULL, NULL, NULL, "\xc7\x96" +}; + +static const char *grn_nfkc50_compose_prefix_cc84_table_c8[] = { + "\xc7\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xc8\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_cc84_table_ce[] = { + "\xe1\xbe\xb9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbf\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xe1\xbf\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbe\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbf\x91" +}; + +static const char *grn_nfkc50_compose_prefix_cc84_table_d0[] = { + "\xd3\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "\xd3\xae", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xd3\xa3" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc84(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x79) { + return grn_nfkc50_compose_prefix_cc84_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc3 : + if (utf8[1] >= 0x86 && + utf8[1] <= 0xbc) { + return grn_nfkc50_compose_prefix_cc84_table_c3[utf8[1] - 0x86]; + } + break; + case 0xc7 : + if (utf8[1] == 0xab) { + return "\xc7\xad"; + } + break; + case 0xc8 : + if (utf8[1] >= 0xa7 && + utf8[1] <= 0xaf) { + return grn_nfkc50_compose_prefix_cc84_table_c8[utf8[1] - 0xa7]; + } + break; + case 0xce : + if (utf8[1] >= 0x91 && + utf8[1] <= 0xb9) { + return grn_nfkc50_compose_prefix_cc84_table_ce[utf8[1] - 0x91]; + } + break; + case 0xcf : + if (utf8[1] == 0x85) { + return "\xe1\xbf\xa1"; + } + break; + case 0xd0 : + if (utf8[1] >= 0x98 && + utf8[1] <= 0xb8) { + return grn_nfkc50_compose_prefix_cc84_table_d0[utf8[1] - 0x98]; + } + break; + case 0xd1 : + if (utf8[1] == 0x83) { + return "\xd3\xaf"; + } + break; + case 0xe1 : + switch (utf8[1]) { + case 0xb8 : + if (utf8[2] == 0xb7) { + return "\xe1\xb8\xb9"; + } + break; + case 0xb9 : + if (utf8[2] == 0x9b) { + return "\xe1\xb9\x9d"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc86_table_[] = { + "\xc4\x83", NULL, NULL, NULL, "\xc4\x95", NULL, "\xc4\x9f", NULL, + "\xc4\xad", NULL, NULL, NULL, NULL, NULL, "\xc5\x8f", NULL, + NULL, NULL, NULL, NULL, "\xc5\xad" +}; + +static const char *grn_nfkc50_compose_prefix_cc86_table_ce[] = { + "\xe1\xbe\xb8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbf\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xe1\xbf\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbe\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbf\x90" +}; + +static const char *grn_nfkc50_compose_prefix_cc86_table_d0[] = { + "\xd3\x90", NULL, NULL, NULL, NULL, "\xd3\x96", "\xd3\x81", NULL, + "\xd0\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "\xd0\x8e", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xd3\x91", NULL, NULL, NULL, NULL, "\xd3\x97", "\xd3\x82", NULL, + "\xd0\xb9" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc86(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x75) { + return grn_nfkc50_compose_prefix_cc86_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc8 : + if (utf8[1] == 0xa9) { + return "\xe1\xb8\x9d"; + } + break; + case 0xce : + if (utf8[1] >= 0x91 && + utf8[1] <= 0xb9) { + return grn_nfkc50_compose_prefix_cc86_table_ce[utf8[1] - 0x91]; + } + break; + case 0xcf : + if (utf8[1] == 0x85) { + return "\xe1\xbf\xa0"; + } + break; + case 0xd0 : + if (utf8[1] >= 0x90 && + utf8[1] <= 0xb8) { + return grn_nfkc50_compose_prefix_cc86_table_d0[utf8[1] - 0x90]; + } + break; + case 0xd1 : + if (utf8[1] == 0x83) { + return "\xd1\x9e"; + } + break; + case 0xe1 : + switch (utf8[1]) { + case 0xba : + if (utf8[2] == 0xa1) { + return "\xe1\xba\xb7"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cca8_table_[] = { + "\xc4\x85", NULL, NULL, NULL, "\xc4\x99", NULL, NULL, NULL, + "\xc4\xaf", NULL, NULL, NULL, NULL, NULL, "\xc7\xab", NULL, + NULL, NULL, NULL, NULL, "\xc5\xb3" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cca8(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x75) { + return grn_nfkc50_compose_prefix_cca8_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc87_table_[] = { + "\xc8\xa7", "\xe1\xb8\x83", "\xc4\x8b", "\xe1\xb8\x8b", "\xc4\x97", "\xe1\xb8\x9f", "\xc4\xa1", "\xe1\xb8\xa3", + NULL, NULL, NULL, NULL, "\xe1\xb9\x81", "\xe1\xb9\x85", "\xc8\xaf", "\xe1\xb9\x97", + NULL, "\xe1\xb9\x99", "\xe1\xb9\xa1", "\xe1\xb9\xab", NULL, NULL, "\xe1\xba\x87", "\xe1\xba\x8b", + "\xe1\xba\x8f", "\xc5\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_cc87_table_c5[] = { + "\xe1\xb9\xa5", NULL, NULL, NULL, NULL, NULL, "\xe1\xb9\xa7" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc87(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x7a) { + return grn_nfkc50_compose_prefix_cc87_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc5 : + if (utf8[1] >= 0x9b && + utf8[1] <= 0xa1) { + return grn_nfkc50_compose_prefix_cc87_table_c5[utf8[1] - 0x9b]; + } + break; + case 0xe1 : + switch (utf8[1]) { + case 0xb9 : + if (utf8[2] == 0xa3) { + return "\xe1\xb9\xa9"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc8c_table_[] = { + "\xc7\x8e", NULL, "\xc4\x8d", "\xc4\x8f", "\xc4\x9b", NULL, "\xc7\xa7", "\xc8\x9f", + "\xc7\x90", "\xc7\xb0", "\xc7\xa9", "\xc4\xbe", NULL, "\xc5\x88", "\xc7\x92", NULL, + NULL, "\xc5\x99", "\xc5\xa1", "\xc5\xa5", "\xc7\x94", NULL, NULL, NULL, + NULL, "\xc5\xbe" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc8c(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x7a) { + return grn_nfkc50_compose_prefix_cc8c_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc3 : + if (utf8[1] == 0xbc) { + return "\xc7\x9a"; + } + break; + case 0xc6 : + if (utf8[1] == 0xb7) { + return "\xc7\xae"; + } + break; + case 0xca : + if (utf8[1] == 0x92) { + return "\xc7\xaf"; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc8b_table_[] = { + "\xc5\x91", NULL, NULL, NULL, NULL, NULL, "\xc5\xb1" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc8b(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x6f && + utf8[0] <= 0x75) { + return grn_nfkc50_compose_prefix_cc8b_table_[utf8[0] - 0x6f]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xd0 : + if (utf8[1] == 0xa3) { + return "\xd3\xb2"; + } + break; + case 0xd1 : + if (utf8[1] == 0x83) { + return "\xd3\xb3"; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc9b_table_[] = { + "\xc6\xa1", NULL, NULL, NULL, NULL, NULL, "\xc6\xb0" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc9b(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x6f && + utf8[0] <= 0x75) { + return grn_nfkc50_compose_prefix_cc9b_table_[utf8[0] - 0x6f]; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc8f_table_[] = { + "\xc8\x81", NULL, NULL, NULL, "\xc8\x85", NULL, NULL, NULL, + "\xc8\x89", NULL, NULL, NULL, NULL, NULL, "\xc8\x8d", NULL, + NULL, "\xc8\x91", NULL, NULL, "\xc8\x95" +}; + +static const char *grn_nfkc50_compose_prefix_cc8f_table_d1[] = { + "\xd1\xb6", "\xd1\xb7" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc8f(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x75) { + return grn_nfkc50_compose_prefix_cc8f_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xd1 : + if (utf8[1] >= 0xb4 && + utf8[1] <= 0xb5) { + return grn_nfkc50_compose_prefix_cc8f_table_d1[utf8[1] - 0xb4]; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc91_table_[] = { + "\xc8\x83", NULL, NULL, NULL, "\xc8\x87", NULL, NULL, NULL, + "\xc8\x8b", NULL, NULL, NULL, NULL, NULL, "\xc8\x8f", NULL, + NULL, "\xc8\x93", NULL, NULL, "\xc8\x97" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc91(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x75) { + return grn_nfkc50_compose_prefix_cc91_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cca6_table_[] = { + "\xc8\x99", "\xc8\x9b" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cca6(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x73 && + utf8[0] <= 0x74) { + return grn_nfkc50_compose_prefix_cca6_table_[utf8[0] - 0x73]; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_d993(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xd8 : + if (utf8[1] == 0xa7) { + return "\xd8\xa2"; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_d994_table_d9[] = { + "\xd8\xa4", NULL, "\xd8\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_d994_table_db[] = { + "\xdb\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "\xdb\x93", NULL, NULL, "\xdb\x80" +}; + +static inline const char * +grn_nfkc50_compose_prefix_d994(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xd8 : + if (utf8[1] == 0xa7) { + return "\xd8\xa3"; + } + break; + case 0xd9 : + if (utf8[1] >= 0x88 && + utf8[1] <= 0x8a) { + return grn_nfkc50_compose_prefix_d994_table_d9[utf8[1] - 0x88]; + } + break; + case 0xdb : + if (utf8[1] >= 0x81 && + utf8[1] <= 0x95) { + return grn_nfkc50_compose_prefix_d994_table_db[utf8[1] - 0x81]; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_d995(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xd8 : + if (utf8[1] == 0xa7) { + return "\xd8\xa5"; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e0a4bc_table_e0a4[] = { + "\xe0\xa4\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe0\xa4\xb1", NULL, NULL, "\xe0\xa4\xb4" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e0a4bc(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xa4 : + if (utf8[2] >= 0xa8 && + utf8[2] <= 0xb3) { + return grn_nfkc50_compose_prefix_e0a4bc_table_e0a4[utf8[2] - 0xa8]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0a6be(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xa7 : + if (utf8[2] == 0x87) { + return "\xe0\xa7\x8b"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0a797(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xa7 : + if (utf8[2] == 0x87) { + return "\xe0\xa7\x8c"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0ad96(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xad : + if (utf8[2] == 0x87) { + return "\xe0\xad\x88"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0acbe(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xad : + if (utf8[2] == 0x87) { + return "\xe0\xad\x8b"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0ad97(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xad : + if (utf8[2] == 0x87) { + return "\xe0\xad\x8c"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0af97(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xae : + if (utf8[2] == 0x92) { + return "\xe0\xae\x94"; + } + break; + case 0xaf : + if (utf8[2] == 0x86) { + return "\xe0\xaf\x8c"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e0aebe_table_e0af[] = { + "\xe0\xaf\x8a", "\xe0\xaf\x8b" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e0aebe(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xaf : + if (utf8[2] >= 0x86 && + utf8[2] <= 0x87) { + return grn_nfkc50_compose_prefix_e0aebe_table_e0af[utf8[2] - 0x86]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0b196(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xb1 : + if (utf8[2] == 0x86) { + return "\xe0\xb1\x88"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e0b395_table_e0b3[] = { + "\xe0\xb3\x87", NULL, NULL, NULL, "\xe0\xb3\x8b" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e0b395(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xb2 : + if (utf8[2] == 0xbf) { + return "\xe0\xb3\x80"; + } + break; + case 0xb3 : + if (utf8[2] >= 0x86 && + utf8[2] <= 0x8a) { + return grn_nfkc50_compose_prefix_e0b395_table_e0b3[utf8[2] - 0x86]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0b396(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xb3 : + if (utf8[2] == 0x86) { + return "\xe0\xb3\x88"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0b382(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xb3 : + if (utf8[2] == 0x86) { + return "\xe0\xb3\x8a"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e0b4be_table_e0b5[] = { + "\xe0\xb5\x8a", "\xe0\xb5\x8b" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e0b4be(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xb5 : + if (utf8[2] >= 0x86 && + utf8[2] <= 0x87) { + return grn_nfkc50_compose_prefix_e0b4be_table_e0b5[utf8[2] - 0x86]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0b597(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xb5 : + if (utf8[2] == 0x86) { + return "\xe0\xb5\x8c"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e0b78a_table_e0b7[] = { + "\xe0\xb7\x9a", NULL, NULL, "\xe0\xb7\x9d" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e0b78a(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xb7 : + if (utf8[2] >= 0x99 && + utf8[2] <= 0x9c) { + return grn_nfkc50_compose_prefix_e0b78a_table_e0b7[utf8[2] - 0x99]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0b78f(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xb7 : + if (utf8[2] == 0x99) { + return "\xe0\xb7\x9c"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e0b79f(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe0 : + switch (utf8[1]) { + case 0xb7 : + if (utf8[2] == 0x99) { + return "\xe0\xb7\x9e"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_e180ae(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] == 0xa5) { + return "\xe1\x80\xa6"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e1acb5_table_e1ac[] = { + "\xe1\xac\x86", NULL, "\xe1\xac\x88", NULL, "\xe1\xac\x8a", NULL, "\xe1\xac\x8c", NULL, + "\xe1\xac\x8e", NULL, NULL, NULL, "\xe1\xac\x92", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, "\xe1\xac\xbb", NULL, "\xe1\xac\xbd", + NULL, "\xe1\xad\x80", "\xe1\xad\x81" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e1acb5(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0xac : + if (utf8[2] >= 0x85 && + utf8[2] <= 0xbf) { + return grn_nfkc50_compose_prefix_e1acb5_table_e1ac[utf8[2] - 0x85]; + } + break; + case 0xad : + if (utf8[2] == 0x82) { + return "\xe1\xad\x83"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_cca5(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] == 0x61) { + return "\xe1\xb8\x81"; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cca3_table_[] = { + "\xe1\xba\xa1", "\xe1\xb8\x85", NULL, "\xe1\xb8\x8d", "\xe1\xba\xb9", NULL, NULL, "\xe1\xb8\xa5", + "\xe1\xbb\x8b", NULL, "\xe1\xb8\xb3", "\xe1\xb8\xb7", "\xe1\xb9\x83", "\xe1\xb9\x87", "\xe1\xbb\x8d", NULL, + NULL, "\xe1\xb9\x9b", "\xe1\xb9\xa3", "\xe1\xb9\xad", "\xe1\xbb\xa5", "\xe1\xb9\xbf", "\xe1\xba\x89", NULL, + "\xe1\xbb\xb5", "\xe1\xba\x93" +}; + +static const char *grn_nfkc50_compose_prefix_cca3_table_c6[] = { + "\xe1\xbb\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\xe1\xbb\xb1" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cca3(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x7a) { + return grn_nfkc50_compose_prefix_cca3_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc6 : + if (utf8[1] >= 0xa1 && + utf8[1] <= 0xb0) { + return grn_nfkc50_compose_prefix_cca3_table_c6[utf8[1] - 0xa1]; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_ccb1_table_[] = { + "\xe1\xb8\x87", NULL, "\xe1\xb8\x8f", NULL, NULL, NULL, "\xe1\xba\x96", NULL, + NULL, "\xe1\xb8\xb5", "\xe1\xb8\xbb", NULL, "\xe1\xb9\x89", NULL, NULL, NULL, + "\xe1\xb9\x9f", NULL, "\xe1\xb9\xaf", NULL, NULL, NULL, NULL, NULL, + "\xe1\xba\x95" +}; + +static inline const char * +grn_nfkc50_compose_prefix_ccb1(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x62 && + utf8[0] <= 0x7a) { + return grn_nfkc50_compose_prefix_ccb1_table_[utf8[0] - 0x62]; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_ccad_table_[] = { + "\xe1\xb8\x93", "\xe1\xb8\x99", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xb8\xbd", NULL, "\xe1\xb9\x8b", NULL, NULL, NULL, NULL, NULL, + "\xe1\xb9\xb1", "\xe1\xb9\xb7" +}; + +static inline const char * +grn_nfkc50_compose_prefix_ccad(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x64 && + utf8[0] <= 0x75) { + return grn_nfkc50_compose_prefix_ccad_table_[utf8[0] - 0x64]; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_ccb0_table_[] = { + "\xe1\xb8\x9b", NULL, NULL, NULL, "\xe1\xb8\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xb9\xb5" +}; + +static inline const char * +grn_nfkc50_compose_prefix_ccb0(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x65 && + utf8[0] <= 0x75) { + return grn_nfkc50_compose_prefix_ccb0_table_[utf8[0] - 0x65]; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_ccae(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] == 0x68) { + return "\xe1\xb8\xab"; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static inline const char * +grn_nfkc50_compose_prefix_cca4(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] == 0x75) { + return "\xe1\xb9\xb3"; + } else { + return NULL; + } + } else { + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc89_table_[] = { + "\xe1\xba\xa3", NULL, NULL, NULL, "\xe1\xba\xbb", NULL, NULL, NULL, + "\xe1\xbb\x89", NULL, NULL, NULL, NULL, NULL, "\xe1\xbb\x8f", NULL, + NULL, NULL, NULL, NULL, "\xe1\xbb\xa7", NULL, NULL, NULL, + "\xe1\xbb\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_cc89_table_c3[] = { + "\xe1\xba\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbb\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, "\xe1\xbb\x95" +}; + +static const char *grn_nfkc50_compose_prefix_cc89_table_c6[] = { + "\xe1\xbb\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\xe1\xbb\xad" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc89(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x61 && + utf8[0] <= 0x79) { + return grn_nfkc50_compose_prefix_cc89_table_[utf8[0] - 0x61]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xc3 : + if (utf8[1] >= 0xa2 && + utf8[1] <= 0xb4) { + return grn_nfkc50_compose_prefix_cc89_table_c3[utf8[1] - 0xa2]; + } + break; + case 0xc4 : + if (utf8[1] == 0x83) { + return "\xe1\xba\xb3"; + } + break; + case 0xc6 : + if (utf8[1] >= 0xa1 && + utf8[1] <= 0xb0) { + return grn_nfkc50_compose_prefix_cc89_table_c6[utf8[1] - 0xa1]; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc93_table_ce[] = { + "\xe1\xbc\x88", NULL, NULL, NULL, "\xe1\xbc\x98", NULL, "\xe1\xbc\xa8", NULL, + "\xe1\xbc\xb8", NULL, NULL, NULL, NULL, NULL, "\xe1\xbd\x88", NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\x80", NULL, NULL, NULL, "\xe1\xbc\x90", NULL, "\xe1\xbc\xa0", NULL, + "\xe1\xbc\xb0", NULL, NULL, NULL, NULL, NULL, "\xe1\xbd\x80" +}; + +static const char *grn_nfkc50_compose_prefix_cc93_table_cf[] = { + "\xe1\xbf\xa4", NULL, NULL, NULL, "\xe1\xbd\x90", NULL, NULL, NULL, + "\xe1\xbd\xa0" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc93(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xce : + if (utf8[1] >= 0x91 && + utf8[1] <= 0xbf) { + return grn_nfkc50_compose_prefix_cc93_table_ce[utf8[1] - 0x91]; + } + break; + case 0xcf : + if (utf8[1] >= 0x81 && + utf8[1] <= 0x89) { + return grn_nfkc50_compose_prefix_cc93_table_cf[utf8[1] - 0x81]; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cc94_table_ce[] = { + "\xe1\xbc\x89", NULL, NULL, NULL, "\xe1\xbc\x99", NULL, "\xe1\xbc\xa9", NULL, + "\xe1\xbc\xb9", NULL, NULL, NULL, NULL, NULL, "\xe1\xbd\x89", NULL, + "\xe1\xbf\xac", NULL, NULL, NULL, "\xe1\xbd\x99", NULL, NULL, NULL, + "\xe1\xbd\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\x81", NULL, NULL, NULL, "\xe1\xbc\x91", NULL, "\xe1\xbc\xa1", NULL, + "\xe1\xbc\xb1", NULL, NULL, NULL, NULL, NULL, "\xe1\xbd\x81" +}; + +static const char *grn_nfkc50_compose_prefix_cc94_table_cf[] = { + "\xe1\xbf\xa5", NULL, NULL, NULL, "\xe1\xbd\x91", NULL, NULL, NULL, + "\xe1\xbd\xa1" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cc94(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xce : + if (utf8[1] >= 0x91 && + utf8[1] <= 0xbf) { + return grn_nfkc50_compose_prefix_cc94_table_ce[utf8[1] - 0x91]; + } + break; + case 0xcf : + if (utf8[1] >= 0x81 && + utf8[1] <= 0x89) { + return grn_nfkc50_compose_prefix_cc94_table_cf[utf8[1] - 0x81]; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cd82_table_ce[] = { + "\xe1\xbe\xb6", NULL, NULL, NULL, NULL, NULL, "\xe1\xbf\x86", NULL, + "\xe1\xbf\x96" +}; + +static const char *grn_nfkc50_compose_prefix_cd82_table_cf[] = { + "\xe1\xbf\xa6", NULL, NULL, NULL, "\xe1\xbf\xb6", "\xe1\xbf\x97", "\xe1\xbf\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_cd82_table_e1bc[] = { + "\xe1\xbc\x86", "\xe1\xbc\x87", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\x8e", "\xe1\xbc\x8f", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xa6", "\xe1\xbc\xa7", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xae", "\xe1\xbc\xaf", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xb6", "\xe1\xbc\xb7", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbc\xbe", "\xe1\xbc\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_cd82_table_e1bd[] = { + "\xe1\xbd\x96", "\xe1\xbd\x97", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "\xe1\xbd\x9f", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\xa6", "\xe1\xbd\xa7", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbd\xae", "\xe1\xbd\xaf" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cd82(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xce : + if (utf8[1] >= 0xb1 && + utf8[1] <= 0xb9) { + return grn_nfkc50_compose_prefix_cd82_table_ce[utf8[1] - 0xb1]; + } + break; + case 0xcf : + if (utf8[1] >= 0x85 && + utf8[1] <= 0x8b) { + return grn_nfkc50_compose_prefix_cd82_table_cf[utf8[1] - 0x85]; + } + break; + case 0xe1 : + switch (utf8[1]) { + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb9) { + return grn_nfkc50_compose_prefix_cd82_table_e1bc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xa9) { + return grn_nfkc50_compose_prefix_cd82_table_e1bd[utf8[2] - 0x90]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_cd85_table_ce[] = { + "\xe1\xbe\xbc", NULL, NULL, NULL, NULL, NULL, "\xe1\xbf\x8c", NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbf\xbc", NULL, NULL, "\xe1\xbe\xb4", NULL, "\xe1\xbf\x84", NULL, NULL, + "\xe1\xbe\xb3", NULL, NULL, NULL, NULL, NULL, "\xe1\xbf\x83" +}; + +static const char *grn_nfkc50_compose_prefix_cd85_table_cf[] = { + "\xe1\xbf\xb3", NULL, NULL, NULL, NULL, "\xe1\xbf\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_cd85_table_e1bc[] = { + "\xe1\xbe\x80", "\xe1\xbe\x81", "\xe1\xbe\x82", "\xe1\xbe\x83", "\xe1\xbe\x84", "\xe1\xbe\x85", "\xe1\xbe\x86", "\xe1\xbe\x87", + "\xe1\xbe\x88", "\xe1\xbe\x89", "\xe1\xbe\x8a", "\xe1\xbe\x8b", "\xe1\xbe\x8c", "\xe1\xbe\x8d", "\xe1\xbe\x8e", "\xe1\xbe\x8f", + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbe\x90", "\xe1\xbe\x91", "\xe1\xbe\x92", "\xe1\xbe\x93", "\xe1\xbe\x94", "\xe1\xbe\x95", "\xe1\xbe\x96", "\xe1\xbe\x97", + "\xe1\xbe\x98", "\xe1\xbe\x99", "\xe1\xbe\x9a", "\xe1\xbe\x9b", "\xe1\xbe\x9c", "\xe1\xbe\x9d", "\xe1\xbe\x9e", "\xe1\xbe\x9f" +}; + +static const char *grn_nfkc50_compose_prefix_cd85_table_e1bd[] = { + "\xe1\xbe\xa0", "\xe1\xbe\xa1", "\xe1\xbe\xa2", "\xe1\xbe\xa3", "\xe1\xbe\xa4", "\xe1\xbe\xa5", "\xe1\xbe\xa6", "\xe1\xbe\xa7", + "\xe1\xbe\xa8", "\xe1\xbe\xa9", "\xe1\xbe\xaa", "\xe1\xbe\xab", "\xe1\xbe\xac", "\xe1\xbe\xad", "\xe1\xbe\xae", "\xe1\xbe\xaf", + "\xe1\xbe\xb2", NULL, NULL, NULL, "\xe1\xbf\x82", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xe1\xbf\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_cd85_table_e1bf[] = { + "\xe1\xbf\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe1\xbf\xb7" +}; + +static inline const char * +grn_nfkc50_compose_prefix_cd85(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xce : + if (utf8[1] >= 0x91 && + utf8[1] <= 0xb7) { + return grn_nfkc50_compose_prefix_cd85_table_ce[utf8[1] - 0x91]; + } + break; + case 0xcf : + if (utf8[1] >= 0x89 && + utf8[1] <= 0x8e) { + return grn_nfkc50_compose_prefix_cd85_table_cf[utf8[1] - 0x89]; + } + break; + case 0xe1 : + switch (utf8[1]) { + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xaf) { + return grn_nfkc50_compose_prefix_cd85_table_e1bc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0xa0 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_cd85_table_e1bd[utf8[2] - 0xa0]; + } + break; + case 0xbe : + if (utf8[2] == 0xb6) { + return "\xe1\xbe\xb7"; + } + break; + case 0xbf : + if (utf8[2] >= 0x86 && + utf8[2] <= 0xb6) { + return grn_nfkc50_compose_prefix_cd85_table_e1bf[utf8[2] - 0x86]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_ccb8_table_[] = { + "\xe2\x89\xae", "\xe2\x89\xa0", "\xe2\x89\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_ccb8_table_e286[] = { + "\xe2\x86\x9a", NULL, "\xe2\x86\x9b", NULL, "\xe2\x86\xae" +}; + +static const char *grn_nfkc50_compose_prefix_ccb8_table_e287[] = { + "\xe2\x87\x8d", NULL, "\xe2\x87\x8f", NULL, "\xe2\x87\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_ccb8_table_e288[] = { + "\xe2\x88\x84", NULL, NULL, NULL, NULL, "\xe2\x88\x89", NULL, NULL, + "\xe2\x88\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe2\x88\xa4", NULL, "\xe2\x88\xa6", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "\xe2\x89\x81" +}; + +static const char *grn_nfkc50_compose_prefix_ccb8_table_e289[] = { + "\xe2\x89\x84", NULL, "\xe2\x89\x87", NULL, NULL, "\xe2\x89\x89", NULL, NULL, + NULL, NULL, "\xe2\x89\xad", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, "\xe2\x89\xa2", NULL, + NULL, "\xe2\x89\xb0", "\xe2\x89\xb1", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\xe2\x89\xb4", + "\xe2\x89\xb5", NULL, NULL, "\xe2\x89\xb8", "\xe2\x89\xb9", NULL, NULL, "\xe2\x8a\x80", + "\xe2\x8a\x81", "\xe2\x8b\xa0", "\xe2\x8b\xa1" +}; + +static const char *grn_nfkc50_compose_prefix_ccb8_table_e28a[] = { + "\xe2\x8a\x84", "\xe2\x8a\x85", NULL, NULL, "\xe2\x8a\x88", "\xe2\x8a\x89", NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\xe2\x8b\xa2", + "\xe2\x8b\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xe2\x8a\xac", NULL, NULL, NULL, NULL, NULL, "\xe2\x8a\xad", "\xe2\x8a\xae", + NULL, "\xe2\x8a\xaf", NULL, NULL, NULL, NULL, NULL, NULL, + "\xe2\x8b\xaa", "\xe2\x8b\xab", "\xe2\x8b\xac", "\xe2\x8b\xad" +}; + +static inline const char * +grn_nfkc50_compose_prefix_ccb8(const unsigned char *utf8) +{ + if (utf8[0] < 0x80) { + if (utf8[0] >= 0x3c && + utf8[0] <= 0x3e) { + return grn_nfkc50_compose_prefix_ccb8_table_[utf8[0] - 0x3c]; + } else { + return NULL; + } + } else { + switch (utf8[0]) { + case 0xe2 : + switch (utf8[1]) { + case 0x86 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0x94) { + return grn_nfkc50_compose_prefix_ccb8_table_e286[utf8[2] - 0x90]; + } + break; + case 0x87 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0x94) { + return grn_nfkc50_compose_prefix_ccb8_table_e287[utf8[2] - 0x90]; + } + break; + case 0x88 : + if (utf8[2] >= 0x83 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_ccb8_table_e288[utf8[2] - 0x83]; + } + break; + case 0x89 : + if (utf8[2] >= 0x83 && + utf8[2] <= 0xbd) { + return grn_nfkc50_compose_prefix_ccb8_table_e289[utf8[2] - 0x83]; + } + break; + case 0x8a : + if (utf8[2] >= 0x82 && + utf8[2] <= 0xb5) { + return grn_nfkc50_compose_prefix_ccb8_table_e28a[utf8[2] - 0x82]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e38299_table_e381[] = { + "\xe3\x82\x94", NULL, NULL, NULL, NULL, "\xe3\x81\x8c", NULL, "\xe3\x81\x8e", + NULL, "\xe3\x81\x90", NULL, "\xe3\x81\x92", NULL, "\xe3\x81\x94", NULL, "\xe3\x81\x96", + NULL, "\xe3\x81\x98", NULL, "\xe3\x81\x9a", NULL, "\xe3\x81\x9c", NULL, "\xe3\x81\x9e", + NULL, "\xe3\x81\xa0", NULL, "\xe3\x81\xa2", NULL, NULL, "\xe3\x81\xa5", NULL, + "\xe3\x81\xa7", NULL, "\xe3\x81\xa9", NULL, NULL, NULL, NULL, NULL, + NULL, "\xe3\x81\xb0", NULL, NULL, "\xe3\x81\xb3", NULL, NULL, "\xe3\x81\xb6", + NULL, NULL, "\xe3\x81\xb9", NULL, NULL, "\xe3\x81\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e38299_table_e382[] = { + "\xe3\x82\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, "\xe3\x83\xb4", NULL, NULL, NULL, NULL, "\xe3\x82\xac", NULL, + "\xe3\x82\xae", NULL, "\xe3\x82\xb0", NULL, "\xe3\x82\xb2", NULL, "\xe3\x82\xb4", NULL, + "\xe3\x82\xb6", NULL, "\xe3\x82\xb8", NULL, "\xe3\x82\xba", NULL, "\xe3\x82\xbc", NULL, + "\xe3\x82\xbe", NULL, "\xe3\x83\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e38299_table_e383[] = { + "\xe3\x83\x82", NULL, NULL, "\xe3\x83\x85", NULL, "\xe3\x83\x87", NULL, "\xe3\x83\x89", + NULL, NULL, NULL, NULL, NULL, NULL, "\xe3\x83\x90", NULL, + NULL, "\xe3\x83\x93", NULL, NULL, "\xe3\x83\x96", NULL, NULL, "\xe3\x83\x99", + NULL, NULL, "\xe3\x83\x9c", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, "\xe3\x83\xb7", "\xe3\x83\xb8", + "\xe3\x83\xb9", "\xe3\x83\xba", NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xe3\x83\xbe" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e38299(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe3 : + switch (utf8[1]) { + case 0x81 : + if (utf8[2] >= 0x86 && + utf8[2] <= 0xbb) { + return grn_nfkc50_compose_prefix_e38299_table_e381[utf8[2] - 0x86]; + } + break; + case 0x82 : + if (utf8[2] >= 0x9d && + utf8[2] <= 0xbf) { + return grn_nfkc50_compose_prefix_e38299_table_e382[utf8[2] - 0x9d]; + } + break; + case 0x83 : + if (utf8[2] >= 0x81 && + utf8[2] <= 0xbd) { + return grn_nfkc50_compose_prefix_e38299_table_e383[utf8[2] - 0x81]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e3829a_table_e381[] = { + "\xe3\x81\xb1", NULL, NULL, "\xe3\x81\xb4", NULL, NULL, "\xe3\x81\xb7", NULL, + NULL, "\xe3\x81\xba", NULL, NULL, "\xe3\x81\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e3829a_table_e383[] = { + "\xe3\x83\x91", NULL, NULL, "\xe3\x83\x94", NULL, NULL, "\xe3\x83\x97", NULL, + NULL, "\xe3\x83\x9a", NULL, NULL, "\xe3\x83\x9d" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e3829a(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe3 : + switch (utf8[1]) { + case 0x81 : + if (utf8[2] >= 0xaf && + utf8[2] <= 0xbb) { + return grn_nfkc50_compose_prefix_e3829a_table_e381[utf8[2] - 0xaf]; + } + break; + case 0x83 : + if (utf8[2] >= 0x8f && + utf8[2] <= 0x9b) { + return grn_nfkc50_compose_prefix_e3829a_table_e383[utf8[2] - 0x8f]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185a1_table_e184[] = { + "\xea\xb0\x80", "\xea\xb9\x8c", "\xeb\x82\x98", "\xeb\x8b\xa4", "\xeb\x94\xb0", "\xeb\x9d\xbc", "\xeb\xa7\x88", "\xeb\xb0\x94", + "\xeb\xb9\xa0", "\xec\x82\xac", "\xec\x8b\xb8", "\xec\x95\x84", "\xec\x9e\x90", "\xec\xa7\x9c", "\xec\xb0\xa8", "\xec\xb9\xb4", + "\xed\x83\x80", "\xed\x8c\x8c", "\xed\x95\x98" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185a1(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185a1_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab0[] = { + "\xea\xb0\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb0\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab1[] = { + "\xea\xb1\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab2[] = { + "\xea\xb2\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab3[] = { + "\xea\xb3\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb3\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab4[] = { + "\xea\xb4\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab5[] = { + "\xea\xb5\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab6[] = { + "\xea\xb6\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab7[] = { + "\xea\xb7\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb7\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab8[] = { + "\xea\xb8\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eab9[] = { + "\xea\xb9\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eaba[] = { + "\xea\xba\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xba\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eabb[] = { + "\xea\xbb\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eabc[] = { + "\xea\xbc\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eabd[] = { + "\xea\xbd\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eabe[] = { + "\xea\xbe\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbe\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eabf[] = { + "\xea\xbf\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb80[] = { + "\xeb\x80\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb81[] = { + "\xeb\x81\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x81\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb82[] = { + "\xeb\x82\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb83[] = { + "\xeb\x83\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb84[] = { + "\xeb\x84\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb85[] = { + "\xeb\x85\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x85\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb86[] = { + "\xeb\x86\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb87[] = { + "\xeb\x87\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb88[] = { + "\xeb\x88\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x88\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb89[] = { + "\xeb\x89\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb8a[] = { + "\xeb\x8a\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb8b[] = { + "\xeb\x8b\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb8c[] = { + "\xeb\x8c\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8c\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb8d[] = { + "\xeb\x8d\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb8e[] = { + "\xeb\x8e\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb8f[] = { + "\xeb\x8f\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8f\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb90[] = { + "\xeb\x90\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb91[] = { + "\xeb\x91\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb92[] = { + "\xeb\x92\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb93[] = { + "\xeb\x93\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x93\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb94[] = { + "\xeb\x94\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb95[] = { + "\xeb\x95\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb96[] = { + "\xeb\x96\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x96\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb97[] = { + "\xeb\x97\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb98[] = { + "\xeb\x98\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb99[] = { + "\xeb\x99\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb9a[] = { + "\xeb\x9a\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9a\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb9b[] = { + "\xeb\x9b\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb9c[] = { + "\xeb\x9c\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb9d[] = { + "\xeb\x9d\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9d\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb9e[] = { + "\xeb\x9e\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eb9f[] = { + "\xeb\x9f\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba0[] = { + "\xeb\xa0\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba1[] = { + "\xeb\xa1\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa1\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba2[] = { + "\xeb\xa2\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba3[] = { + "\xeb\xa3\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba4[] = { + "\xeb\xa4\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa4\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba5[] = { + "\xeb\xa5\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba6[] = { + "\xeb\xa6\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba7[] = { + "\xeb\xa7\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba8[] = { + "\xeb\xa8\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa8\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eba9[] = { + "\xeb\xa9\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebaa[] = { + "\xeb\xaa\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebab[] = { + "\xeb\xab\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xab\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebac[] = { + "\xeb\xac\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebad[] = { + "\xeb\xad\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebae[] = { + "\xeb\xae\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebaf[] = { + "\xeb\xaf\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xaf\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb0[] = { + "\xeb\xb0\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb1[] = { + "\xeb\xb1\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb2[] = { + "\xeb\xb2\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb2\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb3[] = { + "\xeb\xb3\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb4[] = { + "\xeb\xb4\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb5[] = { + "\xeb\xb5\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb6[] = { + "\xeb\xb6\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb6\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb7[] = { + "\xeb\xb7\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb8[] = { + "\xeb\xb8\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebb9[] = { + "\xeb\xb9\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb9\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebba[] = { + "\xeb\xba\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebbb[] = { + "\xeb\xbb\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebbc[] = { + "\xeb\xbc\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebbd[] = { + "\xeb\xbd\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbd\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebbe[] = { + "\xeb\xbe\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ebbf[] = { + "\xeb\xbf\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec80[] = { + "\xec\x80\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x80\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec81[] = { + "\xec\x81\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec82[] = { + "\xec\x82\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec83[] = { + "\xec\x83\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec84[] = { + "\xec\x84\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x84\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec85[] = { + "\xec\x85\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec86[] = { + "\xec\x86\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec87[] = { + "\xec\x87\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x87\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec88[] = { + "\xec\x88\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec89[] = { + "\xec\x89\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec8a[] = { + "\xec\x8a\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec8b[] = { + "\xec\x8b\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8b\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec8c[] = { + "\xec\x8c\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec8d[] = { + "\xec\x8d\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec8e[] = { + "\xec\x8e\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8e\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec8f[] = { + "\xec\x8f\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec90[] = { + "\xec\x90\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec91[] = { + "\xec\x91\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec92[] = { + "\xec\x92\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x92\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec93[] = { + "\xec\x93\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec94[] = { + "\xec\x94\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec95[] = { + "\xec\x95\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x95\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec96[] = { + "\xec\x96\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec97[] = { + "\xec\x97\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec98[] = { + "\xec\x98\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec99[] = { + "\xec\x99\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x99\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec9a[] = { + "\xec\x9a\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec9b[] = { + "\xec\x9b\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec9c[] = { + "\xec\x9c\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9c\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec9d[] = { + "\xec\x9d\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec9e[] = { + "\xec\x9e\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ec9f[] = { + "\xec\x9f\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca0[] = { + "\xec\xa0\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa0\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca1[] = { + "\xec\xa1\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca2[] = { + "\xec\xa2\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca3[] = { + "\xec\xa3\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa3\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca4[] = { + "\xec\xa4\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca5[] = { + "\xec\xa5\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca6[] = { + "\xec\xa6\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca7[] = { + "\xec\xa7\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa7\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca8[] = { + "\xec\xa8\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_eca9[] = { + "\xec\xa9\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecaa[] = { + "\xec\xaa\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaa\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecab[] = { + "\xec\xab\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecac[] = { + "\xec\xac\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecad[] = { + "\xec\xad\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecae[] = { + "\xec\xae\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xae\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecaf[] = { + "\xec\xaf\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb0[] = { + "\xec\xb0\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb1[] = { + "\xec\xb1\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb1\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb2[] = { + "\xec\xb2\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb3[] = { + "\xec\xb3\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb4[] = { + "\xec\xb4\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb5[] = { + "\xec\xb5\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb5\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb6[] = { + "\xec\xb6\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb7[] = { + "\xec\xb7\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb8[] = { + "\xec\xb8\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb8\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecb9[] = { + "\xec\xb9\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecba[] = { + "\xec\xba\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecbb[] = { + "\xec\xbb\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecbc[] = { + "\xec\xbc\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbc\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecbd[] = { + "\xec\xbd\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecbe[] = { + "\xec\xbe\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ecbf[] = { + "\xec\xbf\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbf\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed80[] = { + "\xed\x80\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed81[] = { + "\xed\x81\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed82[] = { + "\xed\x82\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed83[] = { + "\xed\x83\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x83\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed84[] = { + "\xed\x84\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed85[] = { + "\xed\x85\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed86[] = { + "\xed\x86\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x86\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed87[] = { + "\xed\x87\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed88[] = { + "\xed\x88\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed89[] = { + "\xed\x89\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed8a[] = { + "\xed\x8a\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8a\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed8b[] = { + "\xed\x8b\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed8c[] = { + "\xed\x8c\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed8d[] = { + "\xed\x8d\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8d\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed8e[] = { + "\xed\x8e\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed8f[] = { + "\xed\x8f\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed90[] = { + "\xed\x90\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed91[] = { + "\xed\x91\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x91\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed92[] = { + "\xed\x92\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed93[] = { + "\xed\x93\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed94[] = { + "\xed\x94\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x94\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed95[] = { + "\xed\x95\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed96[] = { + "\xed\x96\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed97[] = { + "\xed\x97\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xa5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed98[] = { + "\xed\x98\x81", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\x9d", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x98\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed99[] = { + "\xed\x99\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed9a[] = { + "\xed\x9a\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed9b[] = { + "\xed\x9b\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9b\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed9c[] = { + "\xed\x9c\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186a8_table_ed9d[] = { + "\xed\x9d\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xad" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186a8(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a8_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a8_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a8_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a8_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a8_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a8_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a8_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x89"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab0[] = { + "\xea\xb0\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb0\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab1[] = { + "\xea\xb1\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab2[] = { + "\xea\xb2\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab3[] = { + "\xea\xb3\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb3\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab4[] = { + "\xea\xb4\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab5[] = { + "\xea\xb5\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab6[] = { + "\xea\xb6\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab7[] = { + "\xea\xb7\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb7\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab8[] = { + "\xea\xb8\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eab9[] = { + "\xea\xb9\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eaba[] = { + "\xea\xba\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xba\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eabb[] = { + "\xea\xbb\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eabc[] = { + "\xea\xbc\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eabd[] = { + "\xea\xbd\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eabe[] = { + "\xea\xbe\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbe\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eabf[] = { + "\xea\xbf\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb80[] = { + "\xeb\x80\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb81[] = { + "\xeb\x81\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x81\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb82[] = { + "\xeb\x82\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb83[] = { + "\xeb\x83\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb84[] = { + "\xeb\x84\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb85[] = { + "\xeb\x85\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x85\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb86[] = { + "\xeb\x86\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb87[] = { + "\xeb\x87\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb88[] = { + "\xeb\x88\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x88\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb89[] = { + "\xeb\x89\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb8a[] = { + "\xeb\x8a\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb8b[] = { + "\xeb\x8b\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb8c[] = { + "\xeb\x8c\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8c\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb8d[] = { + "\xeb\x8d\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb8e[] = { + "\xeb\x8e\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb8f[] = { + "\xeb\x8f\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8f\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb90[] = { + "\xeb\x90\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb91[] = { + "\xeb\x91\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb92[] = { + "\xeb\x92\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb93[] = { + "\xeb\x93\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x93\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb94[] = { + "\xeb\x94\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb95[] = { + "\xeb\x95\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb96[] = { + "\xeb\x96\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x96\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb97[] = { + "\xeb\x97\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb98[] = { + "\xeb\x98\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb99[] = { + "\xeb\x99\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb9a[] = { + "\xeb\x9a\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9a\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb9b[] = { + "\xeb\x9b\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb9c[] = { + "\xeb\x9c\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb9d[] = { + "\xeb\x9d\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9d\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb9e[] = { + "\xeb\x9e\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eb9f[] = { + "\xeb\x9f\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba0[] = { + "\xeb\xa0\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba1[] = { + "\xeb\xa1\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa1\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba2[] = { + "\xeb\xa2\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba3[] = { + "\xeb\xa3\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba4[] = { + "\xeb\xa4\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa4\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba5[] = { + "\xeb\xa5\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba6[] = { + "\xeb\xa6\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba7[] = { + "\xeb\xa7\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba8[] = { + "\xeb\xa8\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa8\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eba9[] = { + "\xeb\xa9\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebaa[] = { + "\xeb\xaa\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebab[] = { + "\xeb\xab\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xab\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebac[] = { + "\xeb\xac\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebad[] = { + "\xeb\xad\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebae[] = { + "\xeb\xae\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebaf[] = { + "\xeb\xaf\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xaf\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb0[] = { + "\xeb\xb0\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb1[] = { + "\xeb\xb1\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb2[] = { + "\xeb\xb2\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb2\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb3[] = { + "\xeb\xb3\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb4[] = { + "\xeb\xb4\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb5[] = { + "\xeb\xb5\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb6[] = { + "\xeb\xb6\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb6\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb7[] = { + "\xeb\xb7\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb8[] = { + "\xeb\xb8\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebb9[] = { + "\xeb\xb9\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb9\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebba[] = { + "\xeb\xba\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebbb[] = { + "\xeb\xbb\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebbc[] = { + "\xeb\xbc\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebbd[] = { + "\xeb\xbd\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbd\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebbe[] = { + "\xeb\xbe\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ebbf[] = { + "\xeb\xbf\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec80[] = { + "\xec\x80\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x80\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec81[] = { + "\xec\x81\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec82[] = { + "\xec\x82\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec83[] = { + "\xec\x83\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec84[] = { + "\xec\x84\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x84\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec85[] = { + "\xec\x85\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec86[] = { + "\xec\x86\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec87[] = { + "\xec\x87\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x87\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec88[] = { + "\xec\x88\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec89[] = { + "\xec\x89\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec8a[] = { + "\xec\x8a\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec8b[] = { + "\xec\x8b\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8b\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec8c[] = { + "\xec\x8c\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec8d[] = { + "\xec\x8d\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec8e[] = { + "\xec\x8e\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8e\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec8f[] = { + "\xec\x8f\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec90[] = { + "\xec\x90\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec91[] = { + "\xec\x91\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec92[] = { + "\xec\x92\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x92\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec93[] = { + "\xec\x93\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec94[] = { + "\xec\x94\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec95[] = { + "\xec\x95\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x95\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec96[] = { + "\xec\x96\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec97[] = { + "\xec\x97\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec98[] = { + "\xec\x98\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec99[] = { + "\xec\x99\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x99\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec9a[] = { + "\xec\x9a\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec9b[] = { + "\xec\x9b\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec9c[] = { + "\xec\x9c\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9c\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec9d[] = { + "\xec\x9d\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec9e[] = { + "\xec\x9e\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ec9f[] = { + "\xec\x9f\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca0[] = { + "\xec\xa0\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa0\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca1[] = { + "\xec\xa1\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca2[] = { + "\xec\xa2\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca3[] = { + "\xec\xa3\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa3\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca4[] = { + "\xec\xa4\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca5[] = { + "\xec\xa5\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca6[] = { + "\xec\xa6\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca7[] = { + "\xec\xa7\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa7\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca8[] = { + "\xec\xa8\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_eca9[] = { + "\xec\xa9\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecaa[] = { + "\xec\xaa\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaa\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecab[] = { + "\xec\xab\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecac[] = { + "\xec\xac\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecad[] = { + "\xec\xad\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecae[] = { + "\xec\xae\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xae\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecaf[] = { + "\xec\xaf\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb0[] = { + "\xec\xb0\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb1[] = { + "\xec\xb1\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb1\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb2[] = { + "\xec\xb2\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb3[] = { + "\xec\xb3\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb4[] = { + "\xec\xb4\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb5[] = { + "\xec\xb5\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb5\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb6[] = { + "\xec\xb6\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb7[] = { + "\xec\xb7\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb8[] = { + "\xec\xb8\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb8\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecb9[] = { + "\xec\xb9\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecba[] = { + "\xec\xba\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecbb[] = { + "\xec\xbb\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecbc[] = { + "\xec\xbc\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbc\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecbd[] = { + "\xec\xbd\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecbe[] = { + "\xec\xbe\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ecbf[] = { + "\xec\xbf\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbf\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed80[] = { + "\xed\x80\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed81[] = { + "\xed\x81\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed82[] = { + "\xed\x82\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed83[] = { + "\xed\x83\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x83\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed84[] = { + "\xed\x84\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed85[] = { + "\xed\x85\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed86[] = { + "\xed\x86\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x86\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed87[] = { + "\xed\x87\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed88[] = { + "\xed\x88\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed89[] = { + "\xed\x89\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed8a[] = { + "\xed\x8a\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8a\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed8b[] = { + "\xed\x8b\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed8c[] = { + "\xed\x8c\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed8d[] = { + "\xed\x8d\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8d\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed8e[] = { + "\xed\x8e\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed8f[] = { + "\xed\x8f\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed90[] = { + "\xed\x90\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed91[] = { + "\xed\x91\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x91\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed92[] = { + "\xed\x92\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed93[] = { + "\xed\x93\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed94[] = { + "\xed\x94\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x94\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed95[] = { + "\xed\x95\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed96[] = { + "\xed\x96\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed97[] = { + "\xed\x97\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xa6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed98[] = { + "\xed\x98\x82", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\x9e", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x98\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed99[] = { + "\xed\x99\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed9a[] = { + "\xed\x9a\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed9b[] = { + "\xed\x9b\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9b\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed9c[] = { + "\xed\x9c\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186a9_table_ed9d[] = { + "\xed\x9d\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xae" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186a9(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186a9_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186a9_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186a9_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186a9_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186a9_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186a9_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186a9_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x8a"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab0[] = { + "\xea\xb0\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb0\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab1[] = { + "\xea\xb1\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab2[] = { + "\xea\xb2\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab3[] = { + "\xea\xb3\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb3\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab4[] = { + "\xea\xb4\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab5[] = { + "\xea\xb5\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab6[] = { + "\xea\xb6\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab7[] = { + "\xea\xb7\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb7\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab8[] = { + "\xea\xb8\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eab9[] = { + "\xea\xb9\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eaba[] = { + "\xea\xba\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xba\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eabb[] = { + "\xea\xbb\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eabc[] = { + "\xea\xbc\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eabd[] = { + "\xea\xbd\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eabe[] = { + "\xea\xbe\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbe\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eabf[] = { + "\xea\xbf\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb80[] = { + "\xeb\x80\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb81[] = { + "\xeb\x81\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x81\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb82[] = { + "\xeb\x82\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb83[] = { + "\xeb\x83\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb84[] = { + "\xeb\x84\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb85[] = { + "\xeb\x85\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x85\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb86[] = { + "\xeb\x86\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb87[] = { + "\xeb\x87\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb88[] = { + "\xeb\x88\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x88\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb89[] = { + "\xeb\x89\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb8a[] = { + "\xeb\x8a\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb8b[] = { + "\xeb\x8b\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb8c[] = { + "\xeb\x8c\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8c\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb8d[] = { + "\xeb\x8d\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb8e[] = { + "\xeb\x8e\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb8f[] = { + "\xeb\x8f\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8f\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb90[] = { + "\xeb\x90\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb91[] = { + "\xeb\x91\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb92[] = { + "\xeb\x92\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb93[] = { + "\xeb\x93\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x93\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb94[] = { + "\xeb\x94\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb95[] = { + "\xeb\x95\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb96[] = { + "\xeb\x96\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x96\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb97[] = { + "\xeb\x97\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb98[] = { + "\xeb\x98\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb99[] = { + "\xeb\x99\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb9a[] = { + "\xeb\x9a\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9a\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb9b[] = { + "\xeb\x9b\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb9c[] = { + "\xeb\x9c\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb9d[] = { + "\xeb\x9d\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9d\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb9e[] = { + "\xeb\x9e\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eb9f[] = { + "\xeb\x9f\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba0[] = { + "\xeb\xa0\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba1[] = { + "\xeb\xa1\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa1\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba2[] = { + "\xeb\xa2\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba3[] = { + "\xeb\xa3\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba4[] = { + "\xeb\xa4\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa4\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba5[] = { + "\xeb\xa5\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba6[] = { + "\xeb\xa6\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba7[] = { + "\xeb\xa7\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba8[] = { + "\xeb\xa8\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa8\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eba9[] = { + "\xeb\xa9\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebaa[] = { + "\xeb\xaa\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebab[] = { + "\xeb\xab\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xab\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebac[] = { + "\xeb\xac\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebad[] = { + "\xeb\xad\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebae[] = { + "\xeb\xae\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebaf[] = { + "\xeb\xaf\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xaf\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb0[] = { + "\xeb\xb0\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb1[] = { + "\xeb\xb1\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb2[] = { + "\xeb\xb2\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb2\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb3[] = { + "\xeb\xb3\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb4[] = { + "\xeb\xb4\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb5[] = { + "\xeb\xb5\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb6[] = { + "\xeb\xb6\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb6\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb7[] = { + "\xeb\xb7\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb8[] = { + "\xeb\xb8\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebb9[] = { + "\xeb\xb9\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb9\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebba[] = { + "\xeb\xba\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebbb[] = { + "\xeb\xbb\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebbc[] = { + "\xeb\xbc\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebbd[] = { + "\xeb\xbd\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbd\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebbe[] = { + "\xeb\xbe\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ebbf[] = { + "\xeb\xbf\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec80[] = { + "\xec\x80\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x80\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec81[] = { + "\xec\x81\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec82[] = { + "\xec\x82\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec83[] = { + "\xec\x83\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec84[] = { + "\xec\x84\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x84\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec85[] = { + "\xec\x85\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec86[] = { + "\xec\x86\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec87[] = { + "\xec\x87\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x87\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec88[] = { + "\xec\x88\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec89[] = { + "\xec\x89\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec8a[] = { + "\xec\x8a\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec8b[] = { + "\xec\x8b\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8b\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec8c[] = { + "\xec\x8c\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec8d[] = { + "\xec\x8d\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec8e[] = { + "\xec\x8e\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8e\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec8f[] = { + "\xec\x8f\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec90[] = { + "\xec\x90\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec91[] = { + "\xec\x91\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec92[] = { + "\xec\x92\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x92\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec93[] = { + "\xec\x93\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec94[] = { + "\xec\x94\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec95[] = { + "\xec\x95\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x95\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec96[] = { + "\xec\x96\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec97[] = { + "\xec\x97\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec98[] = { + "\xec\x98\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec99[] = { + "\xec\x99\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x99\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec9a[] = { + "\xec\x9a\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec9b[] = { + "\xec\x9b\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec9c[] = { + "\xec\x9c\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9c\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec9d[] = { + "\xec\x9d\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec9e[] = { + "\xec\x9e\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ec9f[] = { + "\xec\x9f\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca0[] = { + "\xec\xa0\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa0\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca1[] = { + "\xec\xa1\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca2[] = { + "\xec\xa2\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca3[] = { + "\xec\xa3\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa3\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca4[] = { + "\xec\xa4\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca5[] = { + "\xec\xa5\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca6[] = { + "\xec\xa6\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca7[] = { + "\xec\xa7\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa7\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca8[] = { + "\xec\xa8\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_eca9[] = { + "\xec\xa9\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecaa[] = { + "\xec\xaa\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaa\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecab[] = { + "\xec\xab\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecac[] = { + "\xec\xac\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecad[] = { + "\xec\xad\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecae[] = { + "\xec\xae\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xae\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecaf[] = { + "\xec\xaf\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb0[] = { + "\xec\xb0\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb1[] = { + "\xec\xb1\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb1\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb2[] = { + "\xec\xb2\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb3[] = { + "\xec\xb3\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb4[] = { + "\xec\xb4\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb5[] = { + "\xec\xb5\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb5\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb6[] = { + "\xec\xb6\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb7[] = { + "\xec\xb7\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb8[] = { + "\xec\xb8\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb8\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecb9[] = { + "\xec\xb9\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecba[] = { + "\xec\xba\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecbb[] = { + "\xec\xbb\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecbc[] = { + "\xec\xbc\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbc\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecbd[] = { + "\xec\xbd\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecbe[] = { + "\xec\xbe\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ecbf[] = { + "\xec\xbf\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbf\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed80[] = { + "\xed\x80\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed81[] = { + "\xed\x81\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed82[] = { + "\xed\x82\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed83[] = { + "\xed\x83\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x83\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed84[] = { + "\xed\x84\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed85[] = { + "\xed\x85\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed86[] = { + "\xed\x86\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x86\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed87[] = { + "\xed\x87\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed88[] = { + "\xed\x88\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed89[] = { + "\xed\x89\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed8a[] = { + "\xed\x8a\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8a\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed8b[] = { + "\xed\x8b\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed8c[] = { + "\xed\x8c\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed8d[] = { + "\xed\x8d\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8d\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed8e[] = { + "\xed\x8e\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed8f[] = { + "\xed\x8f\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed90[] = { + "\xed\x90\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed91[] = { + "\xed\x91\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x91\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed92[] = { + "\xed\x92\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed93[] = { + "\xed\x93\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed94[] = { + "\xed\x94\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x94\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed95[] = { + "\xed\x95\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed96[] = { + "\xed\x96\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed97[] = { + "\xed\x97\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xa7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed98[] = { + "\xed\x98\x83", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\x9f", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x98\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed99[] = { + "\xed\x99\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed9a[] = { + "\xed\x9a\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed9b[] = { + "\xed\x9b\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9b\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed9c[] = { + "\xed\x9c\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186aa_table_ed9d[] = { + "\xed\x9d\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xaf" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186aa(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186aa_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186aa_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186aa_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186aa_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186aa_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186aa_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186aa_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x8b"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab0[] = { + "\xea\xb0\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb0\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab1[] = { + "\xea\xb1\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab2[] = { + "\xea\xb2\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab3[] = { + "\xea\xb3\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab4[] = { + "\xea\xb4\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab5[] = { + "\xea\xb5\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab6[] = { + "\xea\xb6\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab7[] = { + "\xea\xb7\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb7\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab8[] = { + "\xea\xb8\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eab9[] = { + "\xea\xb9\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eaba[] = { + "\xea\xba\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eabb[] = { + "\xea\xbb\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eabc[] = { + "\xea\xbc\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eabd[] = { + "\xea\xbd\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eabe[] = { + "\xea\xbe\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbe\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eabf[] = { + "\xea\xbf\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb80[] = { + "\xeb\x80\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb81[] = { + "\xeb\x81\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb82[] = { + "\xeb\x82\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb83[] = { + "\xeb\x83\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb84[] = { + "\xeb\x84\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb85[] = { + "\xeb\x85\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x85\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb86[] = { + "\xeb\x86\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb87[] = { + "\xeb\x87\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb88[] = { + "\xeb\x88\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb89[] = { + "\xeb\x89\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb8a[] = { + "\xeb\x8a\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb8b[] = { + "\xeb\x8b\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb8c[] = { + "\xeb\x8c\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8c\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb8d[] = { + "\xeb\x8d\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb8e[] = { + "\xeb\x8e\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb8f[] = { + "\xeb\x8f\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb90[] = { + "\xeb\x90\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb91[] = { + "\xeb\x91\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb92[] = { + "\xeb\x92\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb93[] = { + "\xeb\x93\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x93\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb94[] = { + "\xeb\x94\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb95[] = { + "\xeb\x95\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb96[] = { + "\xeb\x96\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb97[] = { + "\xeb\x97\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb98[] = { + "\xeb\x98\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb99[] = { + "\xeb\x99\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb9a[] = { + "\xeb\x9a\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9a\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb9b[] = { + "\xeb\x9b\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb9c[] = { + "\xeb\x9c\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb9d[] = { + "\xeb\x9d\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb9e[] = { + "\xeb\x9e\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eb9f[] = { + "\xeb\x9f\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba0[] = { + "\xeb\xa0\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba1[] = { + "\xeb\xa1\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa1\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba2[] = { + "\xeb\xa2\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba3[] = { + "\xeb\xa3\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba4[] = { + "\xeb\xa4\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba5[] = { + "\xeb\xa5\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba6[] = { + "\xeb\xa6\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba7[] = { + "\xeb\xa7\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba8[] = { + "\xeb\xa8\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa8\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eba9[] = { + "\xeb\xa9\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebaa[] = { + "\xeb\xaa\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebab[] = { + "\xeb\xab\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebac[] = { + "\xeb\xac\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebad[] = { + "\xeb\xad\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebae[] = { + "\xeb\xae\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebaf[] = { + "\xeb\xaf\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xaf\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb0[] = { + "\xeb\xb0\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb1[] = { + "\xeb\xb1\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb2[] = { + "\xeb\xb2\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb3[] = { + "\xeb\xb3\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb4[] = { + "\xeb\xb4\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb5[] = { + "\xeb\xb5\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb6[] = { + "\xeb\xb6\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb6\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb7[] = { + "\xeb\xb7\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb8[] = { + "\xeb\xb8\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebb9[] = { + "\xeb\xb9\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebba[] = { + "\xeb\xba\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebbb[] = { + "\xeb\xbb\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebbc[] = { + "\xeb\xbc\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebbd[] = { + "\xeb\xbd\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbd\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebbe[] = { + "\xeb\xbe\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ebbf[] = { + "\xeb\xbf\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec80[] = { + "\xec\x80\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec81[] = { + "\xec\x81\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec82[] = { + "\xec\x82\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec83[] = { + "\xec\x83\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec84[] = { + "\xec\x84\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x84\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec85[] = { + "\xec\x85\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec86[] = { + "\xec\x86\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec87[] = { + "\xec\x87\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec88[] = { + "\xec\x88\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec89[] = { + "\xec\x89\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec8a[] = { + "\xec\x8a\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec8b[] = { + "\xec\x8b\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8b\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec8c[] = { + "\xec\x8c\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec8d[] = { + "\xec\x8d\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec8e[] = { + "\xec\x8e\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec8f[] = { + "\xec\x8f\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec90[] = { + "\xec\x90\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec91[] = { + "\xec\x91\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec92[] = { + "\xec\x92\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x92\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec93[] = { + "\xec\x93\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec94[] = { + "\xec\x94\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec95[] = { + "\xec\x95\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec96[] = { + "\xec\x96\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec97[] = { + "\xec\x97\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec98[] = { + "\xec\x98\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec99[] = { + "\xec\x99\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x99\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec9a[] = { + "\xec\x9a\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec9b[] = { + "\xec\x9b\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec9c[] = { + "\xec\x9c\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec9d[] = { + "\xec\x9d\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec9e[] = { + "\xec\x9e\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ec9f[] = { + "\xec\x9f\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca0[] = { + "\xec\xa0\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa0\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca1[] = { + "\xec\xa1\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca2[] = { + "\xec\xa2\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca3[] = { + "\xec\xa3\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca4[] = { + "\xec\xa4\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca5[] = { + "\xec\xa5\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca6[] = { + "\xec\xa6\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca7[] = { + "\xec\xa7\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa7\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca8[] = { + "\xec\xa8\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_eca9[] = { + "\xec\xa9\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecaa[] = { + "\xec\xaa\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecab[] = { + "\xec\xab\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecac[] = { + "\xec\xac\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecad[] = { + "\xec\xad\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecae[] = { + "\xec\xae\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xae\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecaf[] = { + "\xec\xaf\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb0[] = { + "\xec\xb0\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb1[] = { + "\xec\xb1\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb2[] = { + "\xec\xb2\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb3[] = { + "\xec\xb3\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb4[] = { + "\xec\xb4\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb5[] = { + "\xec\xb5\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb5\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb6[] = { + "\xec\xb6\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb7[] = { + "\xec\xb7\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb8[] = { + "\xec\xb8\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecb9[] = { + "\xec\xb9\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecba[] = { + "\xec\xba\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecbb[] = { + "\xec\xbb\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecbc[] = { + "\xec\xbc\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbc\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecbd[] = { + "\xec\xbd\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecbe[] = { + "\xec\xbe\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ecbf[] = { + "\xec\xbf\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed80[] = { + "\xed\x80\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed81[] = { + "\xed\x81\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed82[] = { + "\xed\x82\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed83[] = { + "\xed\x83\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x83\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed84[] = { + "\xed\x84\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed85[] = { + "\xed\x85\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed86[] = { + "\xed\x86\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed87[] = { + "\xed\x87\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed88[] = { + "\xed\x88\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed89[] = { + "\xed\x89\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed8a[] = { + "\xed\x8a\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8a\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed8b[] = { + "\xed\x8b\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed8c[] = { + "\xed\x8c\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed8d[] = { + "\xed\x8d\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed8e[] = { + "\xed\x8e\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed8f[] = { + "\xed\x8f\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed90[] = { + "\xed\x90\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed91[] = { + "\xed\x91\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x91\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed92[] = { + "\xed\x92\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed93[] = { + "\xed\x93\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed94[] = { + "\xed\x94\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed95[] = { + "\xed\x95\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed96[] = { + "\xed\x96\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed97[] = { + "\xed\x97\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xa8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed98[] = { + "\xed\x98\x84", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x98\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed99[] = { + "\xed\x99\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed9a[] = { + "\xed\x9a\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed9b[] = { + "\xed\x9b\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed9c[] = { + "\xed\x9c\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186ab_table_ed9d[] = { + "\xed\x9d\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb0" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186ab(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ab_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ab_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ab_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ab_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ab_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ab_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ab_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x8c"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab0[] = { + "\xea\xb0\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb0\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab1[] = { + "\xea\xb1\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab2[] = { + "\xea\xb2\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab3[] = { + "\xea\xb3\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab4[] = { + "\xea\xb4\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab5[] = { + "\xea\xb5\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab6[] = { + "\xea\xb6\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab7[] = { + "\xea\xb7\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb7\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab8[] = { + "\xea\xb8\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eab9[] = { + "\xea\xb9\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eaba[] = { + "\xea\xba\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eabb[] = { + "\xea\xbb\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eabc[] = { + "\xea\xbc\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eabd[] = { + "\xea\xbd\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eabe[] = { + "\xea\xbe\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbe\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eabf[] = { + "\xea\xbf\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb80[] = { + "\xeb\x80\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb81[] = { + "\xeb\x81\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb82[] = { + "\xeb\x82\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb83[] = { + "\xeb\x83\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb84[] = { + "\xeb\x84\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb85[] = { + "\xeb\x85\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x85\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb86[] = { + "\xeb\x86\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb87[] = { + "\xeb\x87\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb88[] = { + "\xeb\x88\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb89[] = { + "\xeb\x89\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb8a[] = { + "\xeb\x8a\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb8b[] = { + "\xeb\x8b\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb8c[] = { + "\xeb\x8c\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8c\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb8d[] = { + "\xeb\x8d\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb8e[] = { + "\xeb\x8e\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb8f[] = { + "\xeb\x8f\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb90[] = { + "\xeb\x90\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb91[] = { + "\xeb\x91\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb92[] = { + "\xeb\x92\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb93[] = { + "\xeb\x93\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x93\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb94[] = { + "\xeb\x94\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb95[] = { + "\xeb\x95\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb96[] = { + "\xeb\x96\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb97[] = { + "\xeb\x97\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb98[] = { + "\xeb\x98\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb99[] = { + "\xeb\x99\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb9a[] = { + "\xeb\x9a\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9a\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb9b[] = { + "\xeb\x9b\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb9c[] = { + "\xeb\x9c\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb9d[] = { + "\xeb\x9d\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb9e[] = { + "\xeb\x9e\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eb9f[] = { + "\xeb\x9f\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba0[] = { + "\xeb\xa0\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba1[] = { + "\xeb\xa1\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa1\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba2[] = { + "\xeb\xa2\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba3[] = { + "\xeb\xa3\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba4[] = { + "\xeb\xa4\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba5[] = { + "\xeb\xa5\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba6[] = { + "\xeb\xa6\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba7[] = { + "\xeb\xa7\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba8[] = { + "\xeb\xa8\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa8\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eba9[] = { + "\xeb\xa9\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebaa[] = { + "\xeb\xaa\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebab[] = { + "\xeb\xab\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebac[] = { + "\xeb\xac\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebad[] = { + "\xeb\xad\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebae[] = { + "\xeb\xae\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebaf[] = { + "\xeb\xaf\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xaf\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb0[] = { + "\xeb\xb0\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb1[] = { + "\xeb\xb1\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb2[] = { + "\xeb\xb2\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb3[] = { + "\xeb\xb3\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb4[] = { + "\xeb\xb4\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb5[] = { + "\xeb\xb5\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb6[] = { + "\xeb\xb6\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb6\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb7[] = { + "\xeb\xb7\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb8[] = { + "\xeb\xb8\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebb9[] = { + "\xeb\xb9\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebba[] = { + "\xeb\xba\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebbb[] = { + "\xeb\xbb\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebbc[] = { + "\xeb\xbc\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebbd[] = { + "\xeb\xbd\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbd\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebbe[] = { + "\xeb\xbe\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ebbf[] = { + "\xeb\xbf\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec80[] = { + "\xec\x80\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec81[] = { + "\xec\x81\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec82[] = { + "\xec\x82\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec83[] = { + "\xec\x83\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec84[] = { + "\xec\x84\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x84\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec85[] = { + "\xec\x85\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec86[] = { + "\xec\x86\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec87[] = { + "\xec\x87\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec88[] = { + "\xec\x88\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec89[] = { + "\xec\x89\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec8a[] = { + "\xec\x8a\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec8b[] = { + "\xec\x8b\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8b\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec8c[] = { + "\xec\x8c\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec8d[] = { + "\xec\x8d\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec8e[] = { + "\xec\x8e\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec8f[] = { + "\xec\x8f\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec90[] = { + "\xec\x90\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec91[] = { + "\xec\x91\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec92[] = { + "\xec\x92\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x92\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec93[] = { + "\xec\x93\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec94[] = { + "\xec\x94\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec95[] = { + "\xec\x95\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec96[] = { + "\xec\x96\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec97[] = { + "\xec\x97\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec98[] = { + "\xec\x98\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec99[] = { + "\xec\x99\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x99\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec9a[] = { + "\xec\x9a\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec9b[] = { + "\xec\x9b\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec9c[] = { + "\xec\x9c\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec9d[] = { + "\xec\x9d\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec9e[] = { + "\xec\x9e\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ec9f[] = { + "\xec\x9f\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca0[] = { + "\xec\xa0\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa0\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca1[] = { + "\xec\xa1\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca2[] = { + "\xec\xa2\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca3[] = { + "\xec\xa3\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca4[] = { + "\xec\xa4\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca5[] = { + "\xec\xa5\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca6[] = { + "\xec\xa6\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca7[] = { + "\xec\xa7\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa7\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca8[] = { + "\xec\xa8\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_eca9[] = { + "\xec\xa9\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecaa[] = { + "\xec\xaa\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecab[] = { + "\xec\xab\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecac[] = { + "\xec\xac\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecad[] = { + "\xec\xad\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecae[] = { + "\xec\xae\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xae\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecaf[] = { + "\xec\xaf\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb0[] = { + "\xec\xb0\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb1[] = { + "\xec\xb1\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb2[] = { + "\xec\xb2\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb3[] = { + "\xec\xb3\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb4[] = { + "\xec\xb4\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb5[] = { + "\xec\xb5\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb5\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb6[] = { + "\xec\xb6\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb7[] = { + "\xec\xb7\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb8[] = { + "\xec\xb8\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecb9[] = { + "\xec\xb9\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecba[] = { + "\xec\xba\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecbb[] = { + "\xec\xbb\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecbc[] = { + "\xec\xbc\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbc\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecbd[] = { + "\xec\xbd\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecbe[] = { + "\xec\xbe\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ecbf[] = { + "\xec\xbf\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed80[] = { + "\xed\x80\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed81[] = { + "\xed\x81\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed82[] = { + "\xed\x82\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed83[] = { + "\xed\x83\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x83\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed84[] = { + "\xed\x84\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed85[] = { + "\xed\x85\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed86[] = { + "\xed\x86\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed87[] = { + "\xed\x87\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed88[] = { + "\xed\x88\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed89[] = { + "\xed\x89\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed8a[] = { + "\xed\x8a\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8a\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed8b[] = { + "\xed\x8b\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed8c[] = { + "\xed\x8c\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed8d[] = { + "\xed\x8d\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed8e[] = { + "\xed\x8e\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed8f[] = { + "\xed\x8f\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed90[] = { + "\xed\x90\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed91[] = { + "\xed\x91\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x91\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed92[] = { + "\xed\x92\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed93[] = { + "\xed\x93\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed94[] = { + "\xed\x94\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed95[] = { + "\xed\x95\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed96[] = { + "\xed\x96\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed97[] = { + "\xed\x97\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xa9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed98[] = { + "\xed\x98\x85", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x98\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed99[] = { + "\xed\x99\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed9a[] = { + "\xed\x9a\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed9b[] = { + "\xed\x9b\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed9c[] = { + "\xed\x9c\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186ac_table_ed9d[] = { + "\xed\x9d\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb1" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186ac(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ac_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ac_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ac_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ac_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ac_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ac_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ac_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x8d"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab0[] = { + "\xea\xb0\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb0\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab1[] = { + "\xea\xb1\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab2[] = { + "\xea\xb2\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab3[] = { + "\xea\xb3\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab4[] = { + "\xea\xb4\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab5[] = { + "\xea\xb5\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab6[] = { + "\xea\xb6\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab7[] = { + "\xea\xb7\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb7\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab8[] = { + "\xea\xb8\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eab9[] = { + "\xea\xb9\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eaba[] = { + "\xea\xba\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eabb[] = { + "\xea\xbb\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eabc[] = { + "\xea\xbc\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eabd[] = { + "\xea\xbd\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eabe[] = { + "\xea\xbe\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbe\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eabf[] = { + "\xea\xbf\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb80[] = { + "\xeb\x80\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb81[] = { + "\xeb\x81\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb82[] = { + "\xeb\x82\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb83[] = { + "\xeb\x83\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb84[] = { + "\xeb\x84\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb85[] = { + "\xeb\x85\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x85\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb86[] = { + "\xeb\x86\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb87[] = { + "\xeb\x87\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb88[] = { + "\xeb\x88\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb89[] = { + "\xeb\x89\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb8a[] = { + "\xeb\x8a\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb8b[] = { + "\xeb\x8b\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb8c[] = { + "\xeb\x8c\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8c\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb8d[] = { + "\xeb\x8d\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb8e[] = { + "\xeb\x8e\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb8f[] = { + "\xeb\x8f\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb90[] = { + "\xeb\x90\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb91[] = { + "\xeb\x91\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb92[] = { + "\xeb\x92\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb93[] = { + "\xeb\x93\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x93\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb94[] = { + "\xeb\x94\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb95[] = { + "\xeb\x95\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb96[] = { + "\xeb\x96\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb97[] = { + "\xeb\x97\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb98[] = { + "\xeb\x98\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb99[] = { + "\xeb\x99\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb9a[] = { + "\xeb\x9a\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9a\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb9b[] = { + "\xeb\x9b\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb9c[] = { + "\xeb\x9c\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb9d[] = { + "\xeb\x9d\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb9e[] = { + "\xeb\x9e\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eb9f[] = { + "\xeb\x9f\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba0[] = { + "\xeb\xa0\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba1[] = { + "\xeb\xa1\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa1\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba2[] = { + "\xeb\xa2\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba3[] = { + "\xeb\xa3\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba4[] = { + "\xeb\xa4\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba5[] = { + "\xeb\xa5\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba6[] = { + "\xeb\xa6\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba7[] = { + "\xeb\xa7\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba8[] = { + "\xeb\xa8\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa8\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eba9[] = { + "\xeb\xa9\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebaa[] = { + "\xeb\xaa\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebab[] = { + "\xeb\xab\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebac[] = { + "\xeb\xac\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebad[] = { + "\xeb\xad\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebae[] = { + "\xeb\xae\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebaf[] = { + "\xeb\xaf\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xaf\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb0[] = { + "\xeb\xb0\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb1[] = { + "\xeb\xb1\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb2[] = { + "\xeb\xb2\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb3[] = { + "\xeb\xb3\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb4[] = { + "\xeb\xb4\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb5[] = { + "\xeb\xb5\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb6[] = { + "\xeb\xb6\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb6\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb7[] = { + "\xeb\xb7\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb8[] = { + "\xeb\xb8\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebb9[] = { + "\xeb\xb9\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebba[] = { + "\xeb\xba\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebbb[] = { + "\xeb\xbb\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebbc[] = { + "\xeb\xbc\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebbd[] = { + "\xeb\xbd\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbd\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebbe[] = { + "\xeb\xbe\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ebbf[] = { + "\xeb\xbf\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec80[] = { + "\xec\x80\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec81[] = { + "\xec\x81\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec82[] = { + "\xec\x82\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec83[] = { + "\xec\x83\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec84[] = { + "\xec\x84\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x84\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec85[] = { + "\xec\x85\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec86[] = { + "\xec\x86\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec87[] = { + "\xec\x87\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec88[] = { + "\xec\x88\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec89[] = { + "\xec\x89\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec8a[] = { + "\xec\x8a\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec8b[] = { + "\xec\x8b\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8b\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec8c[] = { + "\xec\x8c\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec8d[] = { + "\xec\x8d\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec8e[] = { + "\xec\x8e\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec8f[] = { + "\xec\x8f\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec90[] = { + "\xec\x90\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec91[] = { + "\xec\x91\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec92[] = { + "\xec\x92\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x92\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec93[] = { + "\xec\x93\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec94[] = { + "\xec\x94\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec95[] = { + "\xec\x95\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec96[] = { + "\xec\x96\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec97[] = { + "\xec\x97\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec98[] = { + "\xec\x98\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec99[] = { + "\xec\x99\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x99\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec9a[] = { + "\xec\x9a\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec9b[] = { + "\xec\x9b\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec9c[] = { + "\xec\x9c\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec9d[] = { + "\xec\x9d\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec9e[] = { + "\xec\x9e\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ec9f[] = { + "\xec\x9f\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca0[] = { + "\xec\xa0\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa0\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca1[] = { + "\xec\xa1\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca2[] = { + "\xec\xa2\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca3[] = { + "\xec\xa3\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca4[] = { + "\xec\xa4\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca5[] = { + "\xec\xa5\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca6[] = { + "\xec\xa6\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca7[] = { + "\xec\xa7\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa7\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca8[] = { + "\xec\xa8\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_eca9[] = { + "\xec\xa9\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecaa[] = { + "\xec\xaa\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecab[] = { + "\xec\xab\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecac[] = { + "\xec\xac\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecad[] = { + "\xec\xad\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecae[] = { + "\xec\xae\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xae\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecaf[] = { + "\xec\xaf\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb0[] = { + "\xec\xb0\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb1[] = { + "\xec\xb1\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb2[] = { + "\xec\xb2\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb3[] = { + "\xec\xb3\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb4[] = { + "\xec\xb4\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb5[] = { + "\xec\xb5\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb5\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb6[] = { + "\xec\xb6\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb7[] = { + "\xec\xb7\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb8[] = { + "\xec\xb8\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecb9[] = { + "\xec\xb9\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecba[] = { + "\xec\xba\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecbb[] = { + "\xec\xbb\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecbc[] = { + "\xec\xbc\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbc\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecbd[] = { + "\xec\xbd\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecbe[] = { + "\xec\xbe\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ecbf[] = { + "\xec\xbf\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed80[] = { + "\xed\x80\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed81[] = { + "\xed\x81\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed82[] = { + "\xed\x82\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed83[] = { + "\xed\x83\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x83\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed84[] = { + "\xed\x84\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed85[] = { + "\xed\x85\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed86[] = { + "\xed\x86\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed87[] = { + "\xed\x87\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed88[] = { + "\xed\x88\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed89[] = { + "\xed\x89\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed8a[] = { + "\xed\x8a\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8a\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed8b[] = { + "\xed\x8b\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed8c[] = { + "\xed\x8c\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed8d[] = { + "\xed\x8d\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed8e[] = { + "\xed\x8e\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed8f[] = { + "\xed\x8f\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed90[] = { + "\xed\x90\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed91[] = { + "\xed\x91\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x91\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed92[] = { + "\xed\x92\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed93[] = { + "\xed\x93\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed94[] = { + "\xed\x94\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed95[] = { + "\xed\x95\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed96[] = { + "\xed\x96\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed97[] = { + "\xed\x97\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xaa" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed98[] = { + "\xed\x98\x86", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x98\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed99[] = { + "\xed\x99\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed9a[] = { + "\xed\x9a\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed9b[] = { + "\xed\x9b\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed9c[] = { + "\xed\x9c\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186ad_table_ed9d[] = { + "\xed\x9d\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb2" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186ad(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ad_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ad_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ad_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ad_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ad_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ad_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ad_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x8e"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab0[] = { + "\xea\xb0\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb0\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab1[] = { + "\xea\xb1\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab2[] = { + "\xea\xb2\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab3[] = { + "\xea\xb3\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab4[] = { + "\xea\xb4\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab5[] = { + "\xea\xb5\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab6[] = { + "\xea\xb6\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab7[] = { + "\xea\xb7\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb7\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab8[] = { + "\xea\xb8\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eab9[] = { + "\xea\xb9\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eaba[] = { + "\xea\xba\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eabb[] = { + "\xea\xbb\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eabc[] = { + "\xea\xbc\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eabd[] = { + "\xea\xbd\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eabe[] = { + "\xea\xbe\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbe\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eabf[] = { + "\xea\xbf\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb80[] = { + "\xeb\x80\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb81[] = { + "\xeb\x81\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb82[] = { + "\xeb\x82\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb83[] = { + "\xeb\x83\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb84[] = { + "\xeb\x84\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb85[] = { + "\xeb\x85\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x85\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb86[] = { + "\xeb\x86\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb87[] = { + "\xeb\x87\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb88[] = { + "\xeb\x88\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb89[] = { + "\xeb\x89\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb8a[] = { + "\xeb\x8a\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb8b[] = { + "\xeb\x8b\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb8c[] = { + "\xeb\x8c\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8c\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb8d[] = { + "\xeb\x8d\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb8e[] = { + "\xeb\x8e\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb8f[] = { + "\xeb\x8f\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb90[] = { + "\xeb\x90\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb91[] = { + "\xeb\x91\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb92[] = { + "\xeb\x92\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb93[] = { + "\xeb\x93\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x93\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb94[] = { + "\xeb\x94\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb95[] = { + "\xeb\x95\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb96[] = { + "\xeb\x96\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb97[] = { + "\xeb\x97\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb98[] = { + "\xeb\x98\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb99[] = { + "\xeb\x99\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb9a[] = { + "\xeb\x9a\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9a\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb9b[] = { + "\xeb\x9b\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb9c[] = { + "\xeb\x9c\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb9d[] = { + "\xeb\x9d\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb9e[] = { + "\xeb\x9e\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eb9f[] = { + "\xeb\x9f\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba0[] = { + "\xeb\xa0\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba1[] = { + "\xeb\xa1\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa1\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba2[] = { + "\xeb\xa2\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba3[] = { + "\xeb\xa3\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba4[] = { + "\xeb\xa4\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba5[] = { + "\xeb\xa5\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba6[] = { + "\xeb\xa6\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba7[] = { + "\xeb\xa7\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba8[] = { + "\xeb\xa8\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa8\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eba9[] = { + "\xeb\xa9\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebaa[] = { + "\xeb\xaa\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebab[] = { + "\xeb\xab\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebac[] = { + "\xeb\xac\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebad[] = { + "\xeb\xad\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebae[] = { + "\xeb\xae\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebaf[] = { + "\xeb\xaf\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xaf\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb0[] = { + "\xeb\xb0\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb1[] = { + "\xeb\xb1\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb2[] = { + "\xeb\xb2\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb3[] = { + "\xeb\xb3\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb4[] = { + "\xeb\xb4\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb5[] = { + "\xeb\xb5\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb6[] = { + "\xeb\xb6\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb6\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb7[] = { + "\xeb\xb7\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb8[] = { + "\xeb\xb8\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebb9[] = { + "\xeb\xb9\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebba[] = { + "\xeb\xba\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebbb[] = { + "\xeb\xbb\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebbc[] = { + "\xeb\xbc\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebbd[] = { + "\xeb\xbd\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbd\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebbe[] = { + "\xeb\xbe\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ebbf[] = { + "\xeb\xbf\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec80[] = { + "\xec\x80\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec81[] = { + "\xec\x81\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec82[] = { + "\xec\x82\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec83[] = { + "\xec\x83\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec84[] = { + "\xec\x84\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x84\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec85[] = { + "\xec\x85\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec86[] = { + "\xec\x86\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec87[] = { + "\xec\x87\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec88[] = { + "\xec\x88\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec89[] = { + "\xec\x89\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec8a[] = { + "\xec\x8a\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec8b[] = { + "\xec\x8b\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8b\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec8c[] = { + "\xec\x8c\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec8d[] = { + "\xec\x8d\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec8e[] = { + "\xec\x8e\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec8f[] = { + "\xec\x8f\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec90[] = { + "\xec\x90\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec91[] = { + "\xec\x91\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec92[] = { + "\xec\x92\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x92\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec93[] = { + "\xec\x93\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec94[] = { + "\xec\x94\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec95[] = { + "\xec\x95\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec96[] = { + "\xec\x96\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec97[] = { + "\xec\x97\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec98[] = { + "\xec\x98\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec99[] = { + "\xec\x99\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x99\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec9a[] = { + "\xec\x9a\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec9b[] = { + "\xec\x9b\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec9c[] = { + "\xec\x9c\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec9d[] = { + "\xec\x9d\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec9e[] = { + "\xec\x9e\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ec9f[] = { + "\xec\x9f\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca0[] = { + "\xec\xa0\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa0\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca1[] = { + "\xec\xa1\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca2[] = { + "\xec\xa2\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca3[] = { + "\xec\xa3\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca4[] = { + "\xec\xa4\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca5[] = { + "\xec\xa5\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca6[] = { + "\xec\xa6\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca7[] = { + "\xec\xa7\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa7\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca8[] = { + "\xec\xa8\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_eca9[] = { + "\xec\xa9\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecaa[] = { + "\xec\xaa\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecab[] = { + "\xec\xab\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecac[] = { + "\xec\xac\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecad[] = { + "\xec\xad\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecae[] = { + "\xec\xae\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xae\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecaf[] = { + "\xec\xaf\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb0[] = { + "\xec\xb0\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb1[] = { + "\xec\xb1\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb2[] = { + "\xec\xb2\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb3[] = { + "\xec\xb3\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb4[] = { + "\xec\xb4\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb5[] = { + "\xec\xb5\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb5\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb6[] = { + "\xec\xb6\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb7[] = { + "\xec\xb7\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb8[] = { + "\xec\xb8\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecb9[] = { + "\xec\xb9\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecba[] = { + "\xec\xba\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecbb[] = { + "\xec\xbb\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecbc[] = { + "\xec\xbc\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbc\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecbd[] = { + "\xec\xbd\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecbe[] = { + "\xec\xbe\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ecbf[] = { + "\xec\xbf\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed80[] = { + "\xed\x80\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed81[] = { + "\xed\x81\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed82[] = { + "\xed\x82\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed83[] = { + "\xed\x83\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x83\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed84[] = { + "\xed\x84\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed85[] = { + "\xed\x85\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed86[] = { + "\xed\x86\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed87[] = { + "\xed\x87\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed88[] = { + "\xed\x88\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed89[] = { + "\xed\x89\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed8a[] = { + "\xed\x8a\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8a\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed8b[] = { + "\xed\x8b\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed8c[] = { + "\xed\x8c\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed8d[] = { + "\xed\x8d\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed8e[] = { + "\xed\x8e\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed8f[] = { + "\xed\x8f\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed90[] = { + "\xed\x90\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed91[] = { + "\xed\x91\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x91\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed92[] = { + "\xed\x92\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed93[] = { + "\xed\x93\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed94[] = { + "\xed\x94\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed95[] = { + "\xed\x95\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed96[] = { + "\xed\x96\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed97[] = { + "\xed\x97\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xab" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed98[] = { + "\xed\x98\x87", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x98\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed99[] = { + "\xed\x99\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed9a[] = { + "\xed\x9a\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed9b[] = { + "\xed\x9b\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed9c[] = { + "\xed\x9c\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ae_table_ed9d[] = { + "\xed\x9d\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb3" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186ae(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ae_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ae_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ae_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ae_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ae_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ae_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ae_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x8f"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab0[] = { + "\xea\xb0\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab1[] = { + "\xea\xb1\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab2[] = { + "\xea\xb2\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab3[] = { + "\xea\xb3\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab4[] = { + "\xea\xb4\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab5[] = { + "\xea\xb5\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab6[] = { + "\xea\xb6\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab7[] = { + "\xea\xb7\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab8[] = { + "\xea\xb8\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eab9[] = { + "\xea\xb9\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eaba[] = { + "\xea\xba\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eabb[] = { + "\xea\xbb\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eabc[] = { + "\xea\xbc\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eabd[] = { + "\xea\xbd\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eabe[] = { + "\xea\xbe\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eabf[] = { + "\xea\xbf\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb80[] = { + "\xeb\x80\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb81[] = { + "\xeb\x81\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb82[] = { + "\xeb\x82\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb83[] = { + "\xeb\x83\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb84[] = { + "\xeb\x84\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb85[] = { + "\xeb\x85\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb86[] = { + "\xeb\x86\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb87[] = { + "\xeb\x87\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb88[] = { + "\xeb\x88\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb89[] = { + "\xeb\x89\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb8a[] = { + "\xeb\x8a\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb8b[] = { + "\xeb\x8b\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb8c[] = { + "\xeb\x8c\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb8d[] = { + "\xeb\x8d\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb8e[] = { + "\xeb\x8e\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb8f[] = { + "\xeb\x8f\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb90[] = { + "\xeb\x90\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb91[] = { + "\xeb\x91\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb92[] = { + "\xeb\x92\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb93[] = { + "\xeb\x93\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb94[] = { + "\xeb\x94\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb95[] = { + "\xeb\x95\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb96[] = { + "\xeb\x96\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb97[] = { + "\xeb\x97\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb98[] = { + "\xeb\x98\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb99[] = { + "\xeb\x99\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb9a[] = { + "\xeb\x9a\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb9b[] = { + "\xeb\x9b\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb9c[] = { + "\xeb\x9c\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb9d[] = { + "\xeb\x9d\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb9e[] = { + "\xeb\x9e\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eb9f[] = { + "\xeb\x9f\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba0[] = { + "\xeb\xa0\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba1[] = { + "\xeb\xa1\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba2[] = { + "\xeb\xa2\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba3[] = { + "\xeb\xa3\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba4[] = { + "\xeb\xa4\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba5[] = { + "\xeb\xa5\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba6[] = { + "\xeb\xa6\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba7[] = { + "\xeb\xa7\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba8[] = { + "\xeb\xa8\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eba9[] = { + "\xeb\xa9\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebaa[] = { + "\xeb\xaa\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebab[] = { + "\xeb\xab\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebac[] = { + "\xeb\xac\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebad[] = { + "\xeb\xad\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebae[] = { + "\xeb\xae\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebaf[] = { + "\xeb\xaf\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb0[] = { + "\xeb\xb0\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb1[] = { + "\xeb\xb1\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb2[] = { + "\xeb\xb2\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb3[] = { + "\xeb\xb3\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb4[] = { + "\xeb\xb4\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb5[] = { + "\xeb\xb5\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb6[] = { + "\xeb\xb6\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb7[] = { + "\xeb\xb7\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb8[] = { + "\xeb\xb8\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebb9[] = { + "\xeb\xb9\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebba[] = { + "\xeb\xba\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebbb[] = { + "\xeb\xbb\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebbc[] = { + "\xeb\xbc\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebbd[] = { + "\xeb\xbd\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebbe[] = { + "\xeb\xbe\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ebbf[] = { + "\xeb\xbf\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec80[] = { + "\xec\x80\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec81[] = { + "\xec\x81\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec82[] = { + "\xec\x82\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec83[] = { + "\xec\x83\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec84[] = { + "\xec\x84\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec85[] = { + "\xec\x85\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec86[] = { + "\xec\x86\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec87[] = { + "\xec\x87\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec88[] = { + "\xec\x88\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec89[] = { + "\xec\x89\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec8a[] = { + "\xec\x8a\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec8b[] = { + "\xec\x8b\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec8c[] = { + "\xec\x8c\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec8d[] = { + "\xec\x8d\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec8e[] = { + "\xec\x8e\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec8f[] = { + "\xec\x8f\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec90[] = { + "\xec\x90\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec91[] = { + "\xec\x91\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec92[] = { + "\xec\x92\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec93[] = { + "\xec\x93\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec94[] = { + "\xec\x94\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec95[] = { + "\xec\x95\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec96[] = { + "\xec\x96\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec97[] = { + "\xec\x97\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec98[] = { + "\xec\x98\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec99[] = { + "\xec\x99\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec9a[] = { + "\xec\x9a\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec9b[] = { + "\xec\x9b\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec9c[] = { + "\xec\x9c\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec9d[] = { + "\xec\x9d\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec9e[] = { + "\xec\x9e\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ec9f[] = { + "\xec\x9f\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca0[] = { + "\xec\xa0\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca1[] = { + "\xec\xa1\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca2[] = { + "\xec\xa2\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca3[] = { + "\xec\xa3\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca4[] = { + "\xec\xa4\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca5[] = { + "\xec\xa5\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca6[] = { + "\xec\xa6\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca7[] = { + "\xec\xa7\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca8[] = { + "\xec\xa8\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_eca9[] = { + "\xec\xa9\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecaa[] = { + "\xec\xaa\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecab[] = { + "\xec\xab\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecac[] = { + "\xec\xac\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecad[] = { + "\xec\xad\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecae[] = { + "\xec\xae\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecaf[] = { + "\xec\xaf\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb0[] = { + "\xec\xb0\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb1[] = { + "\xec\xb1\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb2[] = { + "\xec\xb2\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb3[] = { + "\xec\xb3\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb4[] = { + "\xec\xb4\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb5[] = { + "\xec\xb5\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb6[] = { + "\xec\xb6\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb7[] = { + "\xec\xb7\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb8[] = { + "\xec\xb8\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecb9[] = { + "\xec\xb9\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecba[] = { + "\xec\xba\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecbb[] = { + "\xec\xbb\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecbc[] = { + "\xec\xbc\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecbd[] = { + "\xec\xbd\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecbe[] = { + "\xec\xbe\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ecbf[] = { + "\xec\xbf\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed80[] = { + "\xed\x80\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed81[] = { + "\xed\x81\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed82[] = { + "\xed\x82\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed83[] = { + "\xed\x83\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed84[] = { + "\xed\x84\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed85[] = { + "\xed\x85\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed86[] = { + "\xed\x86\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed87[] = { + "\xed\x87\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed88[] = { + "\xed\x88\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed89[] = { + "\xed\x89\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed8a[] = { + "\xed\x8a\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed8b[] = { + "\xed\x8b\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed8c[] = { + "\xed\x8c\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed8d[] = { + "\xed\x8d\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed8e[] = { + "\xed\x8e\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed8f[] = { + "\xed\x8f\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed90[] = { + "\xed\x90\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed91[] = { + "\xed\x91\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed92[] = { + "\xed\x92\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed93[] = { + "\xed\x93\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed94[] = { + "\xed\x94\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed95[] = { + "\xed\x95\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed96[] = { + "\xed\x96\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed97[] = { + "\xed\x97\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xac" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed98[] = { + "\xed\x98\x88", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed99[] = { + "\xed\x99\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed9a[] = { + "\xed\x9a\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed9b[] = { + "\xed\x9b\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed9c[] = { + "\xed\x9c\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186af_table_ed9d[] = { + "\xed\x9d\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb4" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186af(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186af_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186af_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186af_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186af_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186af_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186af_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186af_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x90"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab0[] = { + "\xea\xb0\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab1[] = { + "\xea\xb1\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab2[] = { + "\xea\xb2\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab3[] = { + "\xea\xb3\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab4[] = { + "\xea\xb4\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab5[] = { + "\xea\xb5\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab6[] = { + "\xea\xb6\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab7[] = { + "\xea\xb7\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab8[] = { + "\xea\xb8\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eab9[] = { + "\xea\xb9\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eaba[] = { + "\xea\xba\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eabb[] = { + "\xea\xbb\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eabc[] = { + "\xea\xbc\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eabd[] = { + "\xea\xbd\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eabe[] = { + "\xea\xbe\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eabf[] = { + "\xea\xbf\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb80[] = { + "\xeb\x80\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb81[] = { + "\xeb\x81\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb82[] = { + "\xeb\x82\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb83[] = { + "\xeb\x83\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb84[] = { + "\xeb\x84\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb85[] = { + "\xeb\x85\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb86[] = { + "\xeb\x86\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb87[] = { + "\xeb\x87\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb88[] = { + "\xeb\x88\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb89[] = { + "\xeb\x89\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb8a[] = { + "\xeb\x8a\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb8b[] = { + "\xeb\x8b\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb8c[] = { + "\xeb\x8c\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb8d[] = { + "\xeb\x8d\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb8e[] = { + "\xeb\x8e\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb8f[] = { + "\xeb\x8f\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb90[] = { + "\xeb\x90\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb91[] = { + "\xeb\x91\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb92[] = { + "\xeb\x92\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb93[] = { + "\xeb\x93\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb94[] = { + "\xeb\x94\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb95[] = { + "\xeb\x95\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb96[] = { + "\xeb\x96\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb97[] = { + "\xeb\x97\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb98[] = { + "\xeb\x98\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb99[] = { + "\xeb\x99\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb9a[] = { + "\xeb\x9a\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb9b[] = { + "\xeb\x9b\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb9c[] = { + "\xeb\x9c\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb9d[] = { + "\xeb\x9d\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb9e[] = { + "\xeb\x9e\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eb9f[] = { + "\xeb\x9f\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba0[] = { + "\xeb\xa0\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba1[] = { + "\xeb\xa1\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba2[] = { + "\xeb\xa2\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba3[] = { + "\xeb\xa3\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba4[] = { + "\xeb\xa4\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba5[] = { + "\xeb\xa5\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba6[] = { + "\xeb\xa6\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba7[] = { + "\xeb\xa7\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba8[] = { + "\xeb\xa8\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eba9[] = { + "\xeb\xa9\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebaa[] = { + "\xeb\xaa\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebab[] = { + "\xeb\xab\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebac[] = { + "\xeb\xac\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebad[] = { + "\xeb\xad\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebae[] = { + "\xeb\xae\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebaf[] = { + "\xeb\xaf\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb0[] = { + "\xeb\xb0\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb1[] = { + "\xeb\xb1\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb2[] = { + "\xeb\xb2\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb3[] = { + "\xeb\xb3\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb4[] = { + "\xeb\xb4\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb5[] = { + "\xeb\xb5\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb6[] = { + "\xeb\xb6\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb7[] = { + "\xeb\xb7\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb8[] = { + "\xeb\xb8\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebb9[] = { + "\xeb\xb9\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebba[] = { + "\xeb\xba\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebbb[] = { + "\xeb\xbb\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebbc[] = { + "\xeb\xbc\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebbd[] = { + "\xeb\xbd\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebbe[] = { + "\xeb\xbe\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ebbf[] = { + "\xeb\xbf\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec80[] = { + "\xec\x80\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec81[] = { + "\xec\x81\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec82[] = { + "\xec\x82\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec83[] = { + "\xec\x83\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec84[] = { + "\xec\x84\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec85[] = { + "\xec\x85\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec86[] = { + "\xec\x86\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec87[] = { + "\xec\x87\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec88[] = { + "\xec\x88\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec89[] = { + "\xec\x89\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec8a[] = { + "\xec\x8a\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec8b[] = { + "\xec\x8b\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec8c[] = { + "\xec\x8c\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec8d[] = { + "\xec\x8d\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec8e[] = { + "\xec\x8e\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec8f[] = { + "\xec\x8f\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec90[] = { + "\xec\x90\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec91[] = { + "\xec\x91\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec92[] = { + "\xec\x92\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec93[] = { + "\xec\x93\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec94[] = { + "\xec\x94\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec95[] = { + "\xec\x95\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec96[] = { + "\xec\x96\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec97[] = { + "\xec\x97\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec98[] = { + "\xec\x98\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec99[] = { + "\xec\x99\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec9a[] = { + "\xec\x9a\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec9b[] = { + "\xec\x9b\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec9c[] = { + "\xec\x9c\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec9d[] = { + "\xec\x9d\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec9e[] = { + "\xec\x9e\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ec9f[] = { + "\xec\x9f\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca0[] = { + "\xec\xa0\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca1[] = { + "\xec\xa1\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca2[] = { + "\xec\xa2\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca3[] = { + "\xec\xa3\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca4[] = { + "\xec\xa4\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca5[] = { + "\xec\xa5\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca6[] = { + "\xec\xa6\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca7[] = { + "\xec\xa7\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca8[] = { + "\xec\xa8\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_eca9[] = { + "\xec\xa9\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecaa[] = { + "\xec\xaa\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecab[] = { + "\xec\xab\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecac[] = { + "\xec\xac\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecad[] = { + "\xec\xad\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecae[] = { + "\xec\xae\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecaf[] = { + "\xec\xaf\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb0[] = { + "\xec\xb0\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb1[] = { + "\xec\xb1\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb2[] = { + "\xec\xb2\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb3[] = { + "\xec\xb3\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb4[] = { + "\xec\xb4\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb5[] = { + "\xec\xb5\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb6[] = { + "\xec\xb6\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb7[] = { + "\xec\xb7\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb8[] = { + "\xec\xb8\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecb9[] = { + "\xec\xb9\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecba[] = { + "\xec\xba\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecbb[] = { + "\xec\xbb\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecbc[] = { + "\xec\xbc\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecbd[] = { + "\xec\xbd\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecbe[] = { + "\xec\xbe\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ecbf[] = { + "\xec\xbf\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed80[] = { + "\xed\x80\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed81[] = { + "\xed\x81\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed82[] = { + "\xed\x82\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed83[] = { + "\xed\x83\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed84[] = { + "\xed\x84\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed85[] = { + "\xed\x85\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed86[] = { + "\xed\x86\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed87[] = { + "\xed\x87\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed88[] = { + "\xed\x88\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed89[] = { + "\xed\x89\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed8a[] = { + "\xed\x8a\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed8b[] = { + "\xed\x8b\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed8c[] = { + "\xed\x8c\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed8d[] = { + "\xed\x8d\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed8e[] = { + "\xed\x8e\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed8f[] = { + "\xed\x8f\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed90[] = { + "\xed\x90\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed91[] = { + "\xed\x91\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed92[] = { + "\xed\x92\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed93[] = { + "\xed\x93\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed94[] = { + "\xed\x94\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed95[] = { + "\xed\x95\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed96[] = { + "\xed\x96\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed97[] = { + "\xed\x97\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xad" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed98[] = { + "\xed\x98\x89", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed99[] = { + "\xed\x99\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed9a[] = { + "\xed\x9a\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed9b[] = { + "\xed\x9b\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed9c[] = { + "\xed\x9c\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b0_table_ed9d[] = { + "\xed\x9d\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb5" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b0(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b0_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b0_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b0_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b0_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b0_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b0_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b0_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x91"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab0[] = { + "\xea\xb0\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab1[] = { + "\xea\xb1\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab2[] = { + "\xea\xb2\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab3[] = { + "\xea\xb3\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab4[] = { + "\xea\xb4\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab5[] = { + "\xea\xb5\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab6[] = { + "\xea\xb6\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab7[] = { + "\xea\xb7\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab8[] = { + "\xea\xb8\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eab9[] = { + "\xea\xb9\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eaba[] = { + "\xea\xba\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eabb[] = { + "\xea\xbb\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eabc[] = { + "\xea\xbc\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eabd[] = { + "\xea\xbd\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eabe[] = { + "\xea\xbe\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eabf[] = { + "\xea\xbf\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb80[] = { + "\xeb\x80\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb81[] = { + "\xeb\x81\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb82[] = { + "\xeb\x82\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb83[] = { + "\xeb\x83\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb84[] = { + "\xeb\x84\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb85[] = { + "\xeb\x85\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb86[] = { + "\xeb\x86\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb87[] = { + "\xeb\x87\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb88[] = { + "\xeb\x88\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb89[] = { + "\xeb\x89\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb8a[] = { + "\xeb\x8a\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb8b[] = { + "\xeb\x8b\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb8c[] = { + "\xeb\x8c\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb8d[] = { + "\xeb\x8d\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb8e[] = { + "\xeb\x8e\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb8f[] = { + "\xeb\x8f\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb90[] = { + "\xeb\x90\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb91[] = { + "\xeb\x91\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb92[] = { + "\xeb\x92\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb93[] = { + "\xeb\x93\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb94[] = { + "\xeb\x94\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb95[] = { + "\xeb\x95\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb96[] = { + "\xeb\x96\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb97[] = { + "\xeb\x97\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb98[] = { + "\xeb\x98\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb99[] = { + "\xeb\x99\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb9a[] = { + "\xeb\x9a\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb9b[] = { + "\xeb\x9b\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb9c[] = { + "\xeb\x9c\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb9d[] = { + "\xeb\x9d\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb9e[] = { + "\xeb\x9e\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eb9f[] = { + "\xeb\x9f\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba0[] = { + "\xeb\xa0\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba1[] = { + "\xeb\xa1\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba2[] = { + "\xeb\xa2\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba3[] = { + "\xeb\xa3\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba4[] = { + "\xeb\xa4\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba5[] = { + "\xeb\xa5\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba6[] = { + "\xeb\xa6\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba7[] = { + "\xeb\xa7\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba8[] = { + "\xeb\xa8\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eba9[] = { + "\xeb\xa9\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebaa[] = { + "\xeb\xaa\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebab[] = { + "\xeb\xab\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebac[] = { + "\xeb\xac\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebad[] = { + "\xeb\xad\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebae[] = { + "\xeb\xae\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebaf[] = { + "\xeb\xaf\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb0[] = { + "\xeb\xb0\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb1[] = { + "\xeb\xb1\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb2[] = { + "\xeb\xb2\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb3[] = { + "\xeb\xb3\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb4[] = { + "\xeb\xb4\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb5[] = { + "\xeb\xb5\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb6[] = { + "\xeb\xb6\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb7[] = { + "\xeb\xb7\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb8[] = { + "\xeb\xb8\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebb9[] = { + "\xeb\xb9\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebba[] = { + "\xeb\xba\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebbb[] = { + "\xeb\xbb\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebbc[] = { + "\xeb\xbc\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebbd[] = { + "\xeb\xbd\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebbe[] = { + "\xeb\xbe\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ebbf[] = { + "\xeb\xbf\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec80[] = { + "\xec\x80\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec81[] = { + "\xec\x81\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec82[] = { + "\xec\x82\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec83[] = { + "\xec\x83\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec84[] = { + "\xec\x84\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec85[] = { + "\xec\x85\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec86[] = { + "\xec\x86\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec87[] = { + "\xec\x87\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec88[] = { + "\xec\x88\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec89[] = { + "\xec\x89\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec8a[] = { + "\xec\x8a\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec8b[] = { + "\xec\x8b\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec8c[] = { + "\xec\x8c\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec8d[] = { + "\xec\x8d\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec8e[] = { + "\xec\x8e\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec8f[] = { + "\xec\x8f\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec90[] = { + "\xec\x90\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec91[] = { + "\xec\x91\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec92[] = { + "\xec\x92\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec93[] = { + "\xec\x93\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec94[] = { + "\xec\x94\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec95[] = { + "\xec\x95\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec96[] = { + "\xec\x96\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec97[] = { + "\xec\x97\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec98[] = { + "\xec\x98\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec99[] = { + "\xec\x99\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec9a[] = { + "\xec\x9a\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec9b[] = { + "\xec\x9b\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec9c[] = { + "\xec\x9c\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec9d[] = { + "\xec\x9d\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec9e[] = { + "\xec\x9e\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ec9f[] = { + "\xec\x9f\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca0[] = { + "\xec\xa0\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca1[] = { + "\xec\xa1\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca2[] = { + "\xec\xa2\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca3[] = { + "\xec\xa3\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca4[] = { + "\xec\xa4\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca5[] = { + "\xec\xa5\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca6[] = { + "\xec\xa6\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca7[] = { + "\xec\xa7\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca8[] = { + "\xec\xa8\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_eca9[] = { + "\xec\xa9\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecaa[] = { + "\xec\xaa\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecab[] = { + "\xec\xab\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecac[] = { + "\xec\xac\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecad[] = { + "\xec\xad\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecae[] = { + "\xec\xae\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecaf[] = { + "\xec\xaf\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb0[] = { + "\xec\xb0\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb1[] = { + "\xec\xb1\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb2[] = { + "\xec\xb2\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb3[] = { + "\xec\xb3\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb4[] = { + "\xec\xb4\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb5[] = { + "\xec\xb5\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb6[] = { + "\xec\xb6\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb7[] = { + "\xec\xb7\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb8[] = { + "\xec\xb8\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecb9[] = { + "\xec\xb9\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecba[] = { + "\xec\xba\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecbb[] = { + "\xec\xbb\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecbc[] = { + "\xec\xbc\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecbd[] = { + "\xec\xbd\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecbe[] = { + "\xec\xbe\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ecbf[] = { + "\xec\xbf\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed80[] = { + "\xed\x80\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed81[] = { + "\xed\x81\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed82[] = { + "\xed\x82\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed83[] = { + "\xed\x83\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed84[] = { + "\xed\x84\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed85[] = { + "\xed\x85\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed86[] = { + "\xed\x86\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed87[] = { + "\xed\x87\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed88[] = { + "\xed\x88\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed89[] = { + "\xed\x89\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed8a[] = { + "\xed\x8a\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed8b[] = { + "\xed\x8b\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed8c[] = { + "\xed\x8c\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed8d[] = { + "\xed\x8d\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed8e[] = { + "\xed\x8e\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed8f[] = { + "\xed\x8f\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed90[] = { + "\xed\x90\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed91[] = { + "\xed\x91\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed92[] = { + "\xed\x92\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed93[] = { + "\xed\x93\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed94[] = { + "\xed\x94\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed95[] = { + "\xed\x95\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed96[] = { + "\xed\x96\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed97[] = { + "\xed\x97\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xae" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed98[] = { + "\xed\x98\x8a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed99[] = { + "\xed\x99\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed9a[] = { + "\xed\x9a\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed9b[] = { + "\xed\x9b\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed9c[] = { + "\xed\x9c\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b1_table_ed9d[] = { + "\xed\x9d\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb6" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b1(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b1_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b1_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b1_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b1_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b1_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b1_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b1_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x92"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab0[] = { + "\xea\xb0\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab1[] = { + "\xea\xb1\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab2[] = { + "\xea\xb2\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab3[] = { + "\xea\xb3\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab4[] = { + "\xea\xb4\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb4\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab5[] = { + "\xea\xb5\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab6[] = { + "\xea\xb6\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab7[] = { + "\xea\xb7\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab8[] = { + "\xea\xb8\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eab9[] = { + "\xea\xb9\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eaba[] = { + "\xea\xba\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eabb[] = { + "\xea\xbb\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbb\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eabc[] = { + "\xea\xbc\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eabd[] = { + "\xea\xbd\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eabe[] = { + "\xea\xbe\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eabf[] = { + "\xea\xbf\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb80[] = { + "\xeb\x80\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb81[] = { + "\xeb\x81\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb82[] = { + "\xeb\x82\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x82\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb83[] = { + "\xeb\x83\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb84[] = { + "\xeb\x84\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb85[] = { + "\xeb\x85\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb86[] = { + "\xeb\x86\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb87[] = { + "\xeb\x87\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb88[] = { + "\xeb\x88\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb89[] = { + "\xeb\x89\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x89\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb8a[] = { + "\xeb\x8a\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb8b[] = { + "\xeb\x8b\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb8c[] = { + "\xeb\x8c\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb8d[] = { + "\xeb\x8d\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb8e[] = { + "\xeb\x8e\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb8f[] = { + "\xeb\x8f\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb90[] = { + "\xeb\x90\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x90\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb91[] = { + "\xeb\x91\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb92[] = { + "\xeb\x92\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb93[] = { + "\xeb\x93\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb94[] = { + "\xeb\x94\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb95[] = { + "\xeb\x95\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb96[] = { + "\xeb\x96\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb97[] = { + "\xeb\x97\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x97\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb98[] = { + "\xeb\x98\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb99[] = { + "\xeb\x99\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb9a[] = { + "\xeb\x9a\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb9b[] = { + "\xeb\x9b\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb9c[] = { + "\xeb\x9c\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb9d[] = { + "\xeb\x9d\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb9e[] = { + "\xeb\x9e\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9e\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eb9f[] = { + "\xeb\x9f\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba0[] = { + "\xeb\xa0\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba1[] = { + "\xeb\xa1\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba2[] = { + "\xeb\xa2\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba3[] = { + "\xeb\xa3\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba4[] = { + "\xeb\xa4\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba5[] = { + "\xeb\xa5\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa5\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba6[] = { + "\xeb\xa6\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba7[] = { + "\xeb\xa7\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba8[] = { + "\xeb\xa8\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eba9[] = { + "\xeb\xa9\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebaa[] = { + "\xeb\xaa\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebab[] = { + "\xeb\xab\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebac[] = { + "\xeb\xac\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xac\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebad[] = { + "\xeb\xad\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebae[] = { + "\xeb\xae\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebaf[] = { + "\xeb\xaf\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb0[] = { + "\xeb\xb0\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb1[] = { + "\xeb\xb1\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb2[] = { + "\xeb\xb2\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb3[] = { + "\xeb\xb3\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb3\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb4[] = { + "\xeb\xb4\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb5[] = { + "\xeb\xb5\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb6[] = { + "\xeb\xb6\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb7[] = { + "\xeb\xb7\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb8[] = { + "\xeb\xb8\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebb9[] = { + "\xeb\xb9\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebba[] = { + "\xeb\xba\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xba\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebbb[] = { + "\xeb\xbb\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebbc[] = { + "\xeb\xbc\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebbd[] = { + "\xeb\xbd\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebbe[] = { + "\xeb\xbe\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ebbf[] = { + "\xeb\xbf\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec80[] = { + "\xec\x80\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec81[] = { + "\xec\x81\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x81\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec82[] = { + "\xec\x82\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec83[] = { + "\xec\x83\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec84[] = { + "\xec\x84\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec85[] = { + "\xec\x85\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec86[] = { + "\xec\x86\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec87[] = { + "\xec\x87\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec88[] = { + "\xec\x88\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x88\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec89[] = { + "\xec\x89\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec8a[] = { + "\xec\x8a\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec8b[] = { + "\xec\x8b\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec8c[] = { + "\xec\x8c\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec8d[] = { + "\xec\x8d\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec8e[] = { + "\xec\x8e\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec8f[] = { + "\xec\x8f\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8f\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec90[] = { + "\xec\x90\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec91[] = { + "\xec\x91\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec92[] = { + "\xec\x92\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec93[] = { + "\xec\x93\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec94[] = { + "\xec\x94\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec95[] = { + "\xec\x95\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec96[] = { + "\xec\x96\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x96\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec97[] = { + "\xec\x97\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec98[] = { + "\xec\x98\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec99[] = { + "\xec\x99\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec9a[] = { + "\xec\x9a\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec9b[] = { + "\xec\x9b\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec9c[] = { + "\xec\x9c\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec9d[] = { + "\xec\x9d\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9d\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec9e[] = { + "\xec\x9e\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ec9f[] = { + "\xec\x9f\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca0[] = { + "\xec\xa0\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca1[] = { + "\xec\xa1\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca2[] = { + "\xec\xa2\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca3[] = { + "\xec\xa3\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca4[] = { + "\xec\xa4\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa4\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca5[] = { + "\xec\xa5\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca6[] = { + "\xec\xa6\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca7[] = { + "\xec\xa7\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca8[] = { + "\xec\xa8\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_eca9[] = { + "\xec\xa9\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecaa[] = { + "\xec\xaa\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecab[] = { + "\xec\xab\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xab\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecac[] = { + "\xec\xac\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecad[] = { + "\xec\xad\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecae[] = { + "\xec\xae\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecaf[] = { + "\xec\xaf\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb0[] = { + "\xec\xb0\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb1[] = { + "\xec\xb1\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb2[] = { + "\xec\xb2\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb2\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb3[] = { + "\xec\xb3\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb4[] = { + "\xec\xb4\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb5[] = { + "\xec\xb5\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb6[] = { + "\xec\xb6\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb7[] = { + "\xec\xb7\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb8[] = { + "\xec\xb8\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecb9[] = { + "\xec\xb9\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb9\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecba[] = { + "\xec\xba\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecbb[] = { + "\xec\xbb\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecbc[] = { + "\xec\xbc\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecbd[] = { + "\xec\xbd\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecbe[] = { + "\xec\xbe\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ecbf[] = { + "\xec\xbf\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed80[] = { + "\xed\x80\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x80\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed81[] = { + "\xed\x81\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed82[] = { + "\xed\x82\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed83[] = { + "\xed\x83\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed84[] = { + "\xed\x84\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed85[] = { + "\xed\x85\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed86[] = { + "\xed\x86\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed87[] = { + "\xed\x87\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x87\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed88[] = { + "\xed\x88\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed89[] = { + "\xed\x89\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed8a[] = { + "\xed\x8a\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed8b[] = { + "\xed\x8b\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed8c[] = { + "\xed\x8c\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed8d[] = { + "\xed\x8d\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed8e[] = { + "\xed\x8e\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8e\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed8f[] = { + "\xed\x8f\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed90[] = { + "\xed\x90\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed91[] = { + "\xed\x91\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed92[] = { + "\xed\x92\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed93[] = { + "\xed\x93\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed94[] = { + "\xed\x94\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed95[] = { + "\xed\x95\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x95\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed96[] = { + "\xed\x96\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed97[] = { + "\xed\x97\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xaf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed98[] = { + "\xed\x98\x8b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed99[] = { + "\xed\x99\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed9a[] = { + "\xed\x9a\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed9b[] = { + "\xed\x9b\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed9c[] = { + "\xed\x9c\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9c\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b2_table_ed9d[] = { + "\xed\x9d\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb7" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b2(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b2_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b2_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b2_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b2_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b2_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b2_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b2_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x93"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab0[] = { + "\xea\xb0\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab1[] = { + "\xea\xb1\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab2[] = { + "\xea\xb2\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab3[] = { + "\xea\xb3\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab4[] = { + "\xea\xb4\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab5[] = { + "\xea\xb5\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab6[] = { + "\xea\xb6\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab7[] = { + "\xea\xb7\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab8[] = { + "\xea\xb8\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eab9[] = { + "\xea\xb9\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eaba[] = { + "\xea\xba\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eabb[] = { + "\xea\xbb\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eabc[] = { + "\xea\xbc\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eabd[] = { + "\xea\xbd\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eabe[] = { + "\xea\xbe\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eabf[] = { + "\xea\xbf\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb80[] = { + "\xeb\x80\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb81[] = { + "\xeb\x81\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb82[] = { + "\xeb\x82\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb83[] = { + "\xeb\x83\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb84[] = { + "\xeb\x84\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb85[] = { + "\xeb\x85\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb86[] = { + "\xeb\x86\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb87[] = { + "\xeb\x87\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb88[] = { + "\xeb\x88\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb89[] = { + "\xeb\x89\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb8a[] = { + "\xeb\x8a\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb8b[] = { + "\xeb\x8b\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb8c[] = { + "\xeb\x8c\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb8d[] = { + "\xeb\x8d\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb8e[] = { + "\xeb\x8e\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb8f[] = { + "\xeb\x8f\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb90[] = { + "\xeb\x90\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb91[] = { + "\xeb\x91\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb92[] = { + "\xeb\x92\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb93[] = { + "\xeb\x93\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb94[] = { + "\xeb\x94\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb95[] = { + "\xeb\x95\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb96[] = { + "\xeb\x96\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb97[] = { + "\xeb\x97\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb98[] = { + "\xeb\x98\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb99[] = { + "\xeb\x99\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb9a[] = { + "\xeb\x9a\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb9b[] = { + "\xeb\x9b\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb9c[] = { + "\xeb\x9c\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb9d[] = { + "\xeb\x9d\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb9e[] = { + "\xeb\x9e\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eb9f[] = { + "\xeb\x9f\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba0[] = { + "\xeb\xa0\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba1[] = { + "\xeb\xa1\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba2[] = { + "\xeb\xa2\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba3[] = { + "\xeb\xa3\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba4[] = { + "\xeb\xa4\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba5[] = { + "\xeb\xa5\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba6[] = { + "\xeb\xa6\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba7[] = { + "\xeb\xa7\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba8[] = { + "\xeb\xa8\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eba9[] = { + "\xeb\xa9\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebaa[] = { + "\xeb\xaa\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebab[] = { + "\xeb\xab\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebac[] = { + "\xeb\xac\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebad[] = { + "\xeb\xad\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebae[] = { + "\xeb\xae\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebaf[] = { + "\xeb\xaf\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb0[] = { + "\xeb\xb0\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb1[] = { + "\xeb\xb1\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb2[] = { + "\xeb\xb2\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb3[] = { + "\xeb\xb3\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb4[] = { + "\xeb\xb4\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb5[] = { + "\xeb\xb5\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb6[] = { + "\xeb\xb6\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb7[] = { + "\xeb\xb7\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb8[] = { + "\xeb\xb8\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebb9[] = { + "\xeb\xb9\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebba[] = { + "\xeb\xba\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebbb[] = { + "\xeb\xbb\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebbc[] = { + "\xeb\xbc\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebbd[] = { + "\xeb\xbd\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebbe[] = { + "\xeb\xbe\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ebbf[] = { + "\xeb\xbf\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec80[] = { + "\xec\x80\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec81[] = { + "\xec\x81\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec82[] = { + "\xec\x82\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec83[] = { + "\xec\x83\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec84[] = { + "\xec\x84\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec85[] = { + "\xec\x85\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec86[] = { + "\xec\x86\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec87[] = { + "\xec\x87\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec88[] = { + "\xec\x88\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec89[] = { + "\xec\x89\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec8a[] = { + "\xec\x8a\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec8b[] = { + "\xec\x8b\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec8c[] = { + "\xec\x8c\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec8d[] = { + "\xec\x8d\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec8e[] = { + "\xec\x8e\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec8f[] = { + "\xec\x8f\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec90[] = { + "\xec\x90\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec91[] = { + "\xec\x91\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec92[] = { + "\xec\x92\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec93[] = { + "\xec\x93\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec94[] = { + "\xec\x94\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec95[] = { + "\xec\x95\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec96[] = { + "\xec\x96\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec97[] = { + "\xec\x97\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec98[] = { + "\xec\x98\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec99[] = { + "\xec\x99\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec9a[] = { + "\xec\x9a\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec9b[] = { + "\xec\x9b\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec9c[] = { + "\xec\x9c\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec9d[] = { + "\xec\x9d\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec9e[] = { + "\xec\x9e\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ec9f[] = { + "\xec\x9f\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca0[] = { + "\xec\xa0\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca1[] = { + "\xec\xa1\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca2[] = { + "\xec\xa2\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca3[] = { + "\xec\xa3\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca4[] = { + "\xec\xa4\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca5[] = { + "\xec\xa5\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca6[] = { + "\xec\xa6\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca7[] = { + "\xec\xa7\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca8[] = { + "\xec\xa8\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_eca9[] = { + "\xec\xa9\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecaa[] = { + "\xec\xaa\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecab[] = { + "\xec\xab\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecac[] = { + "\xec\xac\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecad[] = { + "\xec\xad\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecae[] = { + "\xec\xae\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecaf[] = { + "\xec\xaf\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb0[] = { + "\xec\xb0\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb1[] = { + "\xec\xb1\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb2[] = { + "\xec\xb2\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb3[] = { + "\xec\xb3\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb4[] = { + "\xec\xb4\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb5[] = { + "\xec\xb5\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb6[] = { + "\xec\xb6\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb7[] = { + "\xec\xb7\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb8[] = { + "\xec\xb8\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecb9[] = { + "\xec\xb9\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecba[] = { + "\xec\xba\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecbb[] = { + "\xec\xbb\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecbc[] = { + "\xec\xbc\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecbd[] = { + "\xec\xbd\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecbe[] = { + "\xec\xbe\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ecbf[] = { + "\xec\xbf\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed80[] = { + "\xed\x80\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed81[] = { + "\xed\x81\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed82[] = { + "\xed\x82\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed83[] = { + "\xed\x83\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed84[] = { + "\xed\x84\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed85[] = { + "\xed\x85\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed86[] = { + "\xed\x86\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed87[] = { + "\xed\x87\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed88[] = { + "\xed\x88\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed89[] = { + "\xed\x89\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed8a[] = { + "\xed\x8a\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed8b[] = { + "\xed\x8b\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed8c[] = { + "\xed\x8c\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed8d[] = { + "\xed\x8d\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed8e[] = { + "\xed\x8e\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed8f[] = { + "\xed\x8f\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed90[] = { + "\xed\x90\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed91[] = { + "\xed\x91\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed92[] = { + "\xed\x92\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed93[] = { + "\xed\x93\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed94[] = { + "\xed\x94\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed95[] = { + "\xed\x95\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed96[] = { + "\xed\x96\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed97[] = { + "\xed\x97\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb0" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed98[] = { + "\xed\x98\x8c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed99[] = { + "\xed\x99\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed9a[] = { + "\xed\x9a\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed9b[] = { + "\xed\x9b\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed9c[] = { + "\xed\x9c\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b3_table_ed9d[] = { + "\xed\x9d\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb8" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b3(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b3_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b3_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b3_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b3_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b3_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b3_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b3_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x94"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab0[] = { + "\xea\xb0\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab1[] = { + "\xea\xb1\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab2[] = { + "\xea\xb2\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab3[] = { + "\xea\xb3\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab4[] = { + "\xea\xb4\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab5[] = { + "\xea\xb5\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab6[] = { + "\xea\xb6\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab7[] = { + "\xea\xb7\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab8[] = { + "\xea\xb8\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eab9[] = { + "\xea\xb9\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eaba[] = { + "\xea\xba\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eabb[] = { + "\xea\xbb\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eabc[] = { + "\xea\xbc\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eabd[] = { + "\xea\xbd\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eabe[] = { + "\xea\xbe\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eabf[] = { + "\xea\xbf\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb80[] = { + "\xeb\x80\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb81[] = { + "\xeb\x81\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb82[] = { + "\xeb\x82\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb83[] = { + "\xeb\x83\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb84[] = { + "\xeb\x84\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb85[] = { + "\xeb\x85\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb86[] = { + "\xeb\x86\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb87[] = { + "\xeb\x87\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb88[] = { + "\xeb\x88\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb89[] = { + "\xeb\x89\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb8a[] = { + "\xeb\x8a\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb8b[] = { + "\xeb\x8b\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb8c[] = { + "\xeb\x8c\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb8d[] = { + "\xeb\x8d\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb8e[] = { + "\xeb\x8e\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb8f[] = { + "\xeb\x8f\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb90[] = { + "\xeb\x90\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb91[] = { + "\xeb\x91\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb92[] = { + "\xeb\x92\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb93[] = { + "\xeb\x93\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb94[] = { + "\xeb\x94\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb95[] = { + "\xeb\x95\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb96[] = { + "\xeb\x96\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb97[] = { + "\xeb\x97\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb98[] = { + "\xeb\x98\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb99[] = { + "\xeb\x99\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb9a[] = { + "\xeb\x9a\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb9b[] = { + "\xeb\x9b\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb9c[] = { + "\xeb\x9c\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb9d[] = { + "\xeb\x9d\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb9e[] = { + "\xeb\x9e\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eb9f[] = { + "\xeb\x9f\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba0[] = { + "\xeb\xa0\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba1[] = { + "\xeb\xa1\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba2[] = { + "\xeb\xa2\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba3[] = { + "\xeb\xa3\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba4[] = { + "\xeb\xa4\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba5[] = { + "\xeb\xa5\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba6[] = { + "\xeb\xa6\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba7[] = { + "\xeb\xa7\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba8[] = { + "\xeb\xa8\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eba9[] = { + "\xeb\xa9\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebaa[] = { + "\xeb\xaa\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebab[] = { + "\xeb\xab\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebac[] = { + "\xeb\xac\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebad[] = { + "\xeb\xad\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebae[] = { + "\xeb\xae\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebaf[] = { + "\xeb\xaf\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb0[] = { + "\xeb\xb0\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb1[] = { + "\xeb\xb1\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb2[] = { + "\xeb\xb2\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb3[] = { + "\xeb\xb3\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb4[] = { + "\xeb\xb4\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb5[] = { + "\xeb\xb5\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb6[] = { + "\xeb\xb6\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb7[] = { + "\xeb\xb7\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb8[] = { + "\xeb\xb8\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebb9[] = { + "\xeb\xb9\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebba[] = { + "\xeb\xba\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebbb[] = { + "\xeb\xbb\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebbc[] = { + "\xeb\xbc\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebbd[] = { + "\xeb\xbd\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebbe[] = { + "\xeb\xbe\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ebbf[] = { + "\xeb\xbf\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec80[] = { + "\xec\x80\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec81[] = { + "\xec\x81\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec82[] = { + "\xec\x82\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec83[] = { + "\xec\x83\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec84[] = { + "\xec\x84\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec85[] = { + "\xec\x85\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec86[] = { + "\xec\x86\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec87[] = { + "\xec\x87\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec88[] = { + "\xec\x88\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec89[] = { + "\xec\x89\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec8a[] = { + "\xec\x8a\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec8b[] = { + "\xec\x8b\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec8c[] = { + "\xec\x8c\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec8d[] = { + "\xec\x8d\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec8e[] = { + "\xec\x8e\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec8f[] = { + "\xec\x8f\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec90[] = { + "\xec\x90\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec91[] = { + "\xec\x91\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec92[] = { + "\xec\x92\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec93[] = { + "\xec\x93\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec94[] = { + "\xec\x94\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec95[] = { + "\xec\x95\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec96[] = { + "\xec\x96\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec97[] = { + "\xec\x97\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec98[] = { + "\xec\x98\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec99[] = { + "\xec\x99\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec9a[] = { + "\xec\x9a\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec9b[] = { + "\xec\x9b\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec9c[] = { + "\xec\x9c\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec9d[] = { + "\xec\x9d\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec9e[] = { + "\xec\x9e\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ec9f[] = { + "\xec\x9f\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca0[] = { + "\xec\xa0\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca1[] = { + "\xec\xa1\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca2[] = { + "\xec\xa2\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca3[] = { + "\xec\xa3\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca4[] = { + "\xec\xa4\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca5[] = { + "\xec\xa5\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca6[] = { + "\xec\xa6\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca7[] = { + "\xec\xa7\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca8[] = { + "\xec\xa8\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_eca9[] = { + "\xec\xa9\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecaa[] = { + "\xec\xaa\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecab[] = { + "\xec\xab\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecac[] = { + "\xec\xac\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecad[] = { + "\xec\xad\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecae[] = { + "\xec\xae\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecaf[] = { + "\xec\xaf\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb0[] = { + "\xec\xb0\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb1[] = { + "\xec\xb1\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb2[] = { + "\xec\xb2\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb3[] = { + "\xec\xb3\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb4[] = { + "\xec\xb4\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb5[] = { + "\xec\xb5\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb6[] = { + "\xec\xb6\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb7[] = { + "\xec\xb7\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb8[] = { + "\xec\xb8\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecb9[] = { + "\xec\xb9\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecba[] = { + "\xec\xba\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecbb[] = { + "\xec\xbb\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecbc[] = { + "\xec\xbc\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecbd[] = { + "\xec\xbd\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecbe[] = { + "\xec\xbe\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ecbf[] = { + "\xec\xbf\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed80[] = { + "\xed\x80\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed81[] = { + "\xed\x81\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed82[] = { + "\xed\x82\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed83[] = { + "\xed\x83\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed84[] = { + "\xed\x84\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed85[] = { + "\xed\x85\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed86[] = { + "\xed\x86\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed87[] = { + "\xed\x87\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed88[] = { + "\xed\x88\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed89[] = { + "\xed\x89\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed8a[] = { + "\xed\x8a\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed8b[] = { + "\xed\x8b\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed8c[] = { + "\xed\x8c\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed8d[] = { + "\xed\x8d\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed8e[] = { + "\xed\x8e\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed8f[] = { + "\xed\x8f\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed90[] = { + "\xed\x90\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed91[] = { + "\xed\x91\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed92[] = { + "\xed\x92\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed93[] = { + "\xed\x93\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed94[] = { + "\xed\x94\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed95[] = { + "\xed\x95\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed96[] = { + "\xed\x96\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed97[] = { + "\xed\x97\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb1" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed98[] = { + "\xed\x98\x8d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xa9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed99[] = { + "\xed\x99\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed9a[] = { + "\xed\x9a\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed9b[] = { + "\xed\x9b\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed9c[] = { + "\xed\x9c\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b4_table_ed9d[] = { + "\xed\x9d\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xb9" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b4(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b4_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b4_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b4_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b4_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b4_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b4_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b4_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x95"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab0[] = { + "\xea\xb0\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab1[] = { + "\xea\xb1\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab2[] = { + "\xea\xb2\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab3[] = { + "\xea\xb3\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab4[] = { + "\xea\xb4\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab5[] = { + "\xea\xb5\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab6[] = { + "\xea\xb6\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab7[] = { + "\xea\xb7\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab8[] = { + "\xea\xb8\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eab9[] = { + "\xea\xb9\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eaba[] = { + "\xea\xba\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eabb[] = { + "\xea\xbb\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eabc[] = { + "\xea\xbc\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eabd[] = { + "\xea\xbd\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eabe[] = { + "\xea\xbe\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eabf[] = { + "\xea\xbf\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb80[] = { + "\xeb\x80\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb81[] = { + "\xeb\x81\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb82[] = { + "\xeb\x82\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb83[] = { + "\xeb\x83\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb84[] = { + "\xeb\x84\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb85[] = { + "\xeb\x85\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb86[] = { + "\xeb\x86\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb87[] = { + "\xeb\x87\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb88[] = { + "\xeb\x88\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb89[] = { + "\xeb\x89\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb8a[] = { + "\xeb\x8a\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb8b[] = { + "\xeb\x8b\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb8c[] = { + "\xeb\x8c\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb8d[] = { + "\xeb\x8d\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb8e[] = { + "\xeb\x8e\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb8f[] = { + "\xeb\x8f\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb90[] = { + "\xeb\x90\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb91[] = { + "\xeb\x91\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb92[] = { + "\xeb\x92\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb93[] = { + "\xeb\x93\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb94[] = { + "\xeb\x94\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb95[] = { + "\xeb\x95\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb96[] = { + "\xeb\x96\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb97[] = { + "\xeb\x97\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb98[] = { + "\xeb\x98\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb99[] = { + "\xeb\x99\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb9a[] = { + "\xeb\x9a\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb9b[] = { + "\xeb\x9b\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb9c[] = { + "\xeb\x9c\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb9d[] = { + "\xeb\x9d\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb9e[] = { + "\xeb\x9e\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eb9f[] = { + "\xeb\x9f\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba0[] = { + "\xeb\xa0\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba1[] = { + "\xeb\xa1\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba2[] = { + "\xeb\xa2\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba3[] = { + "\xeb\xa3\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba4[] = { + "\xeb\xa4\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba5[] = { + "\xeb\xa5\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba6[] = { + "\xeb\xa6\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba7[] = { + "\xeb\xa7\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba8[] = { + "\xeb\xa8\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eba9[] = { + "\xeb\xa9\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebaa[] = { + "\xeb\xaa\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebab[] = { + "\xeb\xab\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebac[] = { + "\xeb\xac\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebad[] = { + "\xeb\xad\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebae[] = { + "\xeb\xae\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebaf[] = { + "\xeb\xaf\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb0[] = { + "\xeb\xb0\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb1[] = { + "\xeb\xb1\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb2[] = { + "\xeb\xb2\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb3[] = { + "\xeb\xb3\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb4[] = { + "\xeb\xb4\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb5[] = { + "\xeb\xb5\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb6[] = { + "\xeb\xb6\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb7[] = { + "\xeb\xb7\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb8[] = { + "\xeb\xb8\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebb9[] = { + "\xeb\xb9\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebba[] = { + "\xeb\xba\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebbb[] = { + "\xeb\xbb\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebbc[] = { + "\xeb\xbc\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebbd[] = { + "\xeb\xbd\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebbe[] = { + "\xeb\xbe\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ebbf[] = { + "\xeb\xbf\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec80[] = { + "\xec\x80\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec81[] = { + "\xec\x81\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec82[] = { + "\xec\x82\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec83[] = { + "\xec\x83\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec84[] = { + "\xec\x84\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec85[] = { + "\xec\x85\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec86[] = { + "\xec\x86\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec87[] = { + "\xec\x87\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec88[] = { + "\xec\x88\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec89[] = { + "\xec\x89\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec8a[] = { + "\xec\x8a\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec8b[] = { + "\xec\x8b\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec8c[] = { + "\xec\x8c\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec8d[] = { + "\xec\x8d\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec8e[] = { + "\xec\x8e\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec8f[] = { + "\xec\x8f\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec90[] = { + "\xec\x90\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec91[] = { + "\xec\x91\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec92[] = { + "\xec\x92\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec93[] = { + "\xec\x93\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec94[] = { + "\xec\x94\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec95[] = { + "\xec\x95\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec96[] = { + "\xec\x96\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec97[] = { + "\xec\x97\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec98[] = { + "\xec\x98\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec99[] = { + "\xec\x99\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec9a[] = { + "\xec\x9a\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec9b[] = { + "\xec\x9b\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec9c[] = { + "\xec\x9c\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec9d[] = { + "\xec\x9d\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec9e[] = { + "\xec\x9e\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ec9f[] = { + "\xec\x9f\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca0[] = { + "\xec\xa0\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca1[] = { + "\xec\xa1\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca2[] = { + "\xec\xa2\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca3[] = { + "\xec\xa3\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca4[] = { + "\xec\xa4\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca5[] = { + "\xec\xa5\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca6[] = { + "\xec\xa6\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca7[] = { + "\xec\xa7\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca8[] = { + "\xec\xa8\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_eca9[] = { + "\xec\xa9\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecaa[] = { + "\xec\xaa\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecab[] = { + "\xec\xab\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecac[] = { + "\xec\xac\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecad[] = { + "\xec\xad\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecae[] = { + "\xec\xae\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecaf[] = { + "\xec\xaf\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb0[] = { + "\xec\xb0\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb1[] = { + "\xec\xb1\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb2[] = { + "\xec\xb2\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb3[] = { + "\xec\xb3\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb4[] = { + "\xec\xb4\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb5[] = { + "\xec\xb5\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb6[] = { + "\xec\xb6\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb7[] = { + "\xec\xb7\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb8[] = { + "\xec\xb8\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecb9[] = { + "\xec\xb9\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecba[] = { + "\xec\xba\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecbb[] = { + "\xec\xbb\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecbc[] = { + "\xec\xbc\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecbd[] = { + "\xec\xbd\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecbe[] = { + "\xec\xbe\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ecbf[] = { + "\xec\xbf\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed80[] = { + "\xed\x80\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed81[] = { + "\xed\x81\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed82[] = { + "\xed\x82\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed83[] = { + "\xed\x83\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed84[] = { + "\xed\x84\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed85[] = { + "\xed\x85\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed86[] = { + "\xed\x86\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed87[] = { + "\xed\x87\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed88[] = { + "\xed\x88\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed89[] = { + "\xed\x89\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed8a[] = { + "\xed\x8a\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed8b[] = { + "\xed\x8b\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed8c[] = { + "\xed\x8c\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed8d[] = { + "\xed\x8d\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed8e[] = { + "\xed\x8e\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed8f[] = { + "\xed\x8f\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed90[] = { + "\xed\x90\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed91[] = { + "\xed\x91\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed92[] = { + "\xed\x92\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed93[] = { + "\xed\x93\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed94[] = { + "\xed\x94\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed95[] = { + "\xed\x95\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed96[] = { + "\xed\x96\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed97[] = { + "\xed\x97\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb2" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed98[] = { + "\xed\x98\x8e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xaa", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed99[] = { + "\xed\x99\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed9a[] = { + "\xed\x9a\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed9b[] = { + "\xed\x9b\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed9c[] = { + "\xed\x9c\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b5_table_ed9d[] = { + "\xed\x9d\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xba" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b5(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b5_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b5_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b5_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b5_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b5_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b5_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b5_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x96"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab0[] = { + "\xea\xb0\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab1[] = { + "\xea\xb1\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb1\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab2[] = { + "\xea\xb2\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab3[] = { + "\xea\xb3\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab4[] = { + "\xea\xb4\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab5[] = { + "\xea\xb5\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab6[] = { + "\xea\xb6\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab7[] = { + "\xea\xb7\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab8[] = { + "\xea\xb8\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb8\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eab9[] = { + "\xea\xb9\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eaba[] = { + "\xea\xba\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eabb[] = { + "\xea\xbb\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eabc[] = { + "\xea\xbc\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eabd[] = { + "\xea\xbd\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eabe[] = { + "\xea\xbe\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eabf[] = { + "\xea\xbf\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbf\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb80[] = { + "\xeb\x80\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb81[] = { + "\xeb\x81\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb82[] = { + "\xeb\x82\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb83[] = { + "\xeb\x83\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb84[] = { + "\xeb\x84\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb85[] = { + "\xeb\x85\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb86[] = { + "\xeb\x86\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x86\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb87[] = { + "\xeb\x87\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb88[] = { + "\xeb\x88\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb89[] = { + "\xeb\x89\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb8a[] = { + "\xeb\x8a\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb8b[] = { + "\xeb\x8b\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb8c[] = { + "\xeb\x8c\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb8d[] = { + "\xeb\x8d\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8d\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb8e[] = { + "\xeb\x8e\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb8f[] = { + "\xeb\x8f\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb90[] = { + "\xeb\x90\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb91[] = { + "\xeb\x91\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb92[] = { + "\xeb\x92\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb93[] = { + "\xeb\x93\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb94[] = { + "\xeb\x94\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x94\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb95[] = { + "\xeb\x95\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb96[] = { + "\xeb\x96\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb97[] = { + "\xeb\x97\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb98[] = { + "\xeb\x98\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb99[] = { + "\xeb\x99\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb9a[] = { + "\xeb\x9a\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb9b[] = { + "\xeb\x9b\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9b\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb9c[] = { + "\xeb\x9c\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb9d[] = { + "\xeb\x9d\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb9e[] = { + "\xeb\x9e\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eb9f[] = { + "\xeb\x9f\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba0[] = { + "\xeb\xa0\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba1[] = { + "\xeb\xa1\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba2[] = { + "\xeb\xa2\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa2\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba3[] = { + "\xeb\xa3\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba4[] = { + "\xeb\xa4\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba5[] = { + "\xeb\xa5\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba6[] = { + "\xeb\xa6\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba7[] = { + "\xeb\xa7\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba8[] = { + "\xeb\xa8\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eba9[] = { + "\xeb\xa9\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa9\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebaa[] = { + "\xeb\xaa\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebab[] = { + "\xeb\xab\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebac[] = { + "\xeb\xac\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebad[] = { + "\xeb\xad\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebae[] = { + "\xeb\xae\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebaf[] = { + "\xeb\xaf\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb0[] = { + "\xeb\xb0\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb0\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb1[] = { + "\xeb\xb1\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb2[] = { + "\xeb\xb2\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb3[] = { + "\xeb\xb3\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb4[] = { + "\xeb\xb4\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb5[] = { + "\xeb\xb5\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb6[] = { + "\xeb\xb6\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb7[] = { + "\xeb\xb7\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb7\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb8[] = { + "\xeb\xb8\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebb9[] = { + "\xeb\xb9\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebba[] = { + "\xeb\xba\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebbb[] = { + "\xeb\xbb\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebbc[] = { + "\xeb\xbc\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebbd[] = { + "\xeb\xbd\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebbe[] = { + "\xeb\xbe\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbe\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ebbf[] = { + "\xeb\xbf\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec80[] = { + "\xec\x80\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec81[] = { + "\xec\x81\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec82[] = { + "\xec\x82\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec83[] = { + "\xec\x83\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec84[] = { + "\xec\x84\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec85[] = { + "\xec\x85\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x85\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec86[] = { + "\xec\x86\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec87[] = { + "\xec\x87\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec88[] = { + "\xec\x88\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec89[] = { + "\xec\x89\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec8a[] = { + "\xec\x8a\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec8b[] = { + "\xec\x8b\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec8c[] = { + "\xec\x8c\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8c\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec8d[] = { + "\xec\x8d\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec8e[] = { + "\xec\x8e\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec8f[] = { + "\xec\x8f\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec90[] = { + "\xec\x90\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec91[] = { + "\xec\x91\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec92[] = { + "\xec\x92\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec93[] = { + "\xec\x93\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x93\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec94[] = { + "\xec\x94\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec95[] = { + "\xec\x95\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec96[] = { + "\xec\x96\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec97[] = { + "\xec\x97\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec98[] = { + "\xec\x98\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec99[] = { + "\xec\x99\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec9a[] = { + "\xec\x9a\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9a\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec9b[] = { + "\xec\x9b\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec9c[] = { + "\xec\x9c\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec9d[] = { + "\xec\x9d\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec9e[] = { + "\xec\x9e\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ec9f[] = { + "\xec\x9f\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca0[] = { + "\xec\xa0\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca1[] = { + "\xec\xa1\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa1\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca2[] = { + "\xec\xa2\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca3[] = { + "\xec\xa3\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca4[] = { + "\xec\xa4\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca5[] = { + "\xec\xa5\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca6[] = { + "\xec\xa6\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca7[] = { + "\xec\xa7\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca8[] = { + "\xec\xa8\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa8\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_eca9[] = { + "\xec\xa9\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecaa[] = { + "\xec\xaa\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecab[] = { + "\xec\xab\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecac[] = { + "\xec\xac\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecad[] = { + "\xec\xad\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecae[] = { + "\xec\xae\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecaf[] = { + "\xec\xaf\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaf\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb0[] = { + "\xec\xb0\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb1[] = { + "\xec\xb1\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb2[] = { + "\xec\xb2\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb3[] = { + "\xec\xb3\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb4[] = { + "\xec\xb4\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb5[] = { + "\xec\xb5\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb6[] = { + "\xec\xb6\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb6\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb7[] = { + "\xec\xb7\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb8[] = { + "\xec\xb8\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecb9[] = { + "\xec\xb9\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecba[] = { + "\xec\xba\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecbb[] = { + "\xec\xbb\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecbc[] = { + "\xec\xbc\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecbd[] = { + "\xec\xbd\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbd\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecbe[] = { + "\xec\xbe\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ecbf[] = { + "\xec\xbf\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed80[] = { + "\xed\x80\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed81[] = { + "\xed\x81\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed82[] = { + "\xed\x82\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed83[] = { + "\xed\x83\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed84[] = { + "\xed\x84\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x84\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed85[] = { + "\xed\x85\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed86[] = { + "\xed\x86\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed87[] = { + "\xed\x87\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed88[] = { + "\xed\x88\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed89[] = { + "\xed\x89\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed8a[] = { + "\xed\x8a\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed8b[] = { + "\xed\x8b\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8b\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed8c[] = { + "\xed\x8c\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed8d[] = { + "\xed\x8d\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed8e[] = { + "\xed\x8e\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed8f[] = { + "\xed\x8f\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed90[] = { + "\xed\x90\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed91[] = { + "\xed\x91\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed92[] = { + "\xed\x92\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x92\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed93[] = { + "\xed\x93\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed94[] = { + "\xed\x94\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed95[] = { + "\xed\x95\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed96[] = { + "\xed\x96\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed97[] = { + "\xed\x97\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb3" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed98[] = { + "\xed\x98\x8f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xab", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed99[] = { + "\xed\x99\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x99\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed9a[] = { + "\xed\x9a\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed9b[] = { + "\xed\x9b\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed9c[] = { + "\xed\x9c\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186b6_table_ed9d[] = { + "\xed\x9d\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xbb" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b6(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b6_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b6_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b6_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b6_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b6_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b6_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b6_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x97"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab0[] = { + "\xea\xb0\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab1[] = { + "\xea\xb1\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab2[] = { + "\xea\xb2\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab3[] = { + "\xea\xb3\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab4[] = { + "\xea\xb4\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab5[] = { + "\xea\xb5\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab6[] = { + "\xea\xb6\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab7[] = { + "\xea\xb7\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab8[] = { + "\xea\xb8\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eab9[] = { + "\xea\xb9\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eaba[] = { + "\xea\xba\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eabb[] = { + "\xea\xbb\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eabc[] = { + "\xea\xbc\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eabd[] = { + "\xea\xbd\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eabe[] = { + "\xea\xbe\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eabf[] = { + "\xea\xbf\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb80[] = { + "\xeb\x80\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb81[] = { + "\xeb\x81\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb82[] = { + "\xeb\x82\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb83[] = { + "\xeb\x83\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb84[] = { + "\xeb\x84\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb85[] = { + "\xeb\x85\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb86[] = { + "\xeb\x86\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb87[] = { + "\xeb\x87\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb88[] = { + "\xeb\x88\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb89[] = { + "\xeb\x89\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb8a[] = { + "\xeb\x8a\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb8b[] = { + "\xeb\x8b\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb8c[] = { + "\xeb\x8c\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb8d[] = { + "\xeb\x8d\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb8e[] = { + "\xeb\x8e\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb8f[] = { + "\xeb\x8f\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb90[] = { + "\xeb\x90\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb91[] = { + "\xeb\x91\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb92[] = { + "\xeb\x92\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb93[] = { + "\xeb\x93\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb94[] = { + "\xeb\x94\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb95[] = { + "\xeb\x95\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb96[] = { + "\xeb\x96\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb97[] = { + "\xeb\x97\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb98[] = { + "\xeb\x98\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb99[] = { + "\xeb\x99\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb9a[] = { + "\xeb\x9a\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb9b[] = { + "\xeb\x9b\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb9c[] = { + "\xeb\x9c\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb9d[] = { + "\xeb\x9d\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb9e[] = { + "\xeb\x9e\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eb9f[] = { + "\xeb\x9f\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba0[] = { + "\xeb\xa0\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba1[] = { + "\xeb\xa1\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba2[] = { + "\xeb\xa2\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba3[] = { + "\xeb\xa3\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba4[] = { + "\xeb\xa4\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba5[] = { + "\xeb\xa5\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba6[] = { + "\xeb\xa6\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba7[] = { + "\xeb\xa7\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba8[] = { + "\xeb\xa8\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eba9[] = { + "\xeb\xa9\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebaa[] = { + "\xeb\xaa\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebab[] = { + "\xeb\xab\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebac[] = { + "\xeb\xac\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebad[] = { + "\xeb\xad\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebae[] = { + "\xeb\xae\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebaf[] = { + "\xeb\xaf\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb0[] = { + "\xeb\xb0\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb1[] = { + "\xeb\xb1\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb2[] = { + "\xeb\xb2\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb3[] = { + "\xeb\xb3\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb4[] = { + "\xeb\xb4\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb5[] = { + "\xeb\xb5\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb6[] = { + "\xeb\xb6\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb7[] = { + "\xeb\xb7\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb8[] = { + "\xeb\xb8\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebb9[] = { + "\xeb\xb9\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebba[] = { + "\xeb\xba\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebbb[] = { + "\xeb\xbb\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebbc[] = { + "\xeb\xbc\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebbd[] = { + "\xeb\xbd\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebbe[] = { + "\xeb\xbe\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ebbf[] = { + "\xeb\xbf\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec80[] = { + "\xec\x80\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec81[] = { + "\xec\x81\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec82[] = { + "\xec\x82\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec83[] = { + "\xec\x83\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec84[] = { + "\xec\x84\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec85[] = { + "\xec\x85\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec86[] = { + "\xec\x86\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec87[] = { + "\xec\x87\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec88[] = { + "\xec\x88\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec89[] = { + "\xec\x89\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec8a[] = { + "\xec\x8a\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec8b[] = { + "\xec\x8b\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec8c[] = { + "\xec\x8c\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec8d[] = { + "\xec\x8d\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec8e[] = { + "\xec\x8e\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec8f[] = { + "\xec\x8f\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec90[] = { + "\xec\x90\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec91[] = { + "\xec\x91\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec92[] = { + "\xec\x92\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec93[] = { + "\xec\x93\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec94[] = { + "\xec\x94\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec95[] = { + "\xec\x95\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec96[] = { + "\xec\x96\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec97[] = { + "\xec\x97\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec98[] = { + "\xec\x98\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec99[] = { + "\xec\x99\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec9a[] = { + "\xec\x9a\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec9b[] = { + "\xec\x9b\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec9c[] = { + "\xec\x9c\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec9d[] = { + "\xec\x9d\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec9e[] = { + "\xec\x9e\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ec9f[] = { + "\xec\x9f\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca0[] = { + "\xec\xa0\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca1[] = { + "\xec\xa1\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca2[] = { + "\xec\xa2\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca3[] = { + "\xec\xa3\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca4[] = { + "\xec\xa4\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca5[] = { + "\xec\xa5\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca6[] = { + "\xec\xa6\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca7[] = { + "\xec\xa7\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca8[] = { + "\xec\xa8\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_eca9[] = { + "\xec\xa9\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecaa[] = { + "\xec\xaa\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecab[] = { + "\xec\xab\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecac[] = { + "\xec\xac\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecad[] = { + "\xec\xad\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecae[] = { + "\xec\xae\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecaf[] = { + "\xec\xaf\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb0[] = { + "\xec\xb0\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb1[] = { + "\xec\xb1\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb2[] = { + "\xec\xb2\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb3[] = { + "\xec\xb3\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb4[] = { + "\xec\xb4\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb5[] = { + "\xec\xb5\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb6[] = { + "\xec\xb6\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb7[] = { + "\xec\xb7\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb8[] = { + "\xec\xb8\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecb9[] = { + "\xec\xb9\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecba[] = { + "\xec\xba\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecbb[] = { + "\xec\xbb\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecbc[] = { + "\xec\xbc\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecbd[] = { + "\xec\xbd\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecbe[] = { + "\xec\xbe\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ecbf[] = { + "\xec\xbf\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed80[] = { + "\xed\x80\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed81[] = { + "\xed\x81\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed82[] = { + "\xed\x82\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed83[] = { + "\xed\x83\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed84[] = { + "\xed\x84\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed85[] = { + "\xed\x85\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed86[] = { + "\xed\x86\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed87[] = { + "\xed\x87\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed88[] = { + "\xed\x88\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed89[] = { + "\xed\x89\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed8a[] = { + "\xed\x8a\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed8b[] = { + "\xed\x8b\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed8c[] = { + "\xed\x8c\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed8d[] = { + "\xed\x8d\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed8e[] = { + "\xed\x8e\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed8f[] = { + "\xed\x8f\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed90[] = { + "\xed\x90\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed91[] = { + "\xed\x91\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed92[] = { + "\xed\x92\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed93[] = { + "\xed\x93\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed94[] = { + "\xed\x94\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed95[] = { + "\xed\x95\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed96[] = { + "\xed\x96\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed97[] = { + "\xed\x97\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb4" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed98[] = { + "\xed\x98\x90", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xac", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed99[] = { + "\xed\x99\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed9a[] = { + "\xed\x9a\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed9b[] = { + "\xed\x9b\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed9c[] = { + "\xed\x9c\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186b7_table_ed9d[] = { + "\xed\x9d\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xbc" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b7(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b7_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b7_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b7_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b7_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b7_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b7_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b7_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x98"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab0[] = { + "\xea\xb0\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab1[] = { + "\xea\xb1\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab2[] = { + "\xea\xb2\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab3[] = { + "\xea\xb3\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab4[] = { + "\xea\xb4\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab5[] = { + "\xea\xb5\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab6[] = { + "\xea\xb6\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab7[] = { + "\xea\xb7\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab8[] = { + "\xea\xb8\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eab9[] = { + "\xea\xb9\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eaba[] = { + "\xea\xba\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eabb[] = { + "\xea\xbb\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eabc[] = { + "\xea\xbc\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eabd[] = { + "\xea\xbd\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eabe[] = { + "\xea\xbe\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eabf[] = { + "\xea\xbf\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb80[] = { + "\xeb\x80\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb81[] = { + "\xeb\x81\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb82[] = { + "\xeb\x82\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb83[] = { + "\xeb\x83\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb84[] = { + "\xeb\x84\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb85[] = { + "\xeb\x85\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb86[] = { + "\xeb\x86\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb87[] = { + "\xeb\x87\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb88[] = { + "\xeb\x88\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb89[] = { + "\xeb\x89\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb8a[] = { + "\xeb\x8a\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb8b[] = { + "\xeb\x8b\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb8c[] = { + "\xeb\x8c\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb8d[] = { + "\xeb\x8d\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb8e[] = { + "\xeb\x8e\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb8f[] = { + "\xeb\x8f\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb90[] = { + "\xeb\x90\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb91[] = { + "\xeb\x91\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb92[] = { + "\xeb\x92\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb93[] = { + "\xeb\x93\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb94[] = { + "\xeb\x94\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb95[] = { + "\xeb\x95\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb96[] = { + "\xeb\x96\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb97[] = { + "\xeb\x97\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb98[] = { + "\xeb\x98\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb99[] = { + "\xeb\x99\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb9a[] = { + "\xeb\x9a\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb9b[] = { + "\xeb\x9b\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb9c[] = { + "\xeb\x9c\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb9d[] = { + "\xeb\x9d\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb9e[] = { + "\xeb\x9e\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eb9f[] = { + "\xeb\x9f\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba0[] = { + "\xeb\xa0\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba1[] = { + "\xeb\xa1\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba2[] = { + "\xeb\xa2\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba3[] = { + "\xeb\xa3\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba4[] = { + "\xeb\xa4\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba5[] = { + "\xeb\xa5\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba6[] = { + "\xeb\xa6\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba7[] = { + "\xeb\xa7\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba8[] = { + "\xeb\xa8\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eba9[] = { + "\xeb\xa9\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebaa[] = { + "\xeb\xaa\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebab[] = { + "\xeb\xab\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebac[] = { + "\xeb\xac\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebad[] = { + "\xeb\xad\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebae[] = { + "\xeb\xae\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebaf[] = { + "\xeb\xaf\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb0[] = { + "\xeb\xb0\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb1[] = { + "\xeb\xb1\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb2[] = { + "\xeb\xb2\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb3[] = { + "\xeb\xb3\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb4[] = { + "\xeb\xb4\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb5[] = { + "\xeb\xb5\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb6[] = { + "\xeb\xb6\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb7[] = { + "\xeb\xb7\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb8[] = { + "\xeb\xb8\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebb9[] = { + "\xeb\xb9\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebba[] = { + "\xeb\xba\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebbb[] = { + "\xeb\xbb\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebbc[] = { + "\xeb\xbc\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebbd[] = { + "\xeb\xbd\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebbe[] = { + "\xeb\xbe\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ebbf[] = { + "\xeb\xbf\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec80[] = { + "\xec\x80\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec81[] = { + "\xec\x81\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec82[] = { + "\xec\x82\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec83[] = { + "\xec\x83\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec84[] = { + "\xec\x84\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec85[] = { + "\xec\x85\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec86[] = { + "\xec\x86\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec87[] = { + "\xec\x87\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec88[] = { + "\xec\x88\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec89[] = { + "\xec\x89\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec8a[] = { + "\xec\x8a\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec8b[] = { + "\xec\x8b\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec8c[] = { + "\xec\x8c\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec8d[] = { + "\xec\x8d\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec8e[] = { + "\xec\x8e\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec8f[] = { + "\xec\x8f\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec90[] = { + "\xec\x90\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec91[] = { + "\xec\x91\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec92[] = { + "\xec\x92\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec93[] = { + "\xec\x93\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec94[] = { + "\xec\x94\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec95[] = { + "\xec\x95\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec96[] = { + "\xec\x96\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec97[] = { + "\xec\x97\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec98[] = { + "\xec\x98\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec99[] = { + "\xec\x99\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec9a[] = { + "\xec\x9a\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec9b[] = { + "\xec\x9b\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec9c[] = { + "\xec\x9c\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec9d[] = { + "\xec\x9d\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec9e[] = { + "\xec\x9e\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ec9f[] = { + "\xec\x9f\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca0[] = { + "\xec\xa0\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca1[] = { + "\xec\xa1\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca2[] = { + "\xec\xa2\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca3[] = { + "\xec\xa3\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca4[] = { + "\xec\xa4\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca5[] = { + "\xec\xa5\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca6[] = { + "\xec\xa6\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca7[] = { + "\xec\xa7\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca8[] = { + "\xec\xa8\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_eca9[] = { + "\xec\xa9\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecaa[] = { + "\xec\xaa\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecab[] = { + "\xec\xab\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecac[] = { + "\xec\xac\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecad[] = { + "\xec\xad\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecae[] = { + "\xec\xae\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecaf[] = { + "\xec\xaf\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb0[] = { + "\xec\xb0\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb1[] = { + "\xec\xb1\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb2[] = { + "\xec\xb2\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb3[] = { + "\xec\xb3\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb4[] = { + "\xec\xb4\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb5[] = { + "\xec\xb5\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb6[] = { + "\xec\xb6\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb7[] = { + "\xec\xb7\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb8[] = { + "\xec\xb8\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecb9[] = { + "\xec\xb9\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecba[] = { + "\xec\xba\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecbb[] = { + "\xec\xbb\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecbc[] = { + "\xec\xbc\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecbd[] = { + "\xec\xbd\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecbe[] = { + "\xec\xbe\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ecbf[] = { + "\xec\xbf\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed80[] = { + "\xed\x80\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed81[] = { + "\xed\x81\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed82[] = { + "\xed\x82\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed83[] = { + "\xed\x83\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed84[] = { + "\xed\x84\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed85[] = { + "\xed\x85\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed86[] = { + "\xed\x86\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed87[] = { + "\xed\x87\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed88[] = { + "\xed\x88\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed89[] = { + "\xed\x89\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed8a[] = { + "\xed\x8a\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed8b[] = { + "\xed\x8b\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed8c[] = { + "\xed\x8c\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed8d[] = { + "\xed\x8d\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed8e[] = { + "\xed\x8e\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed8f[] = { + "\xed\x8f\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed90[] = { + "\xed\x90\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed91[] = { + "\xed\x91\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed92[] = { + "\xed\x92\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed93[] = { + "\xed\x93\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed94[] = { + "\xed\x94\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed95[] = { + "\xed\x95\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed96[] = { + "\xed\x96\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed97[] = { + "\xed\x97\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb5" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed98[] = { + "\xed\x98\x91", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xad", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed99[] = { + "\xed\x99\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed9a[] = { + "\xed\x9a\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed9b[] = { + "\xed\x9b\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed9c[] = { + "\xed\x9c\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186b8_table_ed9d[] = { + "\xed\x9d\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xbd" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b8(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b8_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b8_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b8_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b8_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b8_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b8_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b8_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x99"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab0[] = { + "\xea\xb0\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab1[] = { + "\xea\xb1\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab2[] = { + "\xea\xb2\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab3[] = { + "\xea\xb3\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab4[] = { + "\xea\xb4\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab5[] = { + "\xea\xb5\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab6[] = { + "\xea\xb6\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab7[] = { + "\xea\xb7\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab8[] = { + "\xea\xb8\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eab9[] = { + "\xea\xb9\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eaba[] = { + "\xea\xba\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eabb[] = { + "\xea\xbb\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eabc[] = { + "\xea\xbc\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eabd[] = { + "\xea\xbd\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eabe[] = { + "\xea\xbe\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eabf[] = { + "\xea\xbf\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb80[] = { + "\xeb\x80\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb81[] = { + "\xeb\x81\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb82[] = { + "\xeb\x82\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb83[] = { + "\xeb\x83\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb84[] = { + "\xeb\x84\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb85[] = { + "\xeb\x85\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb86[] = { + "\xeb\x86\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb87[] = { + "\xeb\x87\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb88[] = { + "\xeb\x88\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb89[] = { + "\xeb\x89\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb8a[] = { + "\xeb\x8a\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb8b[] = { + "\xeb\x8b\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb8c[] = { + "\xeb\x8c\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb8d[] = { + "\xeb\x8d\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb8e[] = { + "\xeb\x8e\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb8f[] = { + "\xeb\x8f\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb90[] = { + "\xeb\x90\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb91[] = { + "\xeb\x91\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb92[] = { + "\xeb\x92\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb93[] = { + "\xeb\x93\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb94[] = { + "\xeb\x94\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb95[] = { + "\xeb\x95\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb96[] = { + "\xeb\x96\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb97[] = { + "\xeb\x97\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb98[] = { + "\xeb\x98\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb99[] = { + "\xeb\x99\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb9a[] = { + "\xeb\x9a\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb9b[] = { + "\xeb\x9b\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb9c[] = { + "\xeb\x9c\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb9d[] = { + "\xeb\x9d\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb9e[] = { + "\xeb\x9e\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eb9f[] = { + "\xeb\x9f\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba0[] = { + "\xeb\xa0\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba1[] = { + "\xeb\xa1\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba2[] = { + "\xeb\xa2\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba3[] = { + "\xeb\xa3\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba4[] = { + "\xeb\xa4\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba5[] = { + "\xeb\xa5\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba6[] = { + "\xeb\xa6\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba7[] = { + "\xeb\xa7\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba8[] = { + "\xeb\xa8\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eba9[] = { + "\xeb\xa9\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebaa[] = { + "\xeb\xaa\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebab[] = { + "\xeb\xab\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebac[] = { + "\xeb\xac\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebad[] = { + "\xeb\xad\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebae[] = { + "\xeb\xae\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebaf[] = { + "\xeb\xaf\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb0[] = { + "\xeb\xb0\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb1[] = { + "\xeb\xb1\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb2[] = { + "\xeb\xb2\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb3[] = { + "\xeb\xb3\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb4[] = { + "\xeb\xb4\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb5[] = { + "\xeb\xb5\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb6[] = { + "\xeb\xb6\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb7[] = { + "\xeb\xb7\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb8[] = { + "\xeb\xb8\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebb9[] = { + "\xeb\xb9\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebba[] = { + "\xeb\xba\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebbb[] = { + "\xeb\xbb\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebbc[] = { + "\xeb\xbc\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebbd[] = { + "\xeb\xbd\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebbe[] = { + "\xeb\xbe\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ebbf[] = { + "\xeb\xbf\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec80[] = { + "\xec\x80\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec81[] = { + "\xec\x81\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec82[] = { + "\xec\x82\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec83[] = { + "\xec\x83\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec84[] = { + "\xec\x84\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec85[] = { + "\xec\x85\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec86[] = { + "\xec\x86\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec87[] = { + "\xec\x87\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec88[] = { + "\xec\x88\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec89[] = { + "\xec\x89\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec8a[] = { + "\xec\x8a\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec8b[] = { + "\xec\x8b\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec8c[] = { + "\xec\x8c\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec8d[] = { + "\xec\x8d\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec8e[] = { + "\xec\x8e\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec8f[] = { + "\xec\x8f\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec90[] = { + "\xec\x90\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec91[] = { + "\xec\x91\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec92[] = { + "\xec\x92\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec93[] = { + "\xec\x93\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec94[] = { + "\xec\x94\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec95[] = { + "\xec\x95\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec96[] = { + "\xec\x96\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec97[] = { + "\xec\x97\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec98[] = { + "\xec\x98\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec99[] = { + "\xec\x99\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec9a[] = { + "\xec\x9a\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec9b[] = { + "\xec\x9b\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec9c[] = { + "\xec\x9c\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec9d[] = { + "\xec\x9d\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec9e[] = { + "\xec\x9e\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ec9f[] = { + "\xec\x9f\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca0[] = { + "\xec\xa0\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca1[] = { + "\xec\xa1\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca2[] = { + "\xec\xa2\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca3[] = { + "\xec\xa3\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca4[] = { + "\xec\xa4\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca5[] = { + "\xec\xa5\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca6[] = { + "\xec\xa6\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca7[] = { + "\xec\xa7\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca8[] = { + "\xec\xa8\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_eca9[] = { + "\xec\xa9\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecaa[] = { + "\xec\xaa\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecab[] = { + "\xec\xab\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecac[] = { + "\xec\xac\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecad[] = { + "\xec\xad\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecae[] = { + "\xec\xae\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecaf[] = { + "\xec\xaf\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb0[] = { + "\xec\xb0\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb1[] = { + "\xec\xb1\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb2[] = { + "\xec\xb2\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb3[] = { + "\xec\xb3\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb4[] = { + "\xec\xb4\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb5[] = { + "\xec\xb5\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb6[] = { + "\xec\xb6\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb7[] = { + "\xec\xb7\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb8[] = { + "\xec\xb8\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecb9[] = { + "\xec\xb9\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecba[] = { + "\xec\xba\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecbb[] = { + "\xec\xbb\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecbc[] = { + "\xec\xbc\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecbd[] = { + "\xec\xbd\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecbe[] = { + "\xec\xbe\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ecbf[] = { + "\xec\xbf\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed80[] = { + "\xed\x80\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed81[] = { + "\xed\x81\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed82[] = { + "\xed\x82\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed83[] = { + "\xed\x83\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed84[] = { + "\xed\x84\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed85[] = { + "\xed\x85\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed86[] = { + "\xed\x86\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed87[] = { + "\xed\x87\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed88[] = { + "\xed\x88\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed89[] = { + "\xed\x89\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed8a[] = { + "\xed\x8a\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed8b[] = { + "\xed\x8b\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed8c[] = { + "\xed\x8c\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed8d[] = { + "\xed\x8d\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed8e[] = { + "\xed\x8e\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed8f[] = { + "\xed\x8f\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed90[] = { + "\xed\x90\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed91[] = { + "\xed\x91\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed92[] = { + "\xed\x92\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed93[] = { + "\xed\x93\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed94[] = { + "\xed\x94\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed95[] = { + "\xed\x95\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed96[] = { + "\xed\x96\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed97[] = { + "\xed\x97\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb6" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed98[] = { + "\xed\x98\x92", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xae", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed99[] = { + "\xed\x99\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed9a[] = { + "\xed\x9a\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed9b[] = { + "\xed\x9b\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed9c[] = { + "\xed\x9c\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186b9_table_ed9d[] = { + "\xed\x9d\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xbe" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186b9(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186b9_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186b9_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186b9_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186b9_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186b9_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186b9_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186b9_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x9a"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab0[] = { + "\xea\xb0\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab1[] = { + "\xea\xb1\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab2[] = { + "\xea\xb2\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab3[] = { + "\xea\xb3\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab4[] = { + "\xea\xb4\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab5[] = { + "\xea\xb5\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab6[] = { + "\xea\xb6\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab7[] = { + "\xea\xb7\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab8[] = { + "\xea\xb8\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eab9[] = { + "\xea\xb9\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eaba[] = { + "\xea\xba\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eabb[] = { + "\xea\xbb\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eabc[] = { + "\xea\xbc\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eabd[] = { + "\xea\xbd\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eabe[] = { + "\xea\xbe\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eabf[] = { + "\xea\xbf\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb80[] = { + "\xeb\x80\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb81[] = { + "\xeb\x81\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb82[] = { + "\xeb\x82\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb83[] = { + "\xeb\x83\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb84[] = { + "\xeb\x84\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb85[] = { + "\xeb\x85\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb86[] = { + "\xeb\x86\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb87[] = { + "\xeb\x87\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb88[] = { + "\xeb\x88\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb89[] = { + "\xeb\x89\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb8a[] = { + "\xeb\x8a\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb8b[] = { + "\xeb\x8b\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb8c[] = { + "\xeb\x8c\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb8d[] = { + "\xeb\x8d\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb8e[] = { + "\xeb\x8e\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb8f[] = { + "\xeb\x8f\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb90[] = { + "\xeb\x90\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb91[] = { + "\xeb\x91\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb92[] = { + "\xeb\x92\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb93[] = { + "\xeb\x93\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb94[] = { + "\xeb\x94\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb95[] = { + "\xeb\x95\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb96[] = { + "\xeb\x96\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb97[] = { + "\xeb\x97\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb98[] = { + "\xeb\x98\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb99[] = { + "\xeb\x99\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb9a[] = { + "\xeb\x9a\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb9b[] = { + "\xeb\x9b\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb9c[] = { + "\xeb\x9c\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb9d[] = { + "\xeb\x9d\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb9e[] = { + "\xeb\x9e\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eb9f[] = { + "\xeb\x9f\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba0[] = { + "\xeb\xa0\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba1[] = { + "\xeb\xa1\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba2[] = { + "\xeb\xa2\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba3[] = { + "\xeb\xa3\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba4[] = { + "\xeb\xa4\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba5[] = { + "\xeb\xa5\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba6[] = { + "\xeb\xa6\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba7[] = { + "\xeb\xa7\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba8[] = { + "\xeb\xa8\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eba9[] = { + "\xeb\xa9\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebaa[] = { + "\xeb\xaa\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebab[] = { + "\xeb\xab\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebac[] = { + "\xeb\xac\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebad[] = { + "\xeb\xad\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebae[] = { + "\xeb\xae\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebaf[] = { + "\xeb\xaf\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb0[] = { + "\xeb\xb0\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb1[] = { + "\xeb\xb1\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb2[] = { + "\xeb\xb2\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb3[] = { + "\xeb\xb3\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb4[] = { + "\xeb\xb4\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb5[] = { + "\xeb\xb5\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb6[] = { + "\xeb\xb6\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb7[] = { + "\xeb\xb7\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb8[] = { + "\xeb\xb8\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebb9[] = { + "\xeb\xb9\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebba[] = { + "\xeb\xba\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebbb[] = { + "\xeb\xbb\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebbc[] = { + "\xeb\xbc\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebbd[] = { + "\xeb\xbd\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebbe[] = { + "\xeb\xbe\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ebbf[] = { + "\xeb\xbf\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec80[] = { + "\xec\x80\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec81[] = { + "\xec\x81\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec82[] = { + "\xec\x82\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec83[] = { + "\xec\x83\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec84[] = { + "\xec\x84\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec85[] = { + "\xec\x85\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec86[] = { + "\xec\x86\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec87[] = { + "\xec\x87\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec88[] = { + "\xec\x88\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec89[] = { + "\xec\x89\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec8a[] = { + "\xec\x8a\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec8b[] = { + "\xec\x8b\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec8c[] = { + "\xec\x8c\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec8d[] = { + "\xec\x8d\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec8e[] = { + "\xec\x8e\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec8f[] = { + "\xec\x8f\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec90[] = { + "\xec\x90\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec91[] = { + "\xec\x91\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec92[] = { + "\xec\x92\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec93[] = { + "\xec\x93\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec94[] = { + "\xec\x94\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec95[] = { + "\xec\x95\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec96[] = { + "\xec\x96\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec97[] = { + "\xec\x97\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec98[] = { + "\xec\x98\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec99[] = { + "\xec\x99\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec9a[] = { + "\xec\x9a\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec9b[] = { + "\xec\x9b\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec9c[] = { + "\xec\x9c\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec9d[] = { + "\xec\x9d\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec9e[] = { + "\xec\x9e\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ec9f[] = { + "\xec\x9f\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca0[] = { + "\xec\xa0\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca1[] = { + "\xec\xa1\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca2[] = { + "\xec\xa2\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca3[] = { + "\xec\xa3\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca4[] = { + "\xec\xa4\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca5[] = { + "\xec\xa5\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca6[] = { + "\xec\xa6\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca7[] = { + "\xec\xa7\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca8[] = { + "\xec\xa8\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_eca9[] = { + "\xec\xa9\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecaa[] = { + "\xec\xaa\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecab[] = { + "\xec\xab\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecac[] = { + "\xec\xac\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecad[] = { + "\xec\xad\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecae[] = { + "\xec\xae\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecaf[] = { + "\xec\xaf\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb0[] = { + "\xec\xb0\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb1[] = { + "\xec\xb1\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb2[] = { + "\xec\xb2\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb3[] = { + "\xec\xb3\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb4[] = { + "\xec\xb4\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb5[] = { + "\xec\xb5\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb6[] = { + "\xec\xb6\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb7[] = { + "\xec\xb7\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb8[] = { + "\xec\xb8\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecb9[] = { + "\xec\xb9\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecba[] = { + "\xec\xba\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecbb[] = { + "\xec\xbb\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecbc[] = { + "\xec\xbc\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecbd[] = { + "\xec\xbd\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecbe[] = { + "\xec\xbe\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ecbf[] = { + "\xec\xbf\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed80[] = { + "\xed\x80\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed81[] = { + "\xed\x81\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed82[] = { + "\xed\x82\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed83[] = { + "\xed\x83\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed84[] = { + "\xed\x84\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed85[] = { + "\xed\x85\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed86[] = { + "\xed\x86\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed87[] = { + "\xed\x87\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed88[] = { + "\xed\x88\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed89[] = { + "\xed\x89\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed8a[] = { + "\xed\x8a\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed8b[] = { + "\xed\x8b\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed8c[] = { + "\xed\x8c\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed8d[] = { + "\xed\x8d\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed8e[] = { + "\xed\x8e\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed8f[] = { + "\xed\x8f\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed90[] = { + "\xed\x90\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed91[] = { + "\xed\x91\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed92[] = { + "\xed\x92\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed93[] = { + "\xed\x93\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed94[] = { + "\xed\x94\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed95[] = { + "\xed\x95\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed96[] = { + "\xed\x96\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed97[] = { + "\xed\x97\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb7" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed98[] = { + "\xed\x98\x93", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xaf", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed99[] = { + "\xed\x99\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed9a[] = { + "\xed\x9a\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed9b[] = { + "\xed\x9b\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed9c[] = { + "\xed\x9c\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186ba_table_ed9d[] = { + "\xed\x9d\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\xbf" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186ba(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186ba_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186ba_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186ba_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186ba_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186ba_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186ba_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186ba_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x9b"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab0[] = { + "\xea\xb0\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab1[] = { + "\xea\xb1\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab2[] = { + "\xea\xb2\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab3[] = { + "\xea\xb3\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab4[] = { + "\xea\xb4\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab5[] = { + "\xea\xb5\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab6[] = { + "\xea\xb6\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab7[] = { + "\xea\xb7\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab8[] = { + "\xea\xb8\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eab9[] = { + "\xea\xb9\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eaba[] = { + "\xea\xba\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eabb[] = { + "\xea\xbb\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eabc[] = { + "\xea\xbc\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eabd[] = { + "\xea\xbd\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eabe[] = { + "\xea\xbe\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eabf[] = { + "\xea\xbf\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb80[] = { + "\xeb\x80\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb81[] = { + "\xeb\x81\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb82[] = { + "\xeb\x82\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb83[] = { + "\xeb\x83\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb84[] = { + "\xeb\x84\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb85[] = { + "\xeb\x85\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb86[] = { + "\xeb\x86\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb87[] = { + "\xeb\x87\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb88[] = { + "\xeb\x88\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb89[] = { + "\xeb\x89\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb8a[] = { + "\xeb\x8a\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb8b[] = { + "\xeb\x8b\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb8c[] = { + "\xeb\x8c\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb8d[] = { + "\xeb\x8d\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb8e[] = { + "\xeb\x8e\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb8f[] = { + "\xeb\x8f\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb90[] = { + "\xeb\x90\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb91[] = { + "\xeb\x91\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb92[] = { + "\xeb\x92\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb93[] = { + "\xeb\x93\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb94[] = { + "\xeb\x94\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb95[] = { + "\xeb\x95\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb96[] = { + "\xeb\x96\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb97[] = { + "\xeb\x97\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb98[] = { + "\xeb\x98\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb99[] = { + "\xeb\x99\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb9a[] = { + "\xeb\x9a\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb9b[] = { + "\xeb\x9b\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb9c[] = { + "\xeb\x9c\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb9d[] = { + "\xeb\x9d\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb9e[] = { + "\xeb\x9e\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eb9f[] = { + "\xeb\x9f\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba0[] = { + "\xeb\xa0\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba1[] = { + "\xeb\xa1\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba2[] = { + "\xeb\xa2\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba3[] = { + "\xeb\xa3\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba4[] = { + "\xeb\xa4\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba5[] = { + "\xeb\xa5\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba6[] = { + "\xeb\xa6\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba7[] = { + "\xeb\xa7\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba8[] = { + "\xeb\xa8\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eba9[] = { + "\xeb\xa9\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebaa[] = { + "\xeb\xaa\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebab[] = { + "\xeb\xab\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebac[] = { + "\xeb\xac\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebad[] = { + "\xeb\xad\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebae[] = { + "\xeb\xae\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebaf[] = { + "\xeb\xaf\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb0[] = { + "\xeb\xb0\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb1[] = { + "\xeb\xb1\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb2[] = { + "\xeb\xb2\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb3[] = { + "\xeb\xb3\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb4[] = { + "\xeb\xb4\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb5[] = { + "\xeb\xb5\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb6[] = { + "\xeb\xb6\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb7[] = { + "\xeb\xb7\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb8[] = { + "\xeb\xb8\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebb9[] = { + "\xeb\xb9\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebba[] = { + "\xeb\xba\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebbb[] = { + "\xeb\xbb\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebbc[] = { + "\xeb\xbc\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebbd[] = { + "\xeb\xbd\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebbe[] = { + "\xeb\xbe\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ebbf[] = { + "\xeb\xbf\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec80[] = { + "\xec\x80\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec81[] = { + "\xec\x81\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec82[] = { + "\xec\x82\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec83[] = { + "\xec\x83\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec84[] = { + "\xec\x84\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec85[] = { + "\xec\x85\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec86[] = { + "\xec\x86\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec87[] = { + "\xec\x87\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec88[] = { + "\xec\x88\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec89[] = { + "\xec\x89\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec8a[] = { + "\xec\x8a\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec8b[] = { + "\xec\x8b\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec8c[] = { + "\xec\x8c\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec8d[] = { + "\xec\x8d\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec8e[] = { + "\xec\x8e\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec8f[] = { + "\xec\x8f\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec90[] = { + "\xec\x90\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec91[] = { + "\xec\x91\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec92[] = { + "\xec\x92\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec93[] = { + "\xec\x93\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec94[] = { + "\xec\x94\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec95[] = { + "\xec\x95\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec96[] = { + "\xec\x96\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec97[] = { + "\xec\x97\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec98[] = { + "\xec\x98\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec99[] = { + "\xec\x99\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec9a[] = { + "\xec\x9a\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec9b[] = { + "\xec\x9b\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec9c[] = { + "\xec\x9c\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec9d[] = { + "\xec\x9d\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec9e[] = { + "\xec\x9e\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ec9f[] = { + "\xec\x9f\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca0[] = { + "\xec\xa0\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca1[] = { + "\xec\xa1\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca2[] = { + "\xec\xa2\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca3[] = { + "\xec\xa3\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca4[] = { + "\xec\xa4\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca5[] = { + "\xec\xa5\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca6[] = { + "\xec\xa6\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca7[] = { + "\xec\xa7\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca8[] = { + "\xec\xa8\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_eca9[] = { + "\xec\xa9\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecaa[] = { + "\xec\xaa\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecab[] = { + "\xec\xab\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecac[] = { + "\xec\xac\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecad[] = { + "\xec\xad\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecae[] = { + "\xec\xae\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecaf[] = { + "\xec\xaf\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb0[] = { + "\xec\xb0\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb1[] = { + "\xec\xb1\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb2[] = { + "\xec\xb2\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb3[] = { + "\xec\xb3\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb4[] = { + "\xec\xb4\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb5[] = { + "\xec\xb5\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb6[] = { + "\xec\xb6\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb7[] = { + "\xec\xb7\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb8[] = { + "\xec\xb8\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecb9[] = { + "\xec\xb9\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecba[] = { + "\xec\xba\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecbb[] = { + "\xec\xbb\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecbc[] = { + "\xec\xbc\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecbd[] = { + "\xec\xbd\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecbe[] = { + "\xec\xbe\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ecbf[] = { + "\xec\xbf\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed80[] = { + "\xed\x80\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed81[] = { + "\xed\x81\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed82[] = { + "\xed\x82\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed83[] = { + "\xed\x83\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed84[] = { + "\xed\x84\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed85[] = { + "\xed\x85\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed86[] = { + "\xed\x86\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed87[] = { + "\xed\x87\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed88[] = { + "\xed\x88\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed89[] = { + "\xed\x89\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed8a[] = { + "\xed\x8a\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed8b[] = { + "\xed\x8b\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed8c[] = { + "\xed\x8c\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed8d[] = { + "\xed\x8d\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed8e[] = { + "\xed\x8e\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed8f[] = { + "\xed\x8f\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed90[] = { + "\xed\x90\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed91[] = { + "\xed\x91\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed92[] = { + "\xed\x92\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed93[] = { + "\xed\x93\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed94[] = { + "\xed\x94\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed95[] = { + "\xed\x95\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed96[] = { + "\xed\x96\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed97[] = { + "\xed\x97\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb8" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed98[] = { + "\xed\x98\x94", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xb0", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed99[] = { + "\xed\x99\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed9a[] = { + "\xed\x9a\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed9b[] = { + "\xed\x9b\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed9c[] = { + "\xed\x9c\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bb_table_ed9d[] = { + "\xed\x9d\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9e\x80" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186bb(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bb_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bb_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bb_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bb_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bb_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bb_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bb_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x9c"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab0[] = { + "\xea\xb0\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab1[] = { + "\xea\xb1\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab2[] = { + "\xea\xb2\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab3[] = { + "\xea\xb3\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab4[] = { + "\xea\xb4\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab5[] = { + "\xea\xb5\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab6[] = { + "\xea\xb6\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab7[] = { + "\xea\xb7\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab8[] = { + "\xea\xb8\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eab9[] = { + "\xea\xb9\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eaba[] = { + "\xea\xba\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eabb[] = { + "\xea\xbb\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eabc[] = { + "\xea\xbc\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eabd[] = { + "\xea\xbd\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eabe[] = { + "\xea\xbe\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eabf[] = { + "\xea\xbf\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb80[] = { + "\xeb\x80\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb81[] = { + "\xeb\x81\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb82[] = { + "\xeb\x82\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb83[] = { + "\xeb\x83\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb84[] = { + "\xeb\x84\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb85[] = { + "\xeb\x85\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb86[] = { + "\xeb\x86\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb87[] = { + "\xeb\x87\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb88[] = { + "\xeb\x88\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb89[] = { + "\xeb\x89\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb8a[] = { + "\xeb\x8a\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb8b[] = { + "\xeb\x8b\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb8c[] = { + "\xeb\x8c\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb8d[] = { + "\xeb\x8d\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb8e[] = { + "\xeb\x8e\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb8f[] = { + "\xeb\x8f\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb90[] = { + "\xeb\x90\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb91[] = { + "\xeb\x91\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb92[] = { + "\xeb\x92\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb93[] = { + "\xeb\x93\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb94[] = { + "\xeb\x94\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb95[] = { + "\xeb\x95\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb96[] = { + "\xeb\x96\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb97[] = { + "\xeb\x97\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb98[] = { + "\xeb\x98\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb99[] = { + "\xeb\x99\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb9a[] = { + "\xeb\x9a\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb9b[] = { + "\xeb\x9b\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb9c[] = { + "\xeb\x9c\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb9d[] = { + "\xeb\x9d\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb9e[] = { + "\xeb\x9e\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eb9f[] = { + "\xeb\x9f\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba0[] = { + "\xeb\xa0\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba1[] = { + "\xeb\xa1\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba2[] = { + "\xeb\xa2\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba3[] = { + "\xeb\xa3\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba4[] = { + "\xeb\xa4\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba5[] = { + "\xeb\xa5\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba6[] = { + "\xeb\xa6\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba7[] = { + "\xeb\xa7\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba8[] = { + "\xeb\xa8\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eba9[] = { + "\xeb\xa9\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebaa[] = { + "\xeb\xaa\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebab[] = { + "\xeb\xab\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebac[] = { + "\xeb\xac\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebad[] = { + "\xeb\xad\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebae[] = { + "\xeb\xae\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebaf[] = { + "\xeb\xaf\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb0[] = { + "\xeb\xb0\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb1[] = { + "\xeb\xb1\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb2[] = { + "\xeb\xb2\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb3[] = { + "\xeb\xb3\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb4[] = { + "\xeb\xb4\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb5[] = { + "\xeb\xb5\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb6[] = { + "\xeb\xb6\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb7[] = { + "\xeb\xb7\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb8[] = { + "\xeb\xb8\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebb9[] = { + "\xeb\xb9\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebba[] = { + "\xeb\xba\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebbb[] = { + "\xeb\xbb\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebbc[] = { + "\xeb\xbc\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebbd[] = { + "\xeb\xbd\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebbe[] = { + "\xeb\xbe\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ebbf[] = { + "\xeb\xbf\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec80[] = { + "\xec\x80\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec81[] = { + "\xec\x81\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec82[] = { + "\xec\x82\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec83[] = { + "\xec\x83\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec84[] = { + "\xec\x84\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec85[] = { + "\xec\x85\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec86[] = { + "\xec\x86\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec87[] = { + "\xec\x87\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec88[] = { + "\xec\x88\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec89[] = { + "\xec\x89\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec8a[] = { + "\xec\x8a\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec8b[] = { + "\xec\x8b\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec8c[] = { + "\xec\x8c\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec8d[] = { + "\xec\x8d\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec8e[] = { + "\xec\x8e\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec8f[] = { + "\xec\x8f\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec90[] = { + "\xec\x90\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec91[] = { + "\xec\x91\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec92[] = { + "\xec\x92\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec93[] = { + "\xec\x93\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec94[] = { + "\xec\x94\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec95[] = { + "\xec\x95\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec96[] = { + "\xec\x96\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec97[] = { + "\xec\x97\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec98[] = { + "\xec\x98\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec99[] = { + "\xec\x99\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec9a[] = { + "\xec\x9a\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec9b[] = { + "\xec\x9b\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec9c[] = { + "\xec\x9c\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec9d[] = { + "\xec\x9d\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec9e[] = { + "\xec\x9e\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ec9f[] = { + "\xec\x9f\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca0[] = { + "\xec\xa0\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca1[] = { + "\xec\xa1\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca2[] = { + "\xec\xa2\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca3[] = { + "\xec\xa3\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca4[] = { + "\xec\xa4\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca5[] = { + "\xec\xa5\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca6[] = { + "\xec\xa6\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca7[] = { + "\xec\xa7\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca8[] = { + "\xec\xa8\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_eca9[] = { + "\xec\xa9\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecaa[] = { + "\xec\xaa\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecab[] = { + "\xec\xab\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecac[] = { + "\xec\xac\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecad[] = { + "\xec\xad\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecae[] = { + "\xec\xae\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecaf[] = { + "\xec\xaf\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb0[] = { + "\xec\xb0\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb1[] = { + "\xec\xb1\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb2[] = { + "\xec\xb2\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb3[] = { + "\xec\xb3\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb4[] = { + "\xec\xb4\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb5[] = { + "\xec\xb5\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb6[] = { + "\xec\xb6\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb7[] = { + "\xec\xb7\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb8[] = { + "\xec\xb8\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecb9[] = { + "\xec\xb9\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecba[] = { + "\xec\xba\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecbb[] = { + "\xec\xbb\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecbc[] = { + "\xec\xbc\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecbd[] = { + "\xec\xbd\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecbe[] = { + "\xec\xbe\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ecbf[] = { + "\xec\xbf\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed80[] = { + "\xed\x80\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed81[] = { + "\xed\x81\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed82[] = { + "\xed\x82\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed83[] = { + "\xed\x83\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed84[] = { + "\xed\x84\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed85[] = { + "\xed\x85\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed86[] = { + "\xed\x86\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed87[] = { + "\xed\x87\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed88[] = { + "\xed\x88\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed89[] = { + "\xed\x89\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed8a[] = { + "\xed\x8a\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed8b[] = { + "\xed\x8b\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed8c[] = { + "\xed\x8c\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed8d[] = { + "\xed\x8d\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed8e[] = { + "\xed\x8e\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed8f[] = { + "\xed\x8f\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed90[] = { + "\xed\x90\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed91[] = { + "\xed\x91\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed92[] = { + "\xed\x92\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed93[] = { + "\xed\x93\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed94[] = { + "\xed\x94\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed95[] = { + "\xed\x95\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed96[] = { + "\xed\x96\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed97[] = { + "\xed\x97\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xb9" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed98[] = { + "\xed\x98\x95", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xb1", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed99[] = { + "\xed\x99\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed9a[] = { + "\xed\x9a\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed9b[] = { + "\xed\x9b\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed9c[] = { + "\xed\x9c\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e186bc_table_ed9d[] = { + "\xed\x9d\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9e\x81" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186bc(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bc_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bc_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bc_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bc_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bc_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bc_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bc_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x9d"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab0[] = { + "\xea\xb0\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab1[] = { + "\xea\xb1\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab2[] = { + "\xea\xb2\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab3[] = { + "\xea\xb3\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab4[] = { + "\xea\xb4\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab5[] = { + "\xea\xb5\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab6[] = { + "\xea\xb6\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab7[] = { + "\xea\xb7\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab8[] = { + "\xea\xb8\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eab9[] = { + "\xea\xb9\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eaba[] = { + "\xea\xba\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eabb[] = { + "\xea\xbb\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eabc[] = { + "\xea\xbc\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eabd[] = { + "\xea\xbd\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eabe[] = { + "\xea\xbe\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eabf[] = { + "\xea\xbf\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb80[] = { + "\xeb\x80\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb81[] = { + "\xeb\x81\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb82[] = { + "\xeb\x82\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb83[] = { + "\xeb\x83\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb84[] = { + "\xeb\x84\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb85[] = { + "\xeb\x85\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb86[] = { + "\xeb\x86\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb87[] = { + "\xeb\x87\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb88[] = { + "\xeb\x88\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb89[] = { + "\xeb\x89\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb8a[] = { + "\xeb\x8a\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb8b[] = { + "\xeb\x8b\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb8c[] = { + "\xeb\x8c\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb8d[] = { + "\xeb\x8d\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb8e[] = { + "\xeb\x8e\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb8f[] = { + "\xeb\x8f\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb90[] = { + "\xeb\x90\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb91[] = { + "\xeb\x91\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb92[] = { + "\xeb\x92\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb93[] = { + "\xeb\x93\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb94[] = { + "\xeb\x94\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb95[] = { + "\xeb\x95\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb96[] = { + "\xeb\x96\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb97[] = { + "\xeb\x97\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb98[] = { + "\xeb\x98\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb99[] = { + "\xeb\x99\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb9a[] = { + "\xeb\x9a\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb9b[] = { + "\xeb\x9b\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb9c[] = { + "\xeb\x9c\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb9d[] = { + "\xeb\x9d\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb9e[] = { + "\xeb\x9e\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eb9f[] = { + "\xeb\x9f\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba0[] = { + "\xeb\xa0\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba1[] = { + "\xeb\xa1\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba2[] = { + "\xeb\xa2\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba3[] = { + "\xeb\xa3\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba4[] = { + "\xeb\xa4\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba5[] = { + "\xeb\xa5\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba6[] = { + "\xeb\xa6\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba7[] = { + "\xeb\xa7\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba8[] = { + "\xeb\xa8\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eba9[] = { + "\xeb\xa9\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebaa[] = { + "\xeb\xaa\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebab[] = { + "\xeb\xab\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebac[] = { + "\xeb\xac\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebad[] = { + "\xeb\xad\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebae[] = { + "\xeb\xae\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebaf[] = { + "\xeb\xaf\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb0[] = { + "\xeb\xb0\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb1[] = { + "\xeb\xb1\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb2[] = { + "\xeb\xb2\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb3[] = { + "\xeb\xb3\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb4[] = { + "\xeb\xb4\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb5[] = { + "\xeb\xb5\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb6[] = { + "\xeb\xb6\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb7[] = { + "\xeb\xb7\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb8[] = { + "\xeb\xb8\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebb9[] = { + "\xeb\xb9\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebba[] = { + "\xeb\xba\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebbb[] = { + "\xeb\xbb\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebbc[] = { + "\xeb\xbc\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebbd[] = { + "\xeb\xbd\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebbe[] = { + "\xeb\xbe\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ebbf[] = { + "\xeb\xbf\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec80[] = { + "\xec\x80\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec81[] = { + "\xec\x81\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec82[] = { + "\xec\x82\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec83[] = { + "\xec\x83\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec84[] = { + "\xec\x84\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec85[] = { + "\xec\x85\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec86[] = { + "\xec\x86\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec87[] = { + "\xec\x87\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec88[] = { + "\xec\x88\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec89[] = { + "\xec\x89\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec8a[] = { + "\xec\x8a\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec8b[] = { + "\xec\x8b\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec8c[] = { + "\xec\x8c\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec8d[] = { + "\xec\x8d\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec8e[] = { + "\xec\x8e\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec8f[] = { + "\xec\x8f\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec90[] = { + "\xec\x90\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec91[] = { + "\xec\x91\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec92[] = { + "\xec\x92\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec93[] = { + "\xec\x93\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec94[] = { + "\xec\x94\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec95[] = { + "\xec\x95\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec96[] = { + "\xec\x96\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec97[] = { + "\xec\x97\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec98[] = { + "\xec\x98\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec99[] = { + "\xec\x99\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec9a[] = { + "\xec\x9a\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec9b[] = { + "\xec\x9b\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec9c[] = { + "\xec\x9c\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec9d[] = { + "\xec\x9d\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec9e[] = { + "\xec\x9e\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ec9f[] = { + "\xec\x9f\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca0[] = { + "\xec\xa0\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca1[] = { + "\xec\xa1\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca2[] = { + "\xec\xa2\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca3[] = { + "\xec\xa3\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca4[] = { + "\xec\xa4\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca5[] = { + "\xec\xa5\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca6[] = { + "\xec\xa6\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca7[] = { + "\xec\xa7\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca8[] = { + "\xec\xa8\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_eca9[] = { + "\xec\xa9\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecaa[] = { + "\xec\xaa\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecab[] = { + "\xec\xab\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecac[] = { + "\xec\xac\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecad[] = { + "\xec\xad\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecae[] = { + "\xec\xae\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecaf[] = { + "\xec\xaf\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb0[] = { + "\xec\xb0\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb1[] = { + "\xec\xb1\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb2[] = { + "\xec\xb2\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb3[] = { + "\xec\xb3\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb4[] = { + "\xec\xb4\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb5[] = { + "\xec\xb5\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb6[] = { + "\xec\xb6\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb7[] = { + "\xec\xb7\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb8[] = { + "\xec\xb8\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecb9[] = { + "\xec\xb9\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecba[] = { + "\xec\xba\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecbb[] = { + "\xec\xbb\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecbc[] = { + "\xec\xbc\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecbd[] = { + "\xec\xbd\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecbe[] = { + "\xec\xbe\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ecbf[] = { + "\xec\xbf\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed80[] = { + "\xed\x80\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed81[] = { + "\xed\x81\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed82[] = { + "\xed\x82\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed83[] = { + "\xed\x83\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed84[] = { + "\xed\x84\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed85[] = { + "\xed\x85\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed86[] = { + "\xed\x86\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed87[] = { + "\xed\x87\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed88[] = { + "\xed\x88\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed89[] = { + "\xed\x89\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed8a[] = { + "\xed\x8a\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed8b[] = { + "\xed\x8b\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed8c[] = { + "\xed\x8c\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed8d[] = { + "\xed\x8d\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed8e[] = { + "\xed\x8e\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed8f[] = { + "\xed\x8f\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed90[] = { + "\xed\x90\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed91[] = { + "\xed\x91\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed92[] = { + "\xed\x92\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed93[] = { + "\xed\x93\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed94[] = { + "\xed\x94\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed95[] = { + "\xed\x95\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed96[] = { + "\xed\x96\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed97[] = { + "\xed\x97\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xba" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed98[] = { + "\xed\x98\x96", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xb2", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed99[] = { + "\xed\x99\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed9a[] = { + "\xed\x9a\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed9b[] = { + "\xed\x9b\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed9c[] = { + "\xed\x9c\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e186bd_table_ed9d[] = { + "\xed\x9d\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9e\x82" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186bd(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bd_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bd_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bd_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bd_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bd_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bd_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bd_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x9e"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab0[] = { + "\xea\xb0\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab1[] = { + "\xea\xb1\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab2[] = { + "\xea\xb2\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab3[] = { + "\xea\xb3\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab4[] = { + "\xea\xb4\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab5[] = { + "\xea\xb5\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab6[] = { + "\xea\xb6\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab7[] = { + "\xea\xb7\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab8[] = { + "\xea\xb8\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eab9[] = { + "\xea\xb9\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eaba[] = { + "\xea\xba\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eabb[] = { + "\xea\xbb\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eabc[] = { + "\xea\xbc\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eabd[] = { + "\xea\xbd\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eabe[] = { + "\xea\xbe\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eabf[] = { + "\xea\xbf\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb80[] = { + "\xeb\x80\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb81[] = { + "\xeb\x81\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb82[] = { + "\xeb\x82\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb83[] = { + "\xeb\x83\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb84[] = { + "\xeb\x84\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb85[] = { + "\xeb\x85\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb86[] = { + "\xeb\x86\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb87[] = { + "\xeb\x87\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb88[] = { + "\xeb\x88\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb89[] = { + "\xeb\x89\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb8a[] = { + "\xeb\x8a\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb8b[] = { + "\xeb\x8b\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb8c[] = { + "\xeb\x8c\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb8d[] = { + "\xeb\x8d\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb8e[] = { + "\xeb\x8e\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb8f[] = { + "\xeb\x8f\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb90[] = { + "\xeb\x90\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb91[] = { + "\xeb\x91\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb92[] = { + "\xeb\x92\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb93[] = { + "\xeb\x93\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb94[] = { + "\xeb\x94\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb95[] = { + "\xeb\x95\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb96[] = { + "\xeb\x96\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb97[] = { + "\xeb\x97\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb98[] = { + "\xeb\x98\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb99[] = { + "\xeb\x99\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb9a[] = { + "\xeb\x9a\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb9b[] = { + "\xeb\x9b\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb9c[] = { + "\xeb\x9c\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb9d[] = { + "\xeb\x9d\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb9e[] = { + "\xeb\x9e\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eb9f[] = { + "\xeb\x9f\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba0[] = { + "\xeb\xa0\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba1[] = { + "\xeb\xa1\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba2[] = { + "\xeb\xa2\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba3[] = { + "\xeb\xa3\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba4[] = { + "\xeb\xa4\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba5[] = { + "\xeb\xa5\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba6[] = { + "\xeb\xa6\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba7[] = { + "\xeb\xa7\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba8[] = { + "\xeb\xa8\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eba9[] = { + "\xeb\xa9\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebaa[] = { + "\xeb\xaa\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebab[] = { + "\xeb\xab\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebac[] = { + "\xeb\xac\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebad[] = { + "\xeb\xad\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebae[] = { + "\xeb\xae\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebaf[] = { + "\xeb\xaf\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb0[] = { + "\xeb\xb0\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb1[] = { + "\xeb\xb1\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb2[] = { + "\xeb\xb2\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb3[] = { + "\xeb\xb3\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb4[] = { + "\xeb\xb4\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb5[] = { + "\xeb\xb5\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb6[] = { + "\xeb\xb6\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb7[] = { + "\xeb\xb7\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb8[] = { + "\xeb\xb8\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebb9[] = { + "\xeb\xb9\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebba[] = { + "\xeb\xba\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebbb[] = { + "\xeb\xbb\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebbc[] = { + "\xeb\xbc\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebbd[] = { + "\xeb\xbd\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebbe[] = { + "\xeb\xbe\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ebbf[] = { + "\xeb\xbf\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec80[] = { + "\xec\x80\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec81[] = { + "\xec\x81\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec82[] = { + "\xec\x82\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec83[] = { + "\xec\x83\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec84[] = { + "\xec\x84\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec85[] = { + "\xec\x85\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec86[] = { + "\xec\x86\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec87[] = { + "\xec\x87\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec88[] = { + "\xec\x88\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec89[] = { + "\xec\x89\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec8a[] = { + "\xec\x8a\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec8b[] = { + "\xec\x8b\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec8c[] = { + "\xec\x8c\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec8d[] = { + "\xec\x8d\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec8e[] = { + "\xec\x8e\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec8f[] = { + "\xec\x8f\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec90[] = { + "\xec\x90\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec91[] = { + "\xec\x91\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec92[] = { + "\xec\x92\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec93[] = { + "\xec\x93\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec94[] = { + "\xec\x94\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec95[] = { + "\xec\x95\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec96[] = { + "\xec\x96\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec97[] = { + "\xec\x97\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec98[] = { + "\xec\x98\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec99[] = { + "\xec\x99\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec9a[] = { + "\xec\x9a\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec9b[] = { + "\xec\x9b\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec9c[] = { + "\xec\x9c\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec9d[] = { + "\xec\x9d\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec9e[] = { + "\xec\x9e\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ec9f[] = { + "\xec\x9f\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca0[] = { + "\xec\xa0\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca1[] = { + "\xec\xa1\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca2[] = { + "\xec\xa2\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca3[] = { + "\xec\xa3\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca4[] = { + "\xec\xa4\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca5[] = { + "\xec\xa5\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca6[] = { + "\xec\xa6\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca7[] = { + "\xec\xa7\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca8[] = { + "\xec\xa8\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_eca9[] = { + "\xec\xa9\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecaa[] = { + "\xec\xaa\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecab[] = { + "\xec\xab\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecac[] = { + "\xec\xac\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecad[] = { + "\xec\xad\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecae[] = { + "\xec\xae\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecaf[] = { + "\xec\xaf\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb0[] = { + "\xec\xb0\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb1[] = { + "\xec\xb1\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb2[] = { + "\xec\xb2\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb3[] = { + "\xec\xb3\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb4[] = { + "\xec\xb4\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb5[] = { + "\xec\xb5\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb6[] = { + "\xec\xb6\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb7[] = { + "\xec\xb7\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb8[] = { + "\xec\xb8\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecb9[] = { + "\xec\xb9\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecba[] = { + "\xec\xba\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecbb[] = { + "\xec\xbb\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecbc[] = { + "\xec\xbc\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecbd[] = { + "\xec\xbd\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecbe[] = { + "\xec\xbe\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ecbf[] = { + "\xec\xbf\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed80[] = { + "\xed\x80\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed81[] = { + "\xed\x81\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed82[] = { + "\xed\x82\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed83[] = { + "\xed\x83\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed84[] = { + "\xed\x84\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed85[] = { + "\xed\x85\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed86[] = { + "\xed\x86\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed87[] = { + "\xed\x87\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed88[] = { + "\xed\x88\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed89[] = { + "\xed\x89\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed8a[] = { + "\xed\x8a\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed8b[] = { + "\xed\x8b\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed8c[] = { + "\xed\x8c\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed8d[] = { + "\xed\x8d\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed8e[] = { + "\xed\x8e\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed8f[] = { + "\xed\x8f\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed90[] = { + "\xed\x90\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed91[] = { + "\xed\x91\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed92[] = { + "\xed\x92\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed93[] = { + "\xed\x93\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed94[] = { + "\xed\x94\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed95[] = { + "\xed\x95\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed96[] = { + "\xed\x96\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed97[] = { + "\xed\x97\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xbb" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed98[] = { + "\xed\x98\x97", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xb3", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed99[] = { + "\xed\x99\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed9a[] = { + "\xed\x9a\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed9b[] = { + "\xed\x9b\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed9c[] = { + "\xed\x9c\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e186be_table_ed9d[] = { + "\xed\x9d\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9e\x83" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186be(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186be_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186be_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186be_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186be_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186be_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186be_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186be_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\x9f"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab0[] = { + "\xea\xb0\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab1[] = { + "\xea\xb1\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab2[] = { + "\xea\xb2\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab3[] = { + "\xea\xb3\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab4[] = { + "\xea\xb4\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab5[] = { + "\xea\xb5\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab6[] = { + "\xea\xb6\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab7[] = { + "\xea\xb7\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab8[] = { + "\xea\xb8\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eab9[] = { + "\xea\xb9\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eaba[] = { + "\xea\xba\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eabb[] = { + "\xea\xbb\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eabc[] = { + "\xea\xbc\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eabd[] = { + "\xea\xbd\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eabe[] = { + "\xea\xbe\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eabf[] = { + "\xea\xbf\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb80[] = { + "\xeb\x80\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb81[] = { + "\xeb\x81\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb82[] = { + "\xeb\x82\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb83[] = { + "\xeb\x83\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb84[] = { + "\xeb\x84\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb85[] = { + "\xeb\x85\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb86[] = { + "\xeb\x86\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb87[] = { + "\xeb\x87\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb88[] = { + "\xeb\x88\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb89[] = { + "\xeb\x89\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb8a[] = { + "\xeb\x8a\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb8b[] = { + "\xeb\x8b\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb8c[] = { + "\xeb\x8c\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb8d[] = { + "\xeb\x8d\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb8e[] = { + "\xeb\x8e\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb8f[] = { + "\xeb\x8f\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb90[] = { + "\xeb\x90\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb91[] = { + "\xeb\x91\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb92[] = { + "\xeb\x92\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb93[] = { + "\xeb\x93\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb94[] = { + "\xeb\x94\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb95[] = { + "\xeb\x95\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb96[] = { + "\xeb\x96\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb97[] = { + "\xeb\x97\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb98[] = { + "\xeb\x98\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb99[] = { + "\xeb\x99\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb9a[] = { + "\xeb\x9a\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb9b[] = { + "\xeb\x9b\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb9c[] = { + "\xeb\x9c\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb9d[] = { + "\xeb\x9d\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb9e[] = { + "\xeb\x9e\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eb9f[] = { + "\xeb\x9f\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba0[] = { + "\xeb\xa0\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba1[] = { + "\xeb\xa1\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba2[] = { + "\xeb\xa2\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba3[] = { + "\xeb\xa3\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba4[] = { + "\xeb\xa4\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba5[] = { + "\xeb\xa5\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba6[] = { + "\xeb\xa6\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba7[] = { + "\xeb\xa7\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba8[] = { + "\xeb\xa8\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eba9[] = { + "\xeb\xa9\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebaa[] = { + "\xeb\xaa\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebab[] = { + "\xeb\xab\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebac[] = { + "\xeb\xac\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebad[] = { + "\xeb\xad\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebae[] = { + "\xeb\xae\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebaf[] = { + "\xeb\xaf\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb0[] = { + "\xeb\xb0\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb1[] = { + "\xeb\xb1\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb2[] = { + "\xeb\xb2\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb3[] = { + "\xeb\xb3\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb4[] = { + "\xeb\xb4\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb5[] = { + "\xeb\xb5\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb6[] = { + "\xeb\xb6\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb7[] = { + "\xeb\xb7\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb8[] = { + "\xeb\xb8\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebb9[] = { + "\xeb\xb9\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebba[] = { + "\xeb\xba\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebbb[] = { + "\xeb\xbb\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebbc[] = { + "\xeb\xbc\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebbd[] = { + "\xeb\xbd\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebbe[] = { + "\xeb\xbe\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ebbf[] = { + "\xeb\xbf\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec80[] = { + "\xec\x80\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec81[] = { + "\xec\x81\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec82[] = { + "\xec\x82\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec83[] = { + "\xec\x83\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec84[] = { + "\xec\x84\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec85[] = { + "\xec\x85\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec86[] = { + "\xec\x86\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec87[] = { + "\xec\x87\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec88[] = { + "\xec\x88\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec89[] = { + "\xec\x89\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec8a[] = { + "\xec\x8a\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec8b[] = { + "\xec\x8b\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec8c[] = { + "\xec\x8c\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec8d[] = { + "\xec\x8d\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec8e[] = { + "\xec\x8e\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec8f[] = { + "\xec\x8f\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec90[] = { + "\xec\x90\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec91[] = { + "\xec\x91\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec92[] = { + "\xec\x92\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec93[] = { + "\xec\x93\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec94[] = { + "\xec\x94\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec95[] = { + "\xec\x95\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec96[] = { + "\xec\x96\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec97[] = { + "\xec\x97\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec98[] = { + "\xec\x98\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec99[] = { + "\xec\x99\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec9a[] = { + "\xec\x9a\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec9b[] = { + "\xec\x9b\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec9c[] = { + "\xec\x9c\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec9d[] = { + "\xec\x9d\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec9e[] = { + "\xec\x9e\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ec9f[] = { + "\xec\x9f\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca0[] = { + "\xec\xa0\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca1[] = { + "\xec\xa1\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca2[] = { + "\xec\xa2\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca3[] = { + "\xec\xa3\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca4[] = { + "\xec\xa4\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca5[] = { + "\xec\xa5\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca6[] = { + "\xec\xa6\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca7[] = { + "\xec\xa7\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca8[] = { + "\xec\xa8\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_eca9[] = { + "\xec\xa9\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecaa[] = { + "\xec\xaa\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecab[] = { + "\xec\xab\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecac[] = { + "\xec\xac\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecad[] = { + "\xec\xad\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecae[] = { + "\xec\xae\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecaf[] = { + "\xec\xaf\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb0[] = { + "\xec\xb0\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb1[] = { + "\xec\xb1\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb2[] = { + "\xec\xb2\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb3[] = { + "\xec\xb3\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb4[] = { + "\xec\xb4\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb5[] = { + "\xec\xb5\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb6[] = { + "\xec\xb6\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb7[] = { + "\xec\xb7\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb8[] = { + "\xec\xb8\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecb9[] = { + "\xec\xb9\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecba[] = { + "\xec\xba\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecbb[] = { + "\xec\xbb\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecbc[] = { + "\xec\xbc\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecbd[] = { + "\xec\xbd\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecbe[] = { + "\xec\xbe\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ecbf[] = { + "\xec\xbf\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed80[] = { + "\xed\x80\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed81[] = { + "\xed\x81\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed82[] = { + "\xed\x82\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed83[] = { + "\xed\x83\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed84[] = { + "\xed\x84\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed85[] = { + "\xed\x85\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed86[] = { + "\xed\x86\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed87[] = { + "\xed\x87\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed88[] = { + "\xed\x88\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed89[] = { + "\xed\x89\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed8a[] = { + "\xed\x8a\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed8b[] = { + "\xed\x8b\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed8c[] = { + "\xed\x8c\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed8d[] = { + "\xed\x8d\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed8e[] = { + "\xed\x8e\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed8f[] = { + "\xed\x8f\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed90[] = { + "\xed\x90\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed91[] = { + "\xed\x91\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed92[] = { + "\xed\x92\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed93[] = { + "\xed\x93\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed94[] = { + "\xed\x94\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed95[] = { + "\xed\x95\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed96[] = { + "\xed\x96\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\x84" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed97[] = { + "\xed\x97\xa0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xbc" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed98[] = { + "\xed\x98\x98", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xb4", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x90" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed99[] = { + "\xed\x99\xac", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x88" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed9a[] = { + "\xed\x9a\xa4", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\x80" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed9b[] = { + "\xed\x9b\x9c", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb8", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x94" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed9c[] = { + "\xed\x9c\xb0", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x8c" +}; + +static const char *grn_nfkc50_compose_prefix_e186bf_table_ed9d[] = { + "\xed\x9d\xa8", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9e\x84" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e186bf(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e186bf_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e186bf_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e186bf_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e186bf_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e186bf_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e186bf_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e186bf_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\xa0"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab0[] = { + "\xea\xb0\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab1[] = { + "\xea\xb1\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab2[] = { + "\xea\xb2\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab3[] = { + "\xea\xb3\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab4[] = { + "\xea\xb4\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab5[] = { + "\xea\xb5\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab6[] = { + "\xea\xb6\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab7[] = { + "\xea\xb7\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab8[] = { + "\xea\xb8\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eab9[] = { + "\xea\xb9\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eaba[] = { + "\xea\xba\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eabb[] = { + "\xea\xbb\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eabc[] = { + "\xea\xbc\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eabd[] = { + "\xea\xbd\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eabe[] = { + "\xea\xbe\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eabf[] = { + "\xea\xbf\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb80[] = { + "\xeb\x80\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb81[] = { + "\xeb\x81\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb82[] = { + "\xeb\x82\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb83[] = { + "\xeb\x83\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb84[] = { + "\xeb\x84\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb85[] = { + "\xeb\x85\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb86[] = { + "\xeb\x86\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb87[] = { + "\xeb\x87\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb88[] = { + "\xeb\x88\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb89[] = { + "\xeb\x89\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb8a[] = { + "\xeb\x8a\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb8b[] = { + "\xeb\x8b\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb8c[] = { + "\xeb\x8c\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb8d[] = { + "\xeb\x8d\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb8e[] = { + "\xeb\x8e\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb8f[] = { + "\xeb\x8f\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb90[] = { + "\xeb\x90\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb91[] = { + "\xeb\x91\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb92[] = { + "\xeb\x92\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb93[] = { + "\xeb\x93\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb94[] = { + "\xeb\x94\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb95[] = { + "\xeb\x95\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb96[] = { + "\xeb\x96\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb97[] = { + "\xeb\x97\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb98[] = { + "\xeb\x98\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb99[] = { + "\xeb\x99\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb9a[] = { + "\xeb\x9a\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb9b[] = { + "\xeb\x9b\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb9c[] = { + "\xeb\x9c\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb9d[] = { + "\xeb\x9d\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb9e[] = { + "\xeb\x9e\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eb9f[] = { + "\xeb\x9f\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba0[] = { + "\xeb\xa0\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba1[] = { + "\xeb\xa1\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba2[] = { + "\xeb\xa2\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba3[] = { + "\xeb\xa3\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba4[] = { + "\xeb\xa4\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba5[] = { + "\xeb\xa5\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba6[] = { + "\xeb\xa6\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba7[] = { + "\xeb\xa7\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba8[] = { + "\xeb\xa8\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eba9[] = { + "\xeb\xa9\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebaa[] = { + "\xeb\xaa\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebab[] = { + "\xeb\xab\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebac[] = { + "\xeb\xac\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebad[] = { + "\xeb\xad\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebae[] = { + "\xeb\xae\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebaf[] = { + "\xeb\xaf\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb0[] = { + "\xeb\xb0\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb1[] = { + "\xeb\xb1\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb2[] = { + "\xeb\xb2\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb3[] = { + "\xeb\xb3\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb4[] = { + "\xeb\xb4\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb5[] = { + "\xeb\xb5\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb6[] = { + "\xeb\xb6\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb7[] = { + "\xeb\xb7\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb8[] = { + "\xeb\xb8\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebb9[] = { + "\xeb\xb9\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebba[] = { + "\xeb\xba\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebbb[] = { + "\xeb\xbb\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebbc[] = { + "\xeb\xbc\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebbd[] = { + "\xeb\xbd\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebbe[] = { + "\xeb\xbe\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ebbf[] = { + "\xeb\xbf\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec80[] = { + "\xec\x80\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec81[] = { + "\xec\x81\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec82[] = { + "\xec\x82\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec83[] = { + "\xec\x83\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec84[] = { + "\xec\x84\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec85[] = { + "\xec\x85\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec86[] = { + "\xec\x86\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec87[] = { + "\xec\x87\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec88[] = { + "\xec\x88\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec89[] = { + "\xec\x89\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec8a[] = { + "\xec\x8a\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec8b[] = { + "\xec\x8b\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec8c[] = { + "\xec\x8c\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec8d[] = { + "\xec\x8d\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec8e[] = { + "\xec\x8e\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec8f[] = { + "\xec\x8f\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec90[] = { + "\xec\x90\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec91[] = { + "\xec\x91\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec92[] = { + "\xec\x92\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec93[] = { + "\xec\x93\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec94[] = { + "\xec\x94\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec95[] = { + "\xec\x95\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec96[] = { + "\xec\x96\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec97[] = { + "\xec\x97\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec98[] = { + "\xec\x98\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec99[] = { + "\xec\x99\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec9a[] = { + "\xec\x9a\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec9b[] = { + "\xec\x9b\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec9c[] = { + "\xec\x9c\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec9d[] = { + "\xec\x9d\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec9e[] = { + "\xec\x9e\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ec9f[] = { + "\xec\x9f\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca0[] = { + "\xec\xa0\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca1[] = { + "\xec\xa1\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca2[] = { + "\xec\xa2\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca3[] = { + "\xec\xa3\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca4[] = { + "\xec\xa4\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca5[] = { + "\xec\xa5\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca6[] = { + "\xec\xa6\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca7[] = { + "\xec\xa7\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca8[] = { + "\xec\xa8\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_eca9[] = { + "\xec\xa9\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecaa[] = { + "\xec\xaa\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecab[] = { + "\xec\xab\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecac[] = { + "\xec\xac\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecad[] = { + "\xec\xad\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecae[] = { + "\xec\xae\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecaf[] = { + "\xec\xaf\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb0[] = { + "\xec\xb0\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb1[] = { + "\xec\xb1\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb2[] = { + "\xec\xb2\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb3[] = { + "\xec\xb3\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb4[] = { + "\xec\xb4\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb5[] = { + "\xec\xb5\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb6[] = { + "\xec\xb6\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb7[] = { + "\xec\xb7\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb8[] = { + "\xec\xb8\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecb9[] = { + "\xec\xb9\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecba[] = { + "\xec\xba\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecbb[] = { + "\xec\xbb\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecbc[] = { + "\xec\xbc\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecbd[] = { + "\xec\xbd\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecbe[] = { + "\xec\xbe\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ecbf[] = { + "\xec\xbf\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed80[] = { + "\xed\x80\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed81[] = { + "\xed\x81\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed82[] = { + "\xed\x82\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed83[] = { + "\xed\x83\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed84[] = { + "\xed\x84\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed85[] = { + "\xed\x85\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed86[] = { + "\xed\x86\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed87[] = { + "\xed\x87\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed88[] = { + "\xed\x88\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed89[] = { + "\xed\x89\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed8a[] = { + "\xed\x8a\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed8b[] = { + "\xed\x8b\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed8c[] = { + "\xed\x8c\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed8d[] = { + "\xed\x8d\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed8e[] = { + "\xed\x8e\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed8f[] = { + "\xed\x8f\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed90[] = { + "\xed\x90\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed91[] = { + "\xed\x91\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed92[] = { + "\xed\x92\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed93[] = { + "\xed\x93\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed94[] = { + "\xed\x94\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed95[] = { + "\xed\x95\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed96[] = { + "\xed\x96\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\x85" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed97[] = { + "\xed\x97\xa1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xbd" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed98[] = { + "\xed\x98\x99", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xb5", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x91" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed99[] = { + "\xed\x99\xad", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x89" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed9a[] = { + "\xed\x9a\xa5", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\x81" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed9b[] = { + "\xed\x9b\x9d", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xb9", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x95" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed9c[] = { + "\xed\x9c\xb1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x8d" +}; + +static const char *grn_nfkc50_compose_prefix_e18780_table_ed9d[] = { + "\xed\x9d\xa9", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9e\x85" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e18780(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18780_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18780_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18780_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18780_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18780_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18780_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18780_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\xa1"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab0[] = { + "\xea\xb0\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab1[] = { + "\xea\xb1\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab2[] = { + "\xea\xb2\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab3[] = { + "\xea\xb3\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab4[] = { + "\xea\xb4\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab5[] = { + "\xea\xb5\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab6[] = { + "\xea\xb6\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab7[] = { + "\xea\xb7\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab8[] = { + "\xea\xb8\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eab9[] = { + "\xea\xb9\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eaba[] = { + "\xea\xba\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eabb[] = { + "\xea\xbb\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eabc[] = { + "\xea\xbc\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eabd[] = { + "\xea\xbd\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eabe[] = { + "\xea\xbe\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eabf[] = { + "\xea\xbf\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb80[] = { + "\xeb\x80\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb81[] = { + "\xeb\x81\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb82[] = { + "\xeb\x82\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb83[] = { + "\xeb\x83\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb84[] = { + "\xeb\x84\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb85[] = { + "\xeb\x85\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb86[] = { + "\xeb\x86\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb87[] = { + "\xeb\x87\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb88[] = { + "\xeb\x88\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb89[] = { + "\xeb\x89\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb8a[] = { + "\xeb\x8a\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb8b[] = { + "\xeb\x8b\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb8c[] = { + "\xeb\x8c\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb8d[] = { + "\xeb\x8d\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb8e[] = { + "\xeb\x8e\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb8f[] = { + "\xeb\x8f\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb90[] = { + "\xeb\x90\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb91[] = { + "\xeb\x91\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb92[] = { + "\xeb\x92\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb93[] = { + "\xeb\x93\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb94[] = { + "\xeb\x94\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb95[] = { + "\xeb\x95\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb96[] = { + "\xeb\x96\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb97[] = { + "\xeb\x97\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb98[] = { + "\xeb\x98\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb99[] = { + "\xeb\x99\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb9a[] = { + "\xeb\x9a\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb9b[] = { + "\xeb\x9b\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb9c[] = { + "\xeb\x9c\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb9d[] = { + "\xeb\x9d\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb9e[] = { + "\xeb\x9e\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eb9f[] = { + "\xeb\x9f\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba0[] = { + "\xeb\xa0\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba1[] = { + "\xeb\xa1\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba2[] = { + "\xeb\xa2\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba3[] = { + "\xeb\xa3\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba4[] = { + "\xeb\xa4\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba5[] = { + "\xeb\xa5\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba6[] = { + "\xeb\xa6\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba7[] = { + "\xeb\xa7\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba8[] = { + "\xeb\xa8\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eba9[] = { + "\xeb\xa9\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebaa[] = { + "\xeb\xaa\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebab[] = { + "\xeb\xab\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebac[] = { + "\xeb\xac\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebad[] = { + "\xeb\xad\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebae[] = { + "\xeb\xae\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebaf[] = { + "\xeb\xaf\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb0[] = { + "\xeb\xb0\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb1[] = { + "\xeb\xb1\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb2[] = { + "\xeb\xb2\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb3[] = { + "\xeb\xb3\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb4[] = { + "\xeb\xb4\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb5[] = { + "\xeb\xb5\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb6[] = { + "\xeb\xb6\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb7[] = { + "\xeb\xb7\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb8[] = { + "\xeb\xb8\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebb9[] = { + "\xeb\xb9\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebba[] = { + "\xeb\xba\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebbb[] = { + "\xeb\xbb\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebbc[] = { + "\xeb\xbc\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebbd[] = { + "\xeb\xbd\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebbe[] = { + "\xeb\xbe\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ebbf[] = { + "\xeb\xbf\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec80[] = { + "\xec\x80\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec81[] = { + "\xec\x81\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec82[] = { + "\xec\x82\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec83[] = { + "\xec\x83\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec84[] = { + "\xec\x84\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec85[] = { + "\xec\x85\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec86[] = { + "\xec\x86\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec87[] = { + "\xec\x87\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec88[] = { + "\xec\x88\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec89[] = { + "\xec\x89\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec8a[] = { + "\xec\x8a\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec8b[] = { + "\xec\x8b\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec8c[] = { + "\xec\x8c\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec8d[] = { + "\xec\x8d\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec8e[] = { + "\xec\x8e\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec8f[] = { + "\xec\x8f\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec90[] = { + "\xec\x90\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec91[] = { + "\xec\x91\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec92[] = { + "\xec\x92\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec93[] = { + "\xec\x93\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec94[] = { + "\xec\x94\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec95[] = { + "\xec\x95\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec96[] = { + "\xec\x96\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec97[] = { + "\xec\x97\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec98[] = { + "\xec\x98\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec99[] = { + "\xec\x99\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec9a[] = { + "\xec\x9a\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec9b[] = { + "\xec\x9b\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec9c[] = { + "\xec\x9c\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec9d[] = { + "\xec\x9d\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec9e[] = { + "\xec\x9e\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ec9f[] = { + "\xec\x9f\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca0[] = { + "\xec\xa0\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca1[] = { + "\xec\xa1\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca2[] = { + "\xec\xa2\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca3[] = { + "\xec\xa3\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca4[] = { + "\xec\xa4\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca5[] = { + "\xec\xa5\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca6[] = { + "\xec\xa6\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca7[] = { + "\xec\xa7\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca8[] = { + "\xec\xa8\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_eca9[] = { + "\xec\xa9\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecaa[] = { + "\xec\xaa\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecab[] = { + "\xec\xab\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecac[] = { + "\xec\xac\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecad[] = { + "\xec\xad\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecae[] = { + "\xec\xae\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecaf[] = { + "\xec\xaf\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb0[] = { + "\xec\xb0\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb1[] = { + "\xec\xb1\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb2[] = { + "\xec\xb2\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb3[] = { + "\xec\xb3\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb4[] = { + "\xec\xb4\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb5[] = { + "\xec\xb5\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb6[] = { + "\xec\xb6\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb7[] = { + "\xec\xb7\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb8[] = { + "\xec\xb8\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecb9[] = { + "\xec\xb9\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecba[] = { + "\xec\xba\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecbb[] = { + "\xec\xbb\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecbc[] = { + "\xec\xbc\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecbd[] = { + "\xec\xbd\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecbe[] = { + "\xec\xbe\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ecbf[] = { + "\xec\xbf\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed80[] = { + "\xed\x80\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed81[] = { + "\xed\x81\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed82[] = { + "\xed\x82\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed83[] = { + "\xed\x83\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed84[] = { + "\xed\x84\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed85[] = { + "\xed\x85\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed86[] = { + "\xed\x86\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed87[] = { + "\xed\x87\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed88[] = { + "\xed\x88\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed89[] = { + "\xed\x89\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed8a[] = { + "\xed\x8a\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed8b[] = { + "\xed\x8b\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed8c[] = { + "\xed\x8c\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed8d[] = { + "\xed\x8d\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed8e[] = { + "\xed\x8e\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed8f[] = { + "\xed\x8f\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed90[] = { + "\xed\x90\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed91[] = { + "\xed\x91\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed92[] = { + "\xed\x92\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed93[] = { + "\xed\x93\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed94[] = { + "\xed\x94\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed95[] = { + "\xed\x95\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed96[] = { + "\xed\x96\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\x86" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed97[] = { + "\xed\x97\xa2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xbe" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed98[] = { + "\xed\x98\x9a", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xb6", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x92" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed99[] = { + "\xed\x99\xae", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x8a" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed9a[] = { + "\xed\x9a\xa6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\x82" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed9b[] = { + "\xed\x9b\x9e", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xba", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x96" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed9c[] = { + "\xed\x9c\xb2", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x8e" +}; + +static const char *grn_nfkc50_compose_prefix_e18781_table_ed9d[] = { + "\xed\x9d\xaa", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9e\x86" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e18781(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18781_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18781_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18781_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18781_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18781_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18781_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18781_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\xa2"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab0[] = { + "\xea\xb0\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb0\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb1\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab1[] = { + "\xea\xb1\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb2\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab2[] = { + "\xea\xb2\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab3[] = { + "\xea\xb3\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb3\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb4\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab4[] = { + "\xea\xb4\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb5\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab5[] = { + "\xea\xb5\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab6[] = { + "\xea\xb6\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb6\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab7[] = { + "\xea\xb7\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb7\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xb8\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab8[] = { + "\xea\xb8\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xb9\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eab9[] = { + "\xea\xb9\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eaba[] = { + "\xea\xba\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xba\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbb\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eabb[] = { + "\xea\xbb\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbc\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eabc[] = { + "\xea\xbc\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eabd[] = { + "\xea\xbd\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbd\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eabe[] = { + "\xea\xbe\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xea\xbe\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xea\xbf\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eabf[] = { + "\xea\xbf\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x80\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb80[] = { + "\xeb\x80\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb81[] = { + "\xeb\x81\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x81\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x82\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb82[] = { + "\xeb\x82\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x83\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb83[] = { + "\xeb\x83\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb84[] = { + "\xeb\x84\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x84\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb85[] = { + "\xeb\x85\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x85\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x86\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb86[] = { + "\xeb\x86\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x87\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb87[] = { + "\xeb\x87\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb88[] = { + "\xeb\x88\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x88\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x89\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb89[] = { + "\xeb\x89\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8a\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb8a[] = { + "\xeb\x8a\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb8b[] = { + "\xeb\x8b\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8b\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb8c[] = { + "\xeb\x8c\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8c\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x8d\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb8d[] = { + "\xeb\x8d\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8e\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb8e[] = { + "\xeb\x8e\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb8f[] = { + "\xeb\x8f\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x8f\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x90\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb90[] = { + "\xeb\x90\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x91\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb91[] = { + "\xeb\x91\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb92[] = { + "\xeb\x92\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x92\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb93[] = { + "\xeb\x93\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x93\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x94\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb94[] = { + "\xeb\x94\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x95\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb95[] = { + "\xeb\x95\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb96[] = { + "\xeb\x96\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x96\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x97\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb97[] = { + "\xeb\x97\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x98\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb98[] = { + "\xeb\x98\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb99[] = { + "\xeb\x99\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x99\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb9a[] = { + "\xeb\x9a\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9a\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9b\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb9b[] = { + "\xeb\x9b\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9c\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb9c[] = { + "\xeb\x9c\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb9d[] = { + "\xeb\x9d\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9d\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\x9e\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb9e[] = { + "\xeb\x9e\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\x9f\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eb9f[] = { + "\xeb\x9f\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba0[] = { + "\xeb\xa0\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa0\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba1[] = { + "\xeb\xa1\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa1\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa2\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba2[] = { + "\xeb\xa2\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa3\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba3[] = { + "\xeb\xa3\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba4[] = { + "\xeb\xa4\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa4\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa5\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba5[] = { + "\xeb\xa5\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa6\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba6[] = { + "\xeb\xa6\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba7[] = { + "\xeb\xa7\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa7\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba8[] = { + "\xeb\xa8\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xa8\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xa9\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eba9[] = { + "\xeb\xa9\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaa\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebaa[] = { + "\xeb\xaa\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebab[] = { + "\xeb\xab\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xab\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xac\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebac[] = { + "\xeb\xac\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xad\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebad[] = { + "\xeb\xad\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebae[] = { + "\xeb\xae\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xae\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebaf[] = { + "\xeb\xaf\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xaf\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb0\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb0[] = { + "\xeb\xb0\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb1\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb1[] = { + "\xeb\xb1\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb2[] = { + "\xeb\xb2\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb2\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb3\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb3[] = { + "\xeb\xb3\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb4\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb4[] = { + "\xeb\xb4\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb5[] = { + "\xeb\xb5\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb5\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb6[] = { + "\xeb\xb6\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb6\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xb7\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb7[] = { + "\xeb\xb7\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb8\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb8[] = { + "\xeb\xb8\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebb9[] = { + "\xeb\xb9\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xb9\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xba\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebba[] = { + "\xeb\xba\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbb\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebbb[] = { + "\xeb\xbb\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebbc[] = { + "\xeb\xbc\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbc\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebbd[] = { + "\xeb\xbd\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbd\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xeb\xbe\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebbe[] = { + "\xeb\xbe\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xeb\xbf\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ebbf[] = { + "\xeb\xbf\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec80[] = { + "\xec\x80\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x80\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x81\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec81[] = { + "\xec\x81\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x82\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec82[] = { + "\xec\x82\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec83[] = { + "\xec\x83\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x83\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec84[] = { + "\xec\x84\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x84\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x85\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec85[] = { + "\xec\x85\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x86\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec86[] = { + "\xec\x86\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec87[] = { + "\xec\x87\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x87\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x88\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec88[] = { + "\xec\x88\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x89\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec89[] = { + "\xec\x89\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec8a[] = { + "\xec\x8a\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8a\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec8b[] = { + "\xec\x8b\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8b\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8c\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec8c[] = { + "\xec\x8c\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8d\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec8d[] = { + "\xec\x8d\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec8e[] = { + "\xec\x8e\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x8e\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x8f\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec8f[] = { + "\xec\x8f\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x90\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec90[] = { + "\xec\x90\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec91[] = { + "\xec\x91\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x91\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec92[] = { + "\xec\x92\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x92\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x93\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec93[] = { + "\xec\x93\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x94\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec94[] = { + "\xec\x94\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec95[] = { + "\xec\x95\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x95\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x96\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec96[] = { + "\xec\x96\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x97\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec97[] = { + "\xec\x97\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec98[] = { + "\xec\x98\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x98\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec99[] = { + "\xec\x99\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x99\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9a\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec9a[] = { + "\xec\x9a\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9b\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec9b[] = { + "\xec\x9b\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec9c[] = { + "\xec\x9c\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9c\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\x9d\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec9d[] = { + "\xec\x9d\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9e\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec9e[] = { + "\xec\x9e\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ec9f[] = { + "\xec\x9f\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\x9f\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca0[] = { + "\xec\xa0\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa0\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa1\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca1[] = { + "\xec\xa1\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa2\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca2[] = { + "\xec\xa2\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca3[] = { + "\xec\xa3\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa3\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa4\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca4[] = { + "\xec\xa4\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa5\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca5[] = { + "\xec\xa5\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca6[] = { + "\xec\xa6\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa6\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca7[] = { + "\xec\xa7\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa7\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xa8\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca8[] = { + "\xec\xa8\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xa9\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_eca9[] = { + "\xec\xa9\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecaa[] = { + "\xec\xaa\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xaa\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xab\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecab[] = { + "\xec\xab\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xac\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecac[] = { + "\xec\xac\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecad[] = { + "\xec\xad\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xad\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecae[] = { + "\xec\xae\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xae\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xaf\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecaf[] = { + "\xec\xaf\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb0\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb0[] = { + "\xec\xb0\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb1[] = { + "\xec\xb1\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb1\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb2\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb2[] = { + "\xec\xb2\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb3\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb3[] = { + "\xec\xb3\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb4[] = { + "\xec\xb4\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb4\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb5[] = { + "\xec\xb5\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb5\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb6\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb6[] = { + "\xec\xb6\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb7\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb7[] = { + "\xec\xb7\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb8[] = { + "\xec\xb8\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xb8\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xb9\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecb9[] = { + "\xec\xb9\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xba\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecba[] = { + "\xec\xba\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecbb[] = { + "\xec\xbb\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbb\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecbc[] = { + "\xec\xbc\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbc\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xec\xbd\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecbd[] = { + "\xec\xbd\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbe\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecbe[] = { + "\xec\xbe\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ecbf[] = { + "\xec\xbf\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xec\xbf\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x80\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed80[] = { + "\xed\x80\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x81\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed81[] = { + "\xed\x81\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed82[] = { + "\xed\x82\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x82\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed83[] = { + "\xed\x83\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x83\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x84\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed84[] = { + "\xed\x84\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x85\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed85[] = { + "\xed\x85\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed86[] = { + "\xed\x86\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x86\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x87\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed87[] = { + "\xed\x87\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x88\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed88[] = { + "\xed\x88\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed89[] = { + "\xed\x89\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x89\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed8a[] = { + "\xed\x8a\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8a\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8b\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed8b[] = { + "\xed\x8b\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8c\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed8c[] = { + "\xed\x8c\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed8d[] = { + "\xed\x8d\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8d\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x8e\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed8e[] = { + "\xed\x8e\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x8f\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed8f[] = { + "\xed\x8f\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed90[] = { + "\xed\x90\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x90\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed91[] = { + "\xed\x91\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x91\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x92\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed92[] = { + "\xed\x92\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x93\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed93[] = { + "\xed\x93\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed94[] = { + "\xed\x94\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x94\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x95\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed95[] = { + "\xed\x95\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x96\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed96[] = { + "\xed\x96\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\x87" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed97[] = { + "\xed\x97\xa3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x97\xbf" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed98[] = { + "\xed\x98\x9b", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x98\xb7", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x99\x93" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed99[] = { + "\xed\x99\xaf", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9a\x8b" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed9a[] = { + "\xed\x9a\xa7", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\x83" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed9b[] = { + "\xed\x9b\x9f", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9b\xbb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + "\xed\x9c\x97" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed9c[] = { + "\xed\x9c\xb3", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9d\x8f" +}; + +static const char *grn_nfkc50_compose_prefix_e18782_table_ed9d[] = { + "\xed\x9d\xab", NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, "\xed\x9e\x87" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e18782(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xea : + switch (utf8[1]) { + case 0xb0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eab0[utf8[2] - 0x80]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eab1[utf8[2] - 0x94]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eab2[utf8[2] - 0x8c]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_eab3[utf8[2] - 0x84]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_eab4[utf8[2] - 0x98]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_eab5[utf8[2] - 0x90]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_eab6[utf8[2] - 0x88]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eab7[utf8[2] - 0x80]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eab8[utf8[2] - 0x94]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eab9[utf8[2] - 0x8c]; + } + break; + case 0xba : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_eaba[utf8[2] - 0x84]; + } + break; + case 0xbb : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_eabb[utf8[2] - 0x98]; + } + break; + case 0xbc : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_eabc[utf8[2] - 0x90]; + } + break; + case 0xbd : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_eabd[utf8[2] - 0x88]; + } + break; + case 0xbe : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eabe[utf8[2] - 0x80]; + } + break; + case 0xbf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eabf[utf8[2] - 0x94]; + } + break; + default : + break; + } + break; + case 0xeb : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eb80[utf8[2] - 0x8c]; + } + break; + case 0x81 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_eb81[utf8[2] - 0x84]; + } + break; + case 0x82 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_eb82[utf8[2] - 0x98]; + } + break; + case 0x83 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_eb83[utf8[2] - 0x90]; + } + break; + case 0x84 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_eb84[utf8[2] - 0x88]; + } + break; + case 0x85 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eb85[utf8[2] - 0x80]; + } + break; + case 0x86 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eb86[utf8[2] - 0x94]; + } + break; + case 0x87 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eb87[utf8[2] - 0x8c]; + } + break; + case 0x88 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_eb88[utf8[2] - 0x84]; + } + break; + case 0x89 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_eb89[utf8[2] - 0x98]; + } + break; + case 0x8a : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_eb8a[utf8[2] - 0x90]; + } + break; + case 0x8b : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_eb8b[utf8[2] - 0x88]; + } + break; + case 0x8c : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eb8c[utf8[2] - 0x80]; + } + break; + case 0x8d : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eb8d[utf8[2] - 0x94]; + } + break; + case 0x8e : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eb8e[utf8[2] - 0x8c]; + } + break; + case 0x8f : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_eb8f[utf8[2] - 0x84]; + } + break; + case 0x90 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_eb90[utf8[2] - 0x98]; + } + break; + case 0x91 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_eb91[utf8[2] - 0x90]; + } + break; + case 0x92 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_eb92[utf8[2] - 0x88]; + } + break; + case 0x93 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eb93[utf8[2] - 0x80]; + } + break; + case 0x94 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eb94[utf8[2] - 0x94]; + } + break; + case 0x95 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eb95[utf8[2] - 0x8c]; + } + break; + case 0x96 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_eb96[utf8[2] - 0x84]; + } + break; + case 0x97 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_eb97[utf8[2] - 0x98]; + } + break; + case 0x98 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_eb98[utf8[2] - 0x90]; + } + break; + case 0x99 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_eb99[utf8[2] - 0x88]; + } + break; + case 0x9a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eb9a[utf8[2] - 0x80]; + } + break; + case 0x9b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eb9b[utf8[2] - 0x94]; + } + break; + case 0x9c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eb9c[utf8[2] - 0x8c]; + } + break; + case 0x9d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_eb9d[utf8[2] - 0x84]; + } + break; + case 0x9e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_eb9e[utf8[2] - 0x98]; + } + break; + case 0x9f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_eb9f[utf8[2] - 0x90]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_eba0[utf8[2] - 0x88]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eba1[utf8[2] - 0x80]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eba2[utf8[2] - 0x94]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eba3[utf8[2] - 0x8c]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_eba4[utf8[2] - 0x84]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_eba5[utf8[2] - 0x98]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_eba6[utf8[2] - 0x90]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_eba7[utf8[2] - 0x88]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eba8[utf8[2] - 0x80]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eba9[utf8[2] - 0x94]; + } + break; + case 0xaa : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ebaa[utf8[2] - 0x8c]; + } + break; + case 0xab : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ebab[utf8[2] - 0x84]; + } + break; + case 0xac : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ebac[utf8[2] - 0x98]; + } + break; + case 0xad : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ebad[utf8[2] - 0x90]; + } + break; + case 0xae : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ebae[utf8[2] - 0x88]; + } + break; + case 0xaf : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ebaf[utf8[2] - 0x80]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ebb0[utf8[2] - 0x94]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ebb1[utf8[2] - 0x8c]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ebb2[utf8[2] - 0x84]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ebb3[utf8[2] - 0x98]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ebb4[utf8[2] - 0x90]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ebb5[utf8[2] - 0x88]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ebb6[utf8[2] - 0x80]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ebb7[utf8[2] - 0x94]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ebb8[utf8[2] - 0x8c]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ebb9[utf8[2] - 0x84]; + } + break; + case 0xba : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ebba[utf8[2] - 0x98]; + } + break; + case 0xbb : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ebbb[utf8[2] - 0x90]; + } + break; + case 0xbc : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ebbc[utf8[2] - 0x88]; + } + break; + case 0xbd : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ebbd[utf8[2] - 0x80]; + } + break; + case 0xbe : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ebbe[utf8[2] - 0x94]; + } + break; + case 0xbf : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ebbf[utf8[2] - 0x8c]; + } + break; + default : + break; + } + break; + case 0xec : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ec80[utf8[2] - 0x84]; + } + break; + case 0x81 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ec81[utf8[2] - 0x98]; + } + break; + case 0x82 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ec82[utf8[2] - 0x90]; + } + break; + case 0x83 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ec83[utf8[2] - 0x88]; + } + break; + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ec84[utf8[2] - 0x80]; + } + break; + case 0x85 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ec85[utf8[2] - 0x94]; + } + break; + case 0x86 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ec86[utf8[2] - 0x8c]; + } + break; + case 0x87 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ec87[utf8[2] - 0x84]; + } + break; + case 0x88 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ec88[utf8[2] - 0x98]; + } + break; + case 0x89 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ec89[utf8[2] - 0x90]; + } + break; + case 0x8a : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ec8a[utf8[2] - 0x88]; + } + break; + case 0x8b : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ec8b[utf8[2] - 0x80]; + } + break; + case 0x8c : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ec8c[utf8[2] - 0x94]; + } + break; + case 0x8d : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ec8d[utf8[2] - 0x8c]; + } + break; + case 0x8e : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ec8e[utf8[2] - 0x84]; + } + break; + case 0x8f : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ec8f[utf8[2] - 0x98]; + } + break; + case 0x90 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ec90[utf8[2] - 0x90]; + } + break; + case 0x91 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ec91[utf8[2] - 0x88]; + } + break; + case 0x92 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ec92[utf8[2] - 0x80]; + } + break; + case 0x93 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ec93[utf8[2] - 0x94]; + } + break; + case 0x94 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ec94[utf8[2] - 0x8c]; + } + break; + case 0x95 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ec95[utf8[2] - 0x84]; + } + break; + case 0x96 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ec96[utf8[2] - 0x98]; + } + break; + case 0x97 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ec97[utf8[2] - 0x90]; + } + break; + case 0x98 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ec98[utf8[2] - 0x88]; + } + break; + case 0x99 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ec99[utf8[2] - 0x80]; + } + break; + case 0x9a : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ec9a[utf8[2] - 0x94]; + } + break; + case 0x9b : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ec9b[utf8[2] - 0x8c]; + } + break; + case 0x9c : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ec9c[utf8[2] - 0x84]; + } + break; + case 0x9d : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ec9d[utf8[2] - 0x98]; + } + break; + case 0x9e : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ec9e[utf8[2] - 0x90]; + } + break; + case 0x9f : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ec9f[utf8[2] - 0x88]; + } + break; + case 0xa0 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eca0[utf8[2] - 0x80]; + } + break; + case 0xa1 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eca1[utf8[2] - 0x94]; + } + break; + case 0xa2 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eca2[utf8[2] - 0x8c]; + } + break; + case 0xa3 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_eca3[utf8[2] - 0x84]; + } + break; + case 0xa4 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_eca4[utf8[2] - 0x98]; + } + break; + case 0xa5 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_eca5[utf8[2] - 0x90]; + } + break; + case 0xa6 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_eca6[utf8[2] - 0x88]; + } + break; + case 0xa7 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_eca7[utf8[2] - 0x80]; + } + break; + case 0xa8 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_eca8[utf8[2] - 0x94]; + } + break; + case 0xa9 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_eca9[utf8[2] - 0x8c]; + } + break; + case 0xaa : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ecaa[utf8[2] - 0x84]; + } + break; + case 0xab : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ecab[utf8[2] - 0x98]; + } + break; + case 0xac : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ecac[utf8[2] - 0x90]; + } + break; + case 0xad : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ecad[utf8[2] - 0x88]; + } + break; + case 0xae : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ecae[utf8[2] - 0x80]; + } + break; + case 0xaf : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ecaf[utf8[2] - 0x94]; + } + break; + case 0xb0 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ecb0[utf8[2] - 0x8c]; + } + break; + case 0xb1 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ecb1[utf8[2] - 0x84]; + } + break; + case 0xb2 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ecb2[utf8[2] - 0x98]; + } + break; + case 0xb3 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ecb3[utf8[2] - 0x90]; + } + break; + case 0xb4 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ecb4[utf8[2] - 0x88]; + } + break; + case 0xb5 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ecb5[utf8[2] - 0x80]; + } + break; + case 0xb6 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ecb6[utf8[2] - 0x94]; + } + break; + case 0xb7 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ecb7[utf8[2] - 0x8c]; + } + break; + case 0xb8 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ecb8[utf8[2] - 0x84]; + } + break; + case 0xb9 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ecb9[utf8[2] - 0x98]; + } + break; + case 0xba : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ecba[utf8[2] - 0x90]; + } + break; + case 0xbb : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ecbb[utf8[2] - 0x88]; + } + break; + case 0xbc : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ecbc[utf8[2] - 0x80]; + } + break; + case 0xbd : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ecbd[utf8[2] - 0x94]; + } + break; + case 0xbe : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ecbe[utf8[2] - 0x8c]; + } + break; + case 0xbf : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ecbf[utf8[2] - 0x84]; + } + break; + default : + break; + } + break; + case 0xed : + switch (utf8[1]) { + case 0x80 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ed80[utf8[2] - 0x98]; + } + break; + case 0x81 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ed81[utf8[2] - 0x90]; + } + break; + case 0x82 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ed82[utf8[2] - 0x88]; + } + break; + case 0x83 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ed83[utf8[2] - 0x80]; + } + break; + case 0x84 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ed84[utf8[2] - 0x94]; + } + break; + case 0x85 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ed85[utf8[2] - 0x8c]; + } + break; + case 0x86 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ed86[utf8[2] - 0x84]; + } + break; + case 0x87 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ed87[utf8[2] - 0x98]; + } + break; + case 0x88 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ed88[utf8[2] - 0x90]; + } + break; + case 0x89 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ed89[utf8[2] - 0x88]; + } + break; + case 0x8a : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ed8a[utf8[2] - 0x80]; + } + break; + case 0x8b : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ed8b[utf8[2] - 0x94]; + } + break; + case 0x8c : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ed8c[utf8[2] - 0x8c]; + } + break; + case 0x8d : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ed8d[utf8[2] - 0x84]; + } + break; + case 0x8e : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ed8e[utf8[2] - 0x98]; + } + break; + case 0x8f : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ed8f[utf8[2] - 0x90]; + } + break; + case 0x90 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ed90[utf8[2] - 0x88]; + } + break; + case 0x91 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ed91[utf8[2] - 0x80]; + } + break; + case 0x92 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ed92[utf8[2] - 0x94]; + } + break; + case 0x93 : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ed93[utf8[2] - 0x8c]; + } + break; + case 0x94 : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ed94[utf8[2] - 0x84]; + } + break; + case 0x95 : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ed95[utf8[2] - 0x98]; + } + break; + case 0x96 : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ed96[utf8[2] - 0x90]; + } + break; + case 0x97 : + if (utf8[2] >= 0x88 && + utf8[2] <= 0xa4) { + return grn_nfkc50_compose_prefix_e18782_table_ed97[utf8[2] - 0x88]; + } + break; + case 0x98 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0xb8) { + return grn_nfkc50_compose_prefix_e18782_table_ed98[utf8[2] - 0x80]; + } + break; + case 0x99 : + if (utf8[2] >= 0x94 && + utf8[2] <= 0xb0) { + return grn_nfkc50_compose_prefix_e18782_table_ed99[utf8[2] - 0x94]; + } + break; + case 0x9a : + if (utf8[2] >= 0x8c && + utf8[2] <= 0xa8) { + return grn_nfkc50_compose_prefix_e18782_table_ed9a[utf8[2] - 0x8c]; + } + break; + case 0x9b : + if (utf8[2] >= 0x84 && + utf8[2] <= 0xbc) { + return grn_nfkc50_compose_prefix_e18782_table_ed9b[utf8[2] - 0x84]; + } + break; + case 0x9c : + if (utf8[2] >= 0x98 && + utf8[2] <= 0xb4) { + return grn_nfkc50_compose_prefix_e18782_table_ed9c[utf8[2] - 0x98]; + } + break; + case 0x9d : + if (utf8[2] >= 0x90 && + utf8[2] <= 0xac) { + return grn_nfkc50_compose_prefix_e18782_table_ed9d[utf8[2] - 0x90]; + } + break; + case 0x9e : + if (utf8[2] == 0x88) { + return "\xed\x9e\xa3"; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185a2_table_e184[] = { + "\xea\xb0\x9c", "\xea\xb9\xa8", "\xeb\x82\xb4", "\xeb\x8c\x80", "\xeb\x95\x8c", "\xeb\x9e\x98", "\xeb\xa7\xa4", "\xeb\xb0\xb0", + "\xeb\xb9\xbc", "\xec\x83\x88", "\xec\x8c\x94", "\xec\x95\xa0", "\xec\x9e\xac", "\xec\xa7\xb8", "\xec\xb1\x84", "\xec\xba\x90", + "\xed\x83\x9c", "\xed\x8c\xa8", "\xed\x95\xb4" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185a2(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185a2_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185a3_table_e184[] = { + "\xea\xb0\xb8", "\xea\xba\x84", "\xeb\x83\x90", "\xeb\x8c\x9c", "\xeb\x95\xa8", "\xeb\x9e\xb4", "\xeb\xa8\x80", "\xeb\xb1\x8c", + "\xeb\xba\x98", "\xec\x83\xa4", "\xec\x8c\xb0", "\xec\x95\xbc", "\xec\x9f\x88", "\xec\xa8\x94", "\xec\xb1\xa0", "\xec\xba\xac", + "\xed\x83\xb8", "\xed\x8d\x84", "\xed\x96\x90" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185a3(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185a3_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185a4_table_e184[] = { + "\xea\xb1\x94", "\xea\xba\xa0", "\xeb\x83\xac", "\xeb\x8c\xb8", "\xeb\x96\x84", "\xeb\x9f\x90", "\xeb\xa8\x9c", "\xeb\xb1\xa8", + "\xeb\xba\xb4", "\xec\x84\x80", "\xec\x8d\x8c", "\xec\x96\x98", "\xec\x9f\xa4", "\xec\xa8\xb0", "\xec\xb1\xbc", "\xec\xbb\x88", + "\xed\x84\x94", "\xed\x8d\xa0", "\xed\x96\xac" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185a4(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185a4_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185a5_table_e184[] = { + "\xea\xb1\xb0", "\xea\xba\xbc", "\xeb\x84\x88", "\xeb\x8d\x94", "\xeb\x96\xa0", "\xeb\x9f\xac", "\xeb\xa8\xb8", "\xeb\xb2\x84", + "\xeb\xbb\x90", "\xec\x84\x9c", "\xec\x8d\xa8", "\xec\x96\xb4", "\xec\xa0\x80", "\xec\xa9\x8c", "\xec\xb2\x98", "\xec\xbb\xa4", + "\xed\x84\xb0", "\xed\x8d\xbc", "\xed\x97\x88" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185a5(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185a5_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185a6_table_e184[] = { + "\xea\xb2\x8c", "\xea\xbb\x98", "\xeb\x84\xa4", "\xeb\x8d\xb0", "\xeb\x96\xbc", "\xeb\xa0\x88", "\xeb\xa9\x94", "\xeb\xb2\xa0", + "\xeb\xbb\xac", "\xec\x84\xb8", "\xec\x8e\x84", "\xec\x97\x90", "\xec\xa0\x9c", "\xec\xa9\xa8", "\xec\xb2\xb4", "\xec\xbc\x80", + "\xed\x85\x8c", "\xed\x8e\x98", "\xed\x97\xa4" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185a6(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185a6_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185a7_table_e184[] = { + "\xea\xb2\xa8", "\xea\xbb\xb4", "\xeb\x85\x80", "\xeb\x8e\x8c", "\xeb\x97\x98", "\xeb\xa0\xa4", "\xeb\xa9\xb0", "\xeb\xb2\xbc", + "\xeb\xbc\x88", "\xec\x85\x94", "\xec\x8e\xa0", "\xec\x97\xac", "\xec\xa0\xb8", "\xec\xaa\x84", "\xec\xb3\x90", "\xec\xbc\x9c", + "\xed\x85\xa8", "\xed\x8e\xb4", "\xed\x98\x80" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185a7(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185a7_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185a8_table_e184[] = { + "\xea\xb3\x84", "\xea\xbc\x90", "\xeb\x85\x9c", "\xeb\x8e\xa8", "\xeb\x97\xb4", "\xeb\xa1\x80", "\xeb\xaa\x8c", "\xeb\xb3\x98", + "\xeb\xbc\xa4", "\xec\x85\xb0", "\xec\x8e\xbc", "\xec\x98\x88", "\xec\xa1\x94", "\xec\xaa\xa0", "\xec\xb3\xac", "\xec\xbc\xb8", + "\xed\x86\x84", "\xed\x8f\x90", "\xed\x98\x9c" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185a8(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185a8_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185a9_table_e184[] = { + "\xea\xb3\xa0", "\xea\xbc\xac", "\xeb\x85\xb8", "\xeb\x8f\x84", "\xeb\x98\x90", "\xeb\xa1\x9c", "\xeb\xaa\xa8", "\xeb\xb3\xb4", + "\xeb\xbd\x80", "\xec\x86\x8c", "\xec\x8f\x98", "\xec\x98\xa4", "\xec\xa1\xb0", "\xec\xaa\xbc", "\xec\xb4\x88", "\xec\xbd\x94", + "\xed\x86\xa0", "\xed\x8f\xac", "\xed\x98\xb8" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185a9(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185a9_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185aa_table_e184[] = { + "\xea\xb3\xbc", "\xea\xbd\x88", "\xeb\x86\x94", "\xeb\x8f\xa0", "\xeb\x98\xac", "\xeb\xa1\xb8", "\xeb\xab\x84", "\xeb\xb4\x90", + "\xeb\xbd\x9c", "\xec\x86\xa8", "\xec\x8f\xb4", "\xec\x99\x80", "\xec\xa2\x8c", "\xec\xab\x98", "\xec\xb4\xa4", "\xec\xbd\xb0", + "\xed\x86\xbc", "\xed\x90\x88", "\xed\x99\x94" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185aa(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185aa_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185ab_table_e184[] = { + "\xea\xb4\x98", "\xea\xbd\xa4", "\xeb\x86\xb0", "\xeb\x8f\xbc", "\xeb\x99\x88", "\xeb\xa2\x94", "\xeb\xab\xa0", "\xeb\xb4\xac", + "\xeb\xbd\xb8", "\xec\x87\x84", "\xec\x90\x90", "\xec\x99\x9c", "\xec\xa2\xa8", "\xec\xab\xb4", "\xec\xb5\x80", "\xec\xbe\x8c", + "\xed\x87\x98", "\xed\x90\xa4", "\xed\x99\xb0" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185ab(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185ab_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185ac_table_e184[] = { + "\xea\xb4\xb4", "\xea\xbe\x80", "\xeb\x87\x8c", "\xeb\x90\x98", "\xeb\x99\xa4", "\xeb\xa2\xb0", "\xeb\xab\xbc", "\xeb\xb5\x88", + "\xeb\xbe\x94", "\xec\x87\xa0", "\xec\x90\xac", "\xec\x99\xb8", "\xec\xa3\x84", "\xec\xac\x90", "\xec\xb5\x9c", "\xec\xbe\xa8", + "\xed\x87\xb4", "\xed\x91\x80", "\xed\x9a\x8c" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185ac(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185ac_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185ad_table_e184[] = { + "\xea\xb5\x90", "\xea\xbe\x9c", "\xeb\x87\xa8", "\xeb\x90\xb4", "\xeb\x9a\x80", "\xeb\xa3\x8c", "\xeb\xac\x98", "\xeb\xb5\xa4", + "\xeb\xbe\xb0", "\xec\x87\xbc", "\xec\x91\x88", "\xec\x9a\x94", "\xec\xa3\xa0", "\xec\xac\xac", "\xec\xb5\xb8", "\xec\xbf\x84", + "\xed\x88\x90", "\xed\x91\x9c", "\xed\x9a\xa8" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185ad(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185ad_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185ae_table_e184[] = { + "\xea\xb5\xac", "\xea\xbe\xb8", "\xeb\x88\x84", "\xeb\x91\x90", "\xeb\x9a\x9c", "\xeb\xa3\xa8", "\xeb\xac\xb4", "\xeb\xb6\x80", + "\xeb\xbf\x8c", "\xec\x88\x98", "\xec\x91\xa4", "\xec\x9a\xb0", "\xec\xa3\xbc", "\xec\xad\x88", "\xec\xb6\x94", "\xec\xbf\xa0", + "\xed\x88\xac", "\xed\x91\xb8", "\xed\x9b\x84" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185ae(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185ae_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185af_table_e184[] = { + "\xea\xb6\x88", "\xea\xbf\x94", "\xeb\x88\xa0", "\xeb\x91\xac", "\xeb\x9a\xb8", "\xeb\xa4\x84", "\xeb\xad\x90", "\xeb\xb6\x9c", + "\xeb\xbf\xa8", "\xec\x88\xb4", "\xec\x92\x80", "\xec\x9b\x8c", "\xec\xa4\x98", "\xec\xad\xa4", "\xec\xb6\xb0", "\xec\xbf\xbc", + "\xed\x89\x88", "\xed\x92\x94", "\xed\x9b\xa0" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185af(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185af_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185b0_table_e184[] = { + "\xea\xb6\xa4", "\xea\xbf\xb0", "\xeb\x88\xbc", "\xeb\x92\x88", "\xeb\x9b\x94", "\xeb\xa4\xa0", "\xeb\xad\xac", "\xeb\xb6\xb8", + "\xec\x80\x84", "\xec\x89\x90", "\xec\x92\x9c", "\xec\x9b\xa8", "\xec\xa4\xb4", "\xec\xae\x80", "\xec\xb7\x8c", "\xed\x80\x98", + "\xed\x89\xa4", "\xed\x92\xb0", "\xed\x9b\xbc" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185b0(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185b0_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185b1_table_e184[] = { + "\xea\xb7\x80", "\xeb\x80\x8c", "\xeb\x89\x98", "\xeb\x92\xa4", "\xeb\x9b\xb0", "\xeb\xa4\xbc", "\xeb\xae\x88", "\xeb\xb7\x94", + "\xec\x80\xa0", "\xec\x89\xac", "\xec\x92\xb8", "\xec\x9c\x84", "\xec\xa5\x90", "\xec\xae\x9c", "\xec\xb7\xa8", "\xed\x80\xb4", + "\xed\x8a\x80", "\xed\x93\x8c", "\xed\x9c\x98" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185b1(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185b1_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185b2_table_e184[] = { + "\xea\xb7\x9c", "\xeb\x80\xa8", "\xeb\x89\xb4", "\xeb\x93\x80", "\xeb\x9c\x8c", "\xeb\xa5\x98", "\xeb\xae\xa4", "\xeb\xb7\xb0", + "\xec\x80\xbc", "\xec\x8a\x88", "\xec\x93\x94", "\xec\x9c\xa0", "\xec\xa5\xac", "\xec\xae\xb8", "\xec\xb8\x84", "\xed\x81\x90", + "\xed\x8a\x9c", "\xed\x93\xa8", "\xed\x9c\xb4" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185b2(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185b2_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185b3_table_e184[] = { + "\xea\xb7\xb8", "\xeb\x81\x84", "\xeb\x8a\x90", "\xeb\x93\x9c", "\xeb\x9c\xa8", "\xeb\xa5\xb4", "\xeb\xaf\x80", "\xeb\xb8\x8c", + "\xec\x81\x98", "\xec\x8a\xa4", "\xec\x93\xb0", "\xec\x9c\xbc", "\xec\xa6\x88", "\xec\xaf\x94", "\xec\xb8\xa0", "\xed\x81\xac", + "\xed\x8a\xb8", "\xed\x94\x84", "\xed\x9d\x90" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185b3(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185b3_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185b4_table_e184[] = { + "\xea\xb8\x94", "\xeb\x81\xa0", "\xeb\x8a\xac", "\xeb\x93\xb8", "\xeb\x9d\x84", "\xeb\xa6\x90", "\xeb\xaf\x9c", "\xeb\xb8\xa8", + "\xec\x81\xb4", "\xec\x8b\x80", "\xec\x94\x8c", "\xec\x9d\x98", "\xec\xa6\xa4", "\xec\xaf\xb0", "\xec\xb8\xbc", "\xed\x82\x88", + "\xed\x8b\x94", "\xed\x94\xa0", "\xed\x9d\xac" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185b4(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185b4_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +static const char *grn_nfkc50_compose_prefix_e185b5_table_e184[] = { + "\xea\xb8\xb0", "\xeb\x81\xbc", "\xeb\x8b\x88", "\xeb\x94\x94", "\xeb\x9d\xa0", "\xeb\xa6\xac", "\xeb\xaf\xb8", "\xeb\xb9\x84", + "\xec\x82\x90", "\xec\x8b\x9c", "\xec\x94\xa8", "\xec\x9d\xb4", "\xec\xa7\x80", "\xec\xb0\x8c", "\xec\xb9\x98", "\xed\x82\xa4", + "\xed\x8b\xb0", "\xed\x94\xbc", "\xed\x9e\x88" +}; + +static inline const char * +grn_nfkc50_compose_prefix_e185b5(const unsigned char *utf8) +{ + { + switch (utf8[0]) { + case 0xe1 : + switch (utf8[1]) { + case 0x84 : + if (utf8[2] >= 0x80 && + utf8[2] <= 0x92) { + return grn_nfkc50_compose_prefix_e185b5_table_e184[utf8[2] - 0x80]; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +const char * +grn_nfkc50_compose(const unsigned char *prefix_utf8, const unsigned char *suffix_utf8) +{ + { + switch (suffix_utf8[0]) { + case 0xcc : + switch (suffix_utf8[1]) { + case 0x80 : + return grn_nfkc50_compose_prefix_cc80(prefix_utf8); + case 0x81 : + return grn_nfkc50_compose_prefix_cc81(prefix_utf8); + case 0x82 : + return grn_nfkc50_compose_prefix_cc82(prefix_utf8); + case 0x83 : + return grn_nfkc50_compose_prefix_cc83(prefix_utf8); + case 0x88 : + return grn_nfkc50_compose_prefix_cc88(prefix_utf8); + case 0x8a : + return grn_nfkc50_compose_prefix_cc8a(prefix_utf8); + case 0xa7 : + return grn_nfkc50_compose_prefix_cca7(prefix_utf8); + case 0x84 : + return grn_nfkc50_compose_prefix_cc84(prefix_utf8); + case 0x86 : + return grn_nfkc50_compose_prefix_cc86(prefix_utf8); + case 0xa8 : + return grn_nfkc50_compose_prefix_cca8(prefix_utf8); + case 0x87 : + return grn_nfkc50_compose_prefix_cc87(prefix_utf8); + case 0x8c : + return grn_nfkc50_compose_prefix_cc8c(prefix_utf8); + case 0x8b : + return grn_nfkc50_compose_prefix_cc8b(prefix_utf8); + case 0x9b : + return grn_nfkc50_compose_prefix_cc9b(prefix_utf8); + case 0x8f : + return grn_nfkc50_compose_prefix_cc8f(prefix_utf8); + case 0x91 : + return grn_nfkc50_compose_prefix_cc91(prefix_utf8); + case 0xa6 : + return grn_nfkc50_compose_prefix_cca6(prefix_utf8); + case 0xa5 : + return grn_nfkc50_compose_prefix_cca5(prefix_utf8); + case 0xa3 : + return grn_nfkc50_compose_prefix_cca3(prefix_utf8); + case 0xb1 : + return grn_nfkc50_compose_prefix_ccb1(prefix_utf8); + case 0xad : + return grn_nfkc50_compose_prefix_ccad(prefix_utf8); + case 0xb0 : + return grn_nfkc50_compose_prefix_ccb0(prefix_utf8); + case 0xae : + return grn_nfkc50_compose_prefix_ccae(prefix_utf8); + case 0xa4 : + return grn_nfkc50_compose_prefix_cca4(prefix_utf8); + case 0x89 : + return grn_nfkc50_compose_prefix_cc89(prefix_utf8); + case 0x93 : + return grn_nfkc50_compose_prefix_cc93(prefix_utf8); + case 0x94 : + return grn_nfkc50_compose_prefix_cc94(prefix_utf8); + case 0xb8 : + return grn_nfkc50_compose_prefix_ccb8(prefix_utf8); + default : + return NULL; + } + break; + case 0xcd : + switch (suffix_utf8[1]) { + case 0x82 : + return grn_nfkc50_compose_prefix_cd82(prefix_utf8); + case 0x85 : + return grn_nfkc50_compose_prefix_cd85(prefix_utf8); + default : + return NULL; + } + break; + case 0xd9 : + switch (suffix_utf8[1]) { + case 0x93 : + return grn_nfkc50_compose_prefix_d993(prefix_utf8); + case 0x94 : + return grn_nfkc50_compose_prefix_d994(prefix_utf8); + case 0x95 : + return grn_nfkc50_compose_prefix_d995(prefix_utf8); + default : + return NULL; + } + break; + case 0xe0 : + switch (suffix_utf8[1]) { + case 0xa4 : + switch (suffix_utf8[2]) { + case 0xbc : + return grn_nfkc50_compose_prefix_e0a4bc(prefix_utf8); + default : + return NULL; + } + break; + case 0xa6 : + switch (suffix_utf8[2]) { + case 0xbe : + return grn_nfkc50_compose_prefix_e0a6be(prefix_utf8); + default : + return NULL; + } + break; + case 0xa7 : + switch (suffix_utf8[2]) { + case 0x97 : + return grn_nfkc50_compose_prefix_e0a797(prefix_utf8); + default : + return NULL; + } + break; + case 0xac : + switch (suffix_utf8[2]) { + case 0xbe : + return grn_nfkc50_compose_prefix_e0acbe(prefix_utf8); + default : + return NULL; + } + break; + case 0xad : + switch (suffix_utf8[2]) { + case 0x96 : + return grn_nfkc50_compose_prefix_e0ad96(prefix_utf8); + case 0x97 : + return grn_nfkc50_compose_prefix_e0ad97(prefix_utf8); + default : + return NULL; + } + break; + case 0xae : + switch (suffix_utf8[2]) { + case 0xbe : + return grn_nfkc50_compose_prefix_e0aebe(prefix_utf8); + default : + return NULL; + } + break; + case 0xaf : + switch (suffix_utf8[2]) { + case 0x97 : + return grn_nfkc50_compose_prefix_e0af97(prefix_utf8); + default : + return NULL; + } + break; + case 0xb1 : + switch (suffix_utf8[2]) { + case 0x96 : + return grn_nfkc50_compose_prefix_e0b196(prefix_utf8); + default : + return NULL; + } + break; + case 0xb3 : + switch (suffix_utf8[2]) { + case 0x95 : + return grn_nfkc50_compose_prefix_e0b395(prefix_utf8); + case 0x96 : + return grn_nfkc50_compose_prefix_e0b396(prefix_utf8); + case 0x82 : + return grn_nfkc50_compose_prefix_e0b382(prefix_utf8); + default : + return NULL; + } + break; + case 0xb4 : + switch (suffix_utf8[2]) { + case 0xbe : + return grn_nfkc50_compose_prefix_e0b4be(prefix_utf8); + default : + return NULL; + } + break; + case 0xb5 : + switch (suffix_utf8[2]) { + case 0x97 : + return grn_nfkc50_compose_prefix_e0b597(prefix_utf8); + default : + return NULL; + } + break; + case 0xb7 : + switch (suffix_utf8[2]) { + case 0x8a : + return grn_nfkc50_compose_prefix_e0b78a(prefix_utf8); + case 0x8f : + return grn_nfkc50_compose_prefix_e0b78f(prefix_utf8); + case 0x9f : + return grn_nfkc50_compose_prefix_e0b79f(prefix_utf8); + default : + return NULL; + } + break; + default : + break; + } + break; + case 0xe1 : + switch (suffix_utf8[1]) { + case 0x80 : + switch (suffix_utf8[2]) { + case 0xae : + return grn_nfkc50_compose_prefix_e180ae(prefix_utf8); + default : + return NULL; + } + break; + case 0x85 : + switch (suffix_utf8[2]) { + case 0xa1 : + return grn_nfkc50_compose_prefix_e185a1(prefix_utf8); + case 0xa2 : + return grn_nfkc50_compose_prefix_e185a2(prefix_utf8); + case 0xa3 : + return grn_nfkc50_compose_prefix_e185a3(prefix_utf8); + case 0xa4 : + return grn_nfkc50_compose_prefix_e185a4(prefix_utf8); + case 0xa5 : + return grn_nfkc50_compose_prefix_e185a5(prefix_utf8); + case 0xa6 : + return grn_nfkc50_compose_prefix_e185a6(prefix_utf8); + case 0xa7 : + return grn_nfkc50_compose_prefix_e185a7(prefix_utf8); + case 0xa8 : + return grn_nfkc50_compose_prefix_e185a8(prefix_utf8); + case 0xa9 : + return grn_nfkc50_compose_prefix_e185a9(prefix_utf8); + case 0xaa : + return grn_nfkc50_compose_prefix_e185aa(prefix_utf8); + case 0xab : + return grn_nfkc50_compose_prefix_e185ab(prefix_utf8); + case 0xac : + return grn_nfkc50_compose_prefix_e185ac(prefix_utf8); + case 0xad : + return grn_nfkc50_compose_prefix_e185ad(prefix_utf8); + case 0xae : + return grn_nfkc50_compose_prefix_e185ae(prefix_utf8); + case 0xaf : + return grn_nfkc50_compose_prefix_e185af(prefix_utf8); + case 0xb0 : + return grn_nfkc50_compose_prefix_e185b0(prefix_utf8); + case 0xb1 : + return grn_nfkc50_compose_prefix_e185b1(prefix_utf8); + case 0xb2 : + return grn_nfkc50_compose_prefix_e185b2(prefix_utf8); + case 0xb3 : + return grn_nfkc50_compose_prefix_e185b3(prefix_utf8); + case 0xb4 : + return grn_nfkc50_compose_prefix_e185b4(prefix_utf8); + case 0xb5 : + return grn_nfkc50_compose_prefix_e185b5(prefix_utf8); + default : + return NULL; + } + break; + case 0x86 : + switch (suffix_utf8[2]) { + case 0xa8 : + return grn_nfkc50_compose_prefix_e186a8(prefix_utf8); + case 0xa9 : + return grn_nfkc50_compose_prefix_e186a9(prefix_utf8); + case 0xaa : + return grn_nfkc50_compose_prefix_e186aa(prefix_utf8); + case 0xab : + return grn_nfkc50_compose_prefix_e186ab(prefix_utf8); + case 0xac : + return grn_nfkc50_compose_prefix_e186ac(prefix_utf8); + case 0xad : + return grn_nfkc50_compose_prefix_e186ad(prefix_utf8); + case 0xae : + return grn_nfkc50_compose_prefix_e186ae(prefix_utf8); + case 0xaf : + return grn_nfkc50_compose_prefix_e186af(prefix_utf8); + case 0xb0 : + return grn_nfkc50_compose_prefix_e186b0(prefix_utf8); + case 0xb1 : + return grn_nfkc50_compose_prefix_e186b1(prefix_utf8); + case 0xb2 : + return grn_nfkc50_compose_prefix_e186b2(prefix_utf8); + case 0xb3 : + return grn_nfkc50_compose_prefix_e186b3(prefix_utf8); + case 0xb4 : + return grn_nfkc50_compose_prefix_e186b4(prefix_utf8); + case 0xb5 : + return grn_nfkc50_compose_prefix_e186b5(prefix_utf8); + case 0xb6 : + return grn_nfkc50_compose_prefix_e186b6(prefix_utf8); + case 0xb7 : + return grn_nfkc50_compose_prefix_e186b7(prefix_utf8); + case 0xb8 : + return grn_nfkc50_compose_prefix_e186b8(prefix_utf8); + case 0xb9 : + return grn_nfkc50_compose_prefix_e186b9(prefix_utf8); + case 0xba : + return grn_nfkc50_compose_prefix_e186ba(prefix_utf8); + case 0xbb : + return grn_nfkc50_compose_prefix_e186bb(prefix_utf8); + case 0xbc : + return grn_nfkc50_compose_prefix_e186bc(prefix_utf8); + case 0xbd : + return grn_nfkc50_compose_prefix_e186bd(prefix_utf8); + case 0xbe : + return grn_nfkc50_compose_prefix_e186be(prefix_utf8); + case 0xbf : + return grn_nfkc50_compose_prefix_e186bf(prefix_utf8); + default : + return NULL; + } + break; + case 0x87 : + switch (suffix_utf8[2]) { + case 0x80 : + return grn_nfkc50_compose_prefix_e18780(prefix_utf8); + case 0x81 : + return grn_nfkc50_compose_prefix_e18781(prefix_utf8); + case 0x82 : + return grn_nfkc50_compose_prefix_e18782(prefix_utf8); + default : + return NULL; + } + break; + case 0xac : + switch (suffix_utf8[2]) { + case 0xb5 : + return grn_nfkc50_compose_prefix_e1acb5(prefix_utf8); + default : + return NULL; + } + break; + default : + break; + } + break; + case 0xe3 : + switch (suffix_utf8[1]) { + case 0x82 : + switch (suffix_utf8[2]) { + case 0x99 : + return grn_nfkc50_compose_prefix_e38299(prefix_utf8); + case 0x9a : + return grn_nfkc50_compose_prefix_e3829a(prefix_utf8); + default : + return NULL; + } + break; + default : + break; + } + break; + default : + break; + } + } + + return NULL; +} + +#endif /* GRN_WITH_NFKC */ + diff --git a/storage/mroonga/vendor/groonga/lib/normalizer.c b/storage/mroonga/vendor/groonga/lib/normalizer.c new file mode 100644 index 00000000..7e69d684 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/normalizer.c @@ -0,0 +1,1193 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include + +#include "grn_normalizer.h" +#include "grn_string.h" +#include "grn_nfkc.h" +#include +#include + +grn_rc +grn_normalizer_register(grn_ctx *ctx, + const char *name_ptr, + int name_length, + grn_proc_func *init, + grn_proc_func *next, + grn_proc_func *fin) +{ + grn_expr_var vars[] = { + { NULL, 0 } + }; + GRN_PTR_INIT(&vars[0].value, 0, GRN_ID_NIL); + + if (name_length < 0) { + name_length = strlen(name_ptr); + } + + { + grn_obj * const normalizer = grn_proc_create(ctx, + name_ptr, name_length, + GRN_PROC_NORMALIZER, + init, next, fin, + sizeof(*vars) / sizeof(vars), + vars); + if (!normalizer) { + GRN_PLUGIN_ERROR(ctx, GRN_NORMALIZER_ERROR, + "[normalizer] failed to register normalizer: <%.*s>", + name_length, name_ptr); + return ctx->rc; + } + } + return GRN_SUCCESS; +} + +grn_rc +grn_normalizer_init(void) +{ + return GRN_SUCCESS; +} + +grn_rc +grn_normalizer_fin(void) +{ + return GRN_SUCCESS; +} + +static unsigned char symbol[] = { + ',', '.', 0, ':', ';', '?', '!', 0, 0, 0, '`', 0, '^', '~', '_', 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, '-', '-', '/', '\\', 0, 0, '|', 0, 0, 0, '\'', 0, + '"', '(', ')', 0, 0, '[', ']', '{', '}', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '+', '-', 0, 0, 0, '=', 0, '<', '>', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '$', 0, 0, '%', '#', '&', '*', '@', 0, 0, 0, 0, 0, 0, 0, 0 +}; + +inline static grn_obj * +eucjp_normalize(grn_ctx *ctx, grn_string *nstr) +{ + static uint16_t hankana[] = { + 0xa1a1, 0xa1a3, 0xa1d6, 0xa1d7, 0xa1a2, 0xa1a6, 0xa5f2, 0xa5a1, 0xa5a3, + 0xa5a5, 0xa5a7, 0xa5a9, 0xa5e3, 0xa5e5, 0xa5e7, 0xa5c3, 0xa1bc, 0xa5a2, + 0xa5a4, 0xa5a6, 0xa5a8, 0xa5aa, 0xa5ab, 0xa5ad, 0xa5af, 0xa5b1, 0xa5b3, + 0xa5b5, 0xa5b7, 0xa5b9, 0xa5bb, 0xa5bd, 0xa5bf, 0xa5c1, 0xa5c4, 0xa5c6, + 0xa5c8, 0xa5ca, 0xa5cb, 0xa5cc, 0xa5cd, 0xa5ce, 0xa5cf, 0xa5d2, 0xa5d5, + 0xa5d8, 0xa5db, 0xa5de, 0xa5df, 0xa5e0, 0xa5e1, 0xa5e2, 0xa5e4, 0xa5e6, + 0xa5e8, 0xa5e9, 0xa5ea, 0xa5eb, 0xa5ec, 0xa5ed, 0xa5ef, 0xa5f3, 0xa1ab, + 0xa1eb + }; + static unsigned char dakuten[] = { + 0xf4, 0, 0, 0, 0, 0xac, 0, 0xae, 0, 0xb0, 0, 0xb2, 0, 0xb4, 0, 0xb6, 0, + 0xb8, 0, 0xba, 0, 0xbc, 0, 0xbe, 0, 0xc0, 0, 0xc2, 0, 0, 0xc5, 0, 0xc7, + 0, 0xc9, 0, 0, 0, 0, 0, 0, 0xd0, 0, 0, 0xd3, 0, 0, 0xd6, 0, 0, 0xd9, 0, + 0, 0xdc + }; + static unsigned char handaku[] = { + 0xd1, 0, 0, 0xd4, 0, 0, 0xd7, 0, 0, 0xda, 0, 0, 0xdd + }; + int16_t *ch; + const unsigned char *s, *s_, *e; + unsigned char *d, *d0, *d_, b; + uint_least8_t *cp, *ctypes, ctype; + size_t size = nstr->original_length_in_bytes, length = 0; + int removeblankp = nstr->flags & GRN_STRING_REMOVE_BLANK; + if (!(nstr->normalized = GRN_MALLOC(size * 2 + 1))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][eucjp] failed to allocate normalized text space"); + return NULL; + } + d0 = (unsigned char *) nstr->normalized; + if (nstr->flags & GRN_STRING_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * 2 * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->normalized); + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][eucjp] failed to allocate checks space"); + return NULL; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STRING_WITH_TYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->normalized); + nstr->checks = NULL; + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][eucjp] failed to allocate character types space"); + return NULL; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->original + size; + for (s = s_ = (unsigned char *) nstr->original, d = d_ = d0; s < e; s++) { + if ((*s & 0x80)) { + if (((s + 1) < e) && (*(s + 1) & 0x80)) { + unsigned char c1 = *s++, c2 = *s, c3 = 0; + switch (c1 >> 4) { + case 0x08 : + if (c1 == 0x8e && 0xa0 <= c2 && c2 <= 0xdf) { + uint16_t c = hankana[c2 - 0xa0]; + switch (c) { + case 0xa1ab : + if (d > d0 + 1 && d[-2] == 0xa5 + && 0xa6 <= d[-1] && d[-1] <= 0xdb && (b = dakuten[d[-1] - 0xa6])) { + *(d - 1) = b; + if (ch) { ch[-1] += 2; s_ += 2; } + continue; + } else { + *d++ = c >> 8; *d = c & 0xff; + } + break; + case 0xa1eb : + if (d > d0 + 1 && d[-2] == 0xa5 + && 0xcf <= d[-1] && d[-1] <= 0xdb && (b = handaku[d[-1] - 0xcf])) { + *(d - 1) = b; + if (ch) { ch[-1] += 2; s_ += 2; } + continue; + } else { + *d++ = c >> 8; *d = c & 0xff; + } + break; + default : + *d++ = c >> 8; *d = c & 0xff; + break; + } + ctype = GRN_CHAR_KATAKANA; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + } + break; + case 0x09 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + break; + case 0x0a : + switch (c1 & 0x0f) { + case 1 : + switch (c2) { + case 0xbc : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KATAKANA; + break; + case 0xb9 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KANJI; + break; + case 0xa1 : + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_CHAR_BLANK|GRN_CHAR_SYMBOL; + } + break; + default : + if (c2 >= 0xa4 && (c3 = symbol[c2 - 0xa4])) { + *d = c3; + ctype = GRN_CHAR_SYMBOL; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + } + break; + } + break; + case 2 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_SYMBOL; + break; + case 3 : + c3 = c2 - 0x80; + if ('a' <= c3 && c3 <= 'z') { + ctype = GRN_CHAR_ALPHA; + *d = c3; + } else if ('A' <= c3 && c3 <= 'Z') { + ctype = GRN_CHAR_ALPHA; + *d = c3 + 0x20; + } else if ('0' <= c3 && c3 <= '9') { + ctype = GRN_CHAR_DIGIT; + *d = c3; + } else { + ctype = GRN_CHAR_OTHERS; + *d++ = c1; *d = c2; + } + break; + case 4 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_HIRAGANA; + break; + case 5 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KATAKANA; + break; + case 6 : + case 7 : + case 8 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_SYMBOL; + break; + default : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + break; + } + break; + default : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KANJI; + break; + } + } else { + /* skip invalid character */ + continue; + } + } else { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_CHAR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->n_characters = length; + nstr->normalized_length_in_bytes = (size_t)(d - (unsigned char *)nstr->normalized); + return NULL; +} + +inline static grn_obj * +sjis_normalize(grn_ctx *ctx, grn_string *nstr) +{ + static uint16_t hankana[] = { + 0x8140, 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x8392, 0x8340, 0x8342, + 0x8344, 0x8346, 0x8348, 0x8383, 0x8385, 0x8387, 0x8362, 0x815b, 0x8341, + 0x8343, 0x8345, 0x8347, 0x8349, 0x834a, 0x834c, 0x834e, 0x8350, 0x8352, + 0x8354, 0x8356, 0x8358, 0x835a, 0x835c, 0x835e, 0x8360, 0x8363, 0x8365, + 0x8367, 0x8369, 0x836a, 0x836b, 0x836c, 0x836d, 0x836e, 0x8371, 0x8374, + 0x8377, 0x837a, 0x837d, 0x837e, 0x8380, 0x8381, 0x8382, 0x8384, 0x8386, + 0x8388, 0x8389, 0x838a, 0x838b, 0x838c, 0x838d, 0x838f, 0x8393, 0x814a, + 0x814b + }; + static unsigned char dakuten[] = { + 0x94, 0, 0, 0, 0, 0x4b, 0, 0x4d, 0, 0x4f, 0, 0x51, 0, 0x53, 0, 0x55, 0, + 0x57, 0, 0x59, 0, 0x5b, 0, 0x5d, 0, 0x5f, 0, 0x61, 0, 0, 0x64, 0, 0x66, + 0, 0x68, 0, 0, 0, 0, 0, 0, 0x6f, 0, 0, 0x72, 0, 0, 0x75, 0, 0, 0x78, 0, + 0, 0x7b + }; + static unsigned char handaku[] = { + 0x70, 0, 0, 0x73, 0, 0, 0x76, 0, 0, 0x79, 0, 0, 0x7c + }; + int16_t *ch; + const unsigned char *s, *s_; + unsigned char *d, *d0, *d_, b, *e; + uint_least8_t *cp, *ctypes, ctype; + size_t size = nstr->original_length_in_bytes, length = 0; + int removeblankp = nstr->flags & GRN_STRING_REMOVE_BLANK; + if (!(nstr->normalized = GRN_MALLOC(size * 2 + 1))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][sjis] failed to allocate normalized text space"); + return NULL; + } + d0 = (unsigned char *) nstr->normalized; + if (nstr->flags & GRN_STRING_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * 2 * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->normalized); + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][sjis] failed to allocate checks space"); + return NULL; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STRING_WITH_TYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->normalized); + nstr->checks = NULL; + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][sjis] failed to allocate character types space"); + return NULL; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->original + size; + for (s = s_ = (unsigned char *) nstr->original, d = d_ = d0; s < e; s++) { + if ((*s & 0x80)) { + if (0xa0 <= *s && *s <= 0xdf) { + uint16_t c = hankana[*s - 0xa0]; + switch (c) { + case 0x814a : + if (d > d0 + 1 && d[-2] == 0x83 + && 0x45 <= d[-1] && d[-1] <= 0x7a && (b = dakuten[d[-1] - 0x45])) { + *(d - 1) = b; + if (ch) { ch[-1]++; s_++; } + continue; + } else { + *d++ = c >> 8; *d = c & 0xff; + } + break; + case 0x814b : + if (d > d0 + 1 && d[-2] == 0x83 + && 0x6e <= d[-1] && d[-1] <= 0x7a && (b = handaku[d[-1] - 0x6e])) { + *(d - 1) = b; + if (ch) { ch[-1]++; s_++; } + continue; + } else { + *d++ = c >> 8; *d = c & 0xff; + } + break; + default : + *d++ = c >> 8; *d = c & 0xff; + break; + } + ctype = GRN_CHAR_KATAKANA; + } else { + if ((s + 1) < e && 0x40 <= *(s + 1) && *(s + 1) <= 0xfc) { + unsigned char c1 = *s++, c2 = *s, c3 = 0; + if (0x81 <= c1 && c1 <= 0x87) { + switch (c1 & 0x0f) { + case 1 : + switch (c2) { + case 0x5b : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KATAKANA; + break; + case 0x58 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KANJI; + break; + case 0x40 : + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_CHAR_BLANK|GRN_CHAR_SYMBOL; + } + break; + default : + if (0x43 <= c2 && c2 <= 0x7e && (c3 = symbol[c2 - 0x43])) { + *d = c3; + ctype = GRN_CHAR_SYMBOL; + } else if (0x7f <= c2 && c2 <= 0x97 && (c3 = symbol[c2 - 0x44])) { + *d = c3; + ctype = GRN_CHAR_SYMBOL; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + } + break; + } + break; + case 2 : + c3 = c2 - 0x1f; + if (0x4f <= c2 && c2 <= 0x58) { + ctype = GRN_CHAR_DIGIT; + *d = c2 - 0x1f; + } else if (0x60 <= c2 && c2 <= 0x79) { + ctype = GRN_CHAR_ALPHA; + *d = c2 + 0x01; + } else if (0x81 <= c2 && c2 <= 0x9a) { + ctype = GRN_CHAR_ALPHA; + *d = c2 - 0x20; + } else if (0x9f <= c2 && c2 <= 0xf1) { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_HIRAGANA; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + } + break; + case 3 : + if (0x40 <= c2 && c2 <= 0x96) { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KATAKANA; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 4 : + case 7 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_SYMBOL; + break; + default : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + break; + } + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KANJI; + } + } else { + /* skip invalid character */ + continue; + } + } + } else { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_CHAR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->n_characters = length; + nstr->normalized_length_in_bytes = (size_t)(d - (unsigned char *)nstr->normalized); + return NULL; +} + +#ifdef GRN_WITH_NFKC +static inline int +grn_str_charlen_utf8(grn_ctx *ctx, const unsigned char *str, const unsigned char *end) +{ + /* MEMO: This function allows non-null-terminated string as str. */ + /* But requires the end of string. */ + const unsigned char *p = str; + if (end <= p || !*p) { return 0; } + if (*p & 0x80) { + int b, w; + int size; + int i; + for (b = 0x40, w = 0; b && (*p & b); b >>= 1, w++); + if (!w) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "invalid utf8 string: the first bit is 0x80: <%.*s>: <%.*s>", + (int)(end - p), p, + (int)(end - str), str); + return 0; + } + size = w + 1; + for (i = 1; i < size; i++) { + if (++p >= end) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "invalid utf8 string: too short: " + "%d byte is required but %d byte is given: <%.*s>", + size, i, + (int)(end - str), str); + return 0; + } + if (!*p) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "invalid utf8 string: NULL character is found: <%.*s>", + (int)(end - str), str); + return 0; + } + if ((*p & 0xc0) != 0x80) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "invalid utf8 string: 0x80 is not allowed: <%.*s>: <%.*s>", + (int)(end - p), p, + (int)(end - str), str); + return 0; + } + } + return size; + } else { + return 1; + } + return 0; +} + +inline static grn_obj * +utf8_normalize(grn_ctx *ctx, grn_string *nstr) +{ + int16_t *ch; + const unsigned char *s, *s_, *s__ = NULL, *p, *p2, *pe, *e; + unsigned char *d, *d_, *de; + uint_least8_t *cp; + size_t length = 0, ls, lp, size = nstr->original_length_in_bytes, ds = size * 3; + int removeblankp = nstr->flags & GRN_STRING_REMOVE_BLANK; + grn_bool remove_tokenized_delimiter_p = + nstr->flags & GRN_STRING_REMOVE_TOKENIZED_DELIMITER; + if (!(nstr->normalized = GRN_MALLOC(ds + 1))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][utf8] failed to allocate normalized text space"); + return NULL; + } + if (nstr->flags & GRN_STRING_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(ds * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->normalized); + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][utf8] failed to allocate checks space"); + return NULL; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STRING_WITH_TYPES) { + if (!(nstr->ctypes = GRN_MALLOC(ds + 1))) { + if (nstr->checks) { GRN_FREE(nstr->checks); nstr->checks = NULL; } + GRN_FREE(nstr->normalized); nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][utf8] failed to allocate character types space"); + return NULL; + } + } + cp = nstr->ctypes; + d = (unsigned char *)nstr->normalized; + de = d + ds; + d_ = NULL; + e = (unsigned char *)nstr->original + size; + for (s = s_ = (unsigned char *)nstr->original; ; s += ls) { + if (!(ls = grn_str_charlen_utf8(ctx, s, e))) { + break; + } + if (remove_tokenized_delimiter_p && + grn_tokenizer_is_tokenized_delimiter(ctx, (const char *)s, ls, + GRN_ENC_UTF8)) { + continue; + } + if ((p = (unsigned char *)grn_nfkc_decompose(s))) { + pe = p + strlen((char *)p); + } else { + p = s; + pe = p + ls; + } + if (d_ && (p2 = (unsigned char *)grn_nfkc_compose(d_, p))) { + p = p2; + pe = p + strlen((char *)p); + if (cp) { cp--; } + if (ch) { + ch -= (d - d_); + if (ch[0] >= 0) { + s_ = s__; + } + } + d = d_; + length--; + } + for (; ; p += lp) { + if (!(lp = grn_str_charlen_utf8(ctx, p, pe))) { + break; + } + if ((*p == ' ' && removeblankp) || *p < 0x20 /* skip unprintable ascii */ ) { + if (cp > nstr->ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + } else { + if (de <= d + lp) { + unsigned char *normalized; + ds += (ds >> 1) + lp; + if (!(normalized = GRN_REALLOC(nstr->normalized, ds + 1))) { + if (nstr->ctypes) { GRN_FREE(nstr->ctypes); nstr->ctypes = NULL; } + if (nstr->checks) { GRN_FREE(nstr->checks); nstr->checks = NULL; } + GRN_FREE(nstr->normalized); nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][utf8] failed to expand normalized text space"); + return NULL; + } + de = normalized + ds; + d = normalized + (d - (unsigned char *)nstr->normalized); + nstr->normalized = (char *)normalized; + if (ch) { + int16_t *checks; + if (!(checks = GRN_REALLOC(nstr->checks, ds * sizeof(int16_t) + 1))) { + if (nstr->ctypes) { GRN_FREE(nstr->ctypes); nstr->ctypes = NULL; } + GRN_FREE(nstr->checks); nstr->checks = NULL; + GRN_FREE(nstr->normalized); nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][utf8] failed to expand checks space"); + return NULL; + } + ch = checks + (ch - nstr->checks); + nstr->checks = checks; + } + if (cp) { + uint_least8_t *ctypes; + if (!(ctypes = GRN_REALLOC(nstr->ctypes, ds + 1))) { + GRN_FREE(nstr->ctypes); nstr->ctypes = NULL; + if (nstr->checks) { GRN_FREE(nstr->checks); nstr->checks = NULL; } + GRN_FREE(nstr->normalized); nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][utf8] failed to expand character types space"); + return NULL; + } + cp = ctypes + (cp - nstr->ctypes); + nstr->ctypes = ctypes; + } + } + grn_memcpy(d, p, lp); + d_ = d; + d += lp; + length++; + if (cp) { *cp++ = grn_nfkc_char_type(p); } + if (ch) { + size_t i; + if (s_ == s + ls) { + *ch++ = -1; + } else { + *ch++ = (int16_t)(s + ls - s_); + s__ = s_; + s_ = s + ls; + } + for (i = lp; i > 1; i--) { *ch++ = 0; } + } + } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->n_characters = length; + nstr->normalized_length_in_bytes = (size_t)(d - (unsigned char *)nstr->normalized); + return NULL; +} +#endif /* GRN_WITH_NFKC */ + +inline static grn_obj * +ascii_normalize(grn_ctx *ctx, grn_string *nstr) +{ + int16_t *ch; + const unsigned char *s, *s_, *e; + unsigned char *d, *d0, *d_; + uint_least8_t *cp, *ctypes, ctype; + size_t size = nstr->original_length_in_bytes, length = 0; + int removeblankp = nstr->flags & GRN_STRING_REMOVE_BLANK; + if (!(nstr->normalized = GRN_MALLOC(size + 1))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][ascii] failed to allocate normalized text space"); + return NULL; + } + d0 = (unsigned char *) nstr->normalized; + if (nstr->flags & GRN_STRING_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->normalized); + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][ascii] failed to allocate checks space"); + return NULL; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STRING_WITH_TYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->normalized); + nstr->checks = NULL; + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][ascii] failed to allocate character types space"); + return NULL; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->original + size; + for (s = s_ = (unsigned char *) nstr->original, d = d_ = d0; s < e; s++) { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_CHAR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->n_characters = length; + nstr->normalized_length_in_bytes = (size_t)(d - (unsigned char *)nstr->normalized); + return NULL; +} + +/* use cp1252 as latin1 */ +inline static grn_obj * +latin1_normalize(grn_ctx *ctx, grn_string *nstr) +{ + int16_t *ch; + const unsigned char *s, *s_, *e; + unsigned char *d, *d0, *d_; + uint_least8_t *cp, *ctypes, ctype; + size_t size = nstr->original_length_in_bytes, length = 0; + int removeblankp = nstr->flags & GRN_STRING_REMOVE_BLANK; + if (!(nstr->normalized = GRN_MALLOC(size + 1))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][latin1] failed to allocate normalized text space"); + return NULL; + } + d0 = (unsigned char *) nstr->normalized; + if (nstr->flags & GRN_STRING_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->normalized); + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][latin1] failed to allocate checks space"); + return NULL; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STRING_WITH_TYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->normalized); + nstr->checks = NULL; + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[normalizer][latin1] failed to allocate character types space"); + return NULL; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->original + size; + for (s = s_ = (unsigned char *) nstr->original, d = d_ = d0; s < e; s++) { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_CHAR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + case 8 : + if (c == 0x8a || c == 0x8c || c == 0x8e) { + *d = c + 0x10; + ctype = GRN_CHAR_ALPHA; + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 9 : + if (c == 0x9a || c == 0x9c || c == 0x9e || c == 0x9f) { + *d = (c == 0x9f) ? c + 0x60 : c; + ctype = GRN_CHAR_ALPHA; + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 0x0c : + *d = c + 0x20; + ctype = GRN_CHAR_ALPHA; + break; + case 0x0d : + *d = (c == 0xd7 || c == 0xdf) ? c : c + 0x20; + ctype = (c == 0xd7) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 0x0e : + *d = c; + ctype = GRN_CHAR_ALPHA; + break; + case 0x0f : + *d = c; + ctype = (c == 0xf7) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->n_characters = length; + nstr->normalized_length_in_bytes = (size_t)(d - (unsigned char *)nstr->normalized); + return NULL; +} + +inline static grn_obj * +koi8r_normalize(grn_ctx *ctx, grn_string *nstr) +{ + int16_t *ch; + const unsigned char *s, *s_, *e; + unsigned char *d, *d0, *d_; + uint_least8_t *cp, *ctypes, ctype; + size_t size = nstr->original_length_in_bytes, length = 0; + int removeblankp = nstr->flags & GRN_STRING_REMOVE_BLANK; + if (!(nstr->normalized = GRN_MALLOC(size + 1))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][koi8r] failed to allocate normalized text space"); + return NULL; + } + d0 = (unsigned char *) nstr->normalized; + if (nstr->flags & GRN_STRING_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->normalized); + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][koi8r] failed to allocate checks space"); + return NULL; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STRING_WITH_TYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->normalized); + nstr->checks = NULL; + nstr->normalized = NULL; + ERR(GRN_NO_MEMORY_AVAILABLE, + "[string][koi8r] failed to allocate character types space"); + return NULL; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->original + size; + for (s = s_ = (unsigned char *) nstr->original, d = d_ = d0; s < e; s++) { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_CHAR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_CHAR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + case 0x0a : + *d = c; + ctype = (c == 0xa3) ? GRN_CHAR_ALPHA : GRN_CHAR_OTHERS; + break; + case 0x0b : + if (c == 0xb3) { + *d = c - 0x10; + ctype = GRN_CHAR_ALPHA; + } else { + *d = c; + ctype = GRN_CHAR_OTHERS; + } + break; + case 0x0c : + case 0x0d : + *d = c; + ctype = GRN_CHAR_ALPHA; + break; + case 0x0e : + case 0x0f : + *d = c - 0x20; + ctype = GRN_CHAR_ALPHA; + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->n_characters = length; + nstr->normalized_length_in_bytes = (size_t)(d - (unsigned char *)nstr->normalized); + return NULL; +} + +static grn_obj * +auto_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_string *string = (grn_string *)(args[0]); + switch (string->encoding) { + case GRN_ENC_EUC_JP : + eucjp_normalize(ctx, string); + break; + case GRN_ENC_UTF8 : +#ifdef GRN_WITH_NFKC + utf8_normalize(ctx, string); +#else /* GRN_WITH_NFKC */ + ascii_normalize(ctx, string); +#endif /* GRN_WITH_NFKC */ + break; + case GRN_ENC_SJIS : + sjis_normalize(ctx, string); + break; + case GRN_ENC_LATIN1 : + latin1_normalize(ctx, string); + break; + case GRN_ENC_KOI8R : + koi8r_normalize(ctx, string); + break; + default : + ascii_normalize(ctx, string); + break; + } + return NULL; +} + +#ifdef GRN_WITH_NFKC +static grn_obj * +nfkc51_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_string *string = (grn_string *)(args[0]); + utf8_normalize(ctx, string); + return NULL; +} +#endif /* GRN_WITH_NFKC */ + +grn_rc +grn_normalizer_normalize(grn_ctx *ctx, grn_obj *normalizer, grn_obj *string) +{ + grn_rc rc; + int nargs = 0; + + grn_ctx_push(ctx, string); + nargs++; + rc = grn_proc_call(ctx, normalizer, nargs, NULL); + grn_ctx_pop(ctx); + + return rc; +} + +grn_rc +grn_db_init_builtin_normalizers(grn_ctx *ctx) +{ + const char *normalizer_nfkc51_name = "NormalizerNFKC51"; + + grn_normalizer_register(ctx, GRN_NORMALIZER_AUTO_NAME, -1, + NULL, auto_next, NULL); + +#ifdef GRN_WITH_NFKC + grn_normalizer_register(ctx, normalizer_nfkc51_name, -1, + NULL, nfkc51_next, NULL); +#else /* GRN_WITH_NFKC */ + grn_normalizer_register(ctx, normalizer_nfkc51_name, -1, + NULL, NULL, NULL); +#endif /* GRN_WITH_NFKC */ +/* + grn_normalizer_register(ctx, "NormalizerUCA", -1, + NULL, uca_next, NULL); +*/ + + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/obj.c b/storage/mroonga/vendor/groonga/lib/obj.c new file mode 100644 index 00000000..8160daf5 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/obj.c @@ -0,0 +1,689 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_index_column.h" +#include "grn_pat.h" +#include "grn_dat.h" +#include "grn_ii.h" + +grn_bool +grn_obj_is_true(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return GRN_FALSE; + } + + switch (obj->header.type) { + case GRN_BULK : + switch (obj->header.domain) { + case GRN_DB_BOOL : + return GRN_BOOL_VALUE(obj); + break; + case GRN_DB_INT32 : + return GRN_INT32_VALUE(obj) != 0; + break; + case GRN_DB_UINT32 : + return GRN_UINT32_VALUE(obj) != 0; + break; + case GRN_DB_FLOAT : { + double float_value; + float_value = GRN_FLOAT_VALUE(obj); + return (float_value < -DBL_EPSILON || + DBL_EPSILON < float_value); + break; + } + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + return GRN_TEXT_LEN(obj) != 0; + break; + default : + return GRN_FALSE; + break; + } + break; + case GRN_VECTOR : + return GRN_TRUE; + break; + default : + return GRN_FALSE; + break; + } +} + +grn_bool +grn_obj_is_builtin(grn_ctx *ctx, grn_obj *obj) +{ + grn_id id; + + if (!obj) { return GRN_FALSE; } + + id = grn_obj_id(ctx, obj); + return grn_id_is_builtin(ctx, id); +} + +grn_bool +grn_obj_is_bulk(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return GRN_FALSE; + } + + return obj->header.type == GRN_BULK; +} + +grn_bool +grn_obj_is_text_family_bulk(grn_ctx *ctx, grn_obj *obj) +{ + if (!grn_obj_is_bulk(ctx, obj)) { + return GRN_FALSE; + } + + return GRN_TYPE_IS_TEXT_FAMILY(obj->header.domain); +} + +grn_bool +grn_obj_is_table(grn_ctx *ctx, grn_obj *obj) +{ + grn_bool is_table = GRN_FALSE; + + if (!obj) { + return GRN_FALSE; + } + + switch (obj->header.type) { + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + is_table = GRN_TRUE; + default : + break; + } + + return is_table; +} + +grn_bool +grn_obj_is_column(grn_ctx *ctx, grn_obj *obj) +{ + grn_bool is_column = GRN_FALSE; + + if (!obj) { + return GRN_FALSE; + } + + switch (obj->header.type) { + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + is_column = GRN_TRUE; + default : + break; + } + + return is_column; +} + +grn_bool +grn_obj_is_scalar_column(grn_ctx *ctx, grn_obj *obj) +{ + if (!grn_obj_is_column(ctx, obj)) { + return GRN_FALSE; + } + + return (obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_SCALAR; +} + +grn_bool +grn_obj_is_vector_column(grn_ctx *ctx, grn_obj *obj) +{ + if (!grn_obj_is_column(ctx, obj)) { + return GRN_FALSE; + } + + return ((obj->header.type == GRN_COLUMN_VAR_SIZE) && + ((obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == + GRN_OBJ_COLUMN_VECTOR)); +} + +grn_bool +grn_obj_is_weight_vector_column(grn_ctx *ctx, grn_obj *obj) +{ + if (!grn_obj_is_vector_column(ctx, obj)) { + return GRN_FALSE; + } + + return (obj->header.flags & GRN_OBJ_WITH_WEIGHT) == GRN_OBJ_WITH_WEIGHT; +} + +grn_bool +grn_obj_is_reference_column(grn_ctx *ctx, grn_obj *obj) +{ + grn_obj *range; + + if (!grn_obj_is_column(ctx, obj)) { + return GRN_FALSE; + } + + range = grn_ctx_at(ctx, grn_obj_get_range(ctx, obj)); + if (!range) { + return GRN_FALSE; + } + + switch (range->header.type) { + case GRN_TABLE_HASH_KEY: + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: + case GRN_TABLE_NO_KEY: + return GRN_TRUE; + default: + return GRN_FALSE; + } +} + +grn_bool +grn_obj_is_data_column(grn_ctx *ctx, grn_obj *obj) +{ + if (!grn_obj_is_column(ctx, obj)) { + return GRN_FALSE; + } + + return obj->header.type == GRN_COLUMN_FIX_SIZE || + obj->header.type == GRN_COLUMN_VAR_SIZE; +} + +grn_bool +grn_obj_is_index_column(grn_ctx *ctx, grn_obj *obj) +{ + if (!grn_obj_is_column(ctx, obj)) { + return GRN_FALSE; + } + + return obj->header.type == GRN_COLUMN_INDEX; +} + +grn_bool +grn_obj_is_accessor(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return GRN_FALSE; + } + + return obj->header.type == GRN_ACCESSOR; +} + +grn_bool +grn_obj_is_key_accessor(grn_ctx *ctx, grn_obj *obj) +{ + grn_accessor *accessor; + + if (!grn_obj_is_accessor(ctx, obj)) { + return GRN_FALSE; + } + + accessor = (grn_accessor *)obj; + if (accessor->next) { + return GRN_FALSE; + } + + return accessor->action == GRN_ACCESSOR_GET_KEY; +} + +grn_bool +grn_obj_is_type(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return GRN_FALSE; + } + + return obj->header.type == GRN_TYPE; +} + +grn_bool +grn_obj_is_text_family_type(grn_ctx *ctx, grn_obj *obj) +{ + if (!grn_obj_is_type(ctx, obj)) { + return GRN_FALSE; + } + + return GRN_TYPE_IS_TEXT_FAMILY(grn_obj_id(ctx, obj)); +} + +grn_bool +grn_obj_is_proc(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return GRN_FALSE; + } + + return obj->header.type == GRN_PROC; +} + +grn_bool +grn_obj_is_tokenizer_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->type == GRN_PROC_TOKENIZER; +} + +grn_bool +grn_obj_is_function_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->type == GRN_PROC_FUNCTION; +} + +grn_bool +grn_obj_is_selector_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_function_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->callbacks.function.selector != NULL; +} + +grn_bool +grn_obj_is_selector_only_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_selector_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->funcs[PROC_INIT] == NULL; +} + +grn_bool +grn_obj_is_normalizer_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->type == GRN_PROC_NORMALIZER; +} + +grn_bool +grn_obj_is_token_filter_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->type == GRN_PROC_TOKEN_FILTER; +} + +grn_bool +grn_obj_is_scorer_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->type == GRN_PROC_SCORER; +} + +grn_bool +grn_obj_is_window_function_proc(grn_ctx *ctx, grn_obj *obj) +{ + grn_proc *proc; + + if (!grn_obj_is_proc(ctx, obj)) { + return GRN_FALSE; + } + + proc = (grn_proc *)obj; + return proc->type == GRN_PROC_WINDOW_FUNCTION; +} + +grn_bool +grn_obj_is_expr(grn_ctx *ctx, grn_obj *obj) +{ + if (!obj) { + return GRN_FALSE; + } + + return obj->header.type == GRN_EXPR; +} + +static void +grn_db_reindex(grn_ctx *ctx, grn_obj *db) +{ + grn_table_cursor *cursor; + grn_id id; + + cursor = grn_table_cursor_open(ctx, db, + NULL, 0, NULL, 0, + 0, -1, + GRN_CURSOR_BY_ID); + if (!cursor) { + return; + } + + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_obj *object; + + object = grn_ctx_at(ctx, id); + if (!object) { + ERRCLR(ctx); + continue; + } + + switch (object->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + grn_obj_reindex(ctx, object); + break; + default: + break; + } + + grn_obj_unlink(ctx, object); + + if (ctx->rc != GRN_SUCCESS) { + break; + } + } + grn_table_cursor_close(ctx, cursor); +} + +static void +grn_table_reindex(grn_ctx *ctx, grn_obj *table) +{ + grn_hash *columns; + + columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); + if (!columns) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[table][reindex] failed to create a table to store columns"); + return; + } + + if (grn_table_columns(ctx, table, "", 0, (grn_obj *)columns) > 0) { + grn_id *key; + GRN_HASH_EACH(ctx, columns, id, &key, NULL, NULL, { + grn_obj *column = grn_ctx_at(ctx, *key); + if (column && column->header.type == GRN_COLUMN_INDEX) { + grn_obj_reindex(ctx, column); + } + }); + } + grn_hash_close(ctx, columns); +} + +static void +grn_data_column_reindex(grn_ctx *ctx, grn_obj *data_column) +{ + grn_hook *hooks; + + for (hooks = DB_OBJ(data_column)->hooks[GRN_HOOK_SET]; + hooks; + hooks = hooks->next) { + grn_obj_default_set_value_hook_data *data = (void *)GRN_NEXT_ADDR(hooks); + grn_obj *target = grn_ctx_at(ctx, data->target); + if (target->header.type != GRN_COLUMN_INDEX) { + continue; + } + grn_obj_reindex(ctx, target); + if (ctx->rc != GRN_SUCCESS) { + break; + } + } +} + +grn_rc +grn_obj_reindex(grn_ctx *ctx, grn_obj *obj) +{ + GRN_API_ENTER; + + if (!obj) { + ERR(GRN_INVALID_ARGUMENT, "[object][reindex] object must not be NULL"); + GRN_API_RETURN(ctx->rc); + } + + switch (obj->header.type) { + case GRN_DB : + grn_db_reindex(ctx, obj); + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + grn_table_reindex(ctx, obj); + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + grn_data_column_reindex(ctx, obj); + break; + case GRN_COLUMN_INDEX : + grn_index_column_rebuild(ctx, obj); + break; + default : + { + grn_obj type_name; + GRN_TEXT_INIT(&type_name, 0); + grn_inspect_type(ctx, &type_name, obj->header.type); + ERR(GRN_INVALID_ARGUMENT, + "[object][reindex] object must be TABLE_HASH_KEY, " + "TABLE_PAT_KEY, TABLE_DAT_KEY or COLUMN_INDEX: <%.*s>", + (int)GRN_TEXT_LEN(&type_name), + GRN_TEXT_VALUE(&type_name)); + GRN_OBJ_FIN(ctx, &type_name); + GRN_API_RETURN(ctx->rc); + } + break; + } + + GRN_API_RETURN(ctx->rc); +} + +const char * +grn_obj_type_to_string(uint8_t type) +{ + switch (type) { + case GRN_VOID : + return "void"; + case GRN_BULK : + return "bulk"; + case GRN_PTR : + return "ptr"; + case GRN_UVECTOR : + return "uvector"; + case GRN_PVECTOR : + return "pvector"; + case GRN_VECTOR : + return "vector"; + case GRN_MSG : + return "msg"; + case GRN_QUERY : + return "query"; + case GRN_ACCESSOR : + return "accessor"; + case GRN_SNIP : + return "snip"; + case GRN_PATSNIP : + return "patsnip"; + case GRN_STRING : + return "string"; + case GRN_CURSOR_TABLE_HASH_KEY : + return "cursor:table:hash_key"; + case GRN_CURSOR_TABLE_PAT_KEY : + return "cursor:table:pat_key"; + case GRN_CURSOR_TABLE_DAT_KEY : + return "cursor:table:dat_key"; + case GRN_CURSOR_TABLE_NO_KEY : + return "cursor:table:no_key"; + case GRN_CURSOR_COLUMN_INDEX : + return "cursor:column:index"; + case GRN_CURSOR_COLUMN_GEO_INDEX : + return "cursor:column:geo_index"; + case GRN_CURSOR_CONFIG : + return "cursor:config"; + case GRN_TYPE : + return "type"; + case GRN_PROC : + return "proc"; + case GRN_EXPR : + return "expr"; + case GRN_TABLE_HASH_KEY : + return "table:hash_key"; + case GRN_TABLE_PAT_KEY : + return "table:pat_key"; + case GRN_TABLE_DAT_KEY : + return "table:dat_key"; + case GRN_TABLE_NO_KEY : + return "table:no_key"; + case GRN_DB : + return "db"; + case GRN_COLUMN_FIX_SIZE : + return "column:fix_size"; + case GRN_COLUMN_VAR_SIZE : + return "column:var_size"; + case GRN_COLUMN_INDEX : + return "column:index"; + default : + return "unknown"; + } +} + +grn_bool +grn_obj_name_is_column(grn_ctx *ctx, const char *name, int name_len) +{ + if (!name) { + return GRN_FALSE; + } + + if (name_len < 0) { + name_len = strlen(name); + } + + return memchr(name, GRN_DB_DELIMITER, name_len) != NULL; +} + +grn_io * +grn_obj_get_io(grn_ctx *ctx, grn_obj *obj) +{ + grn_io *io = NULL; + + if (!obj) { + return NULL; + } + + if (obj->header.type == GRN_DB) { + obj = ((grn_db *)obj)->keys; + } + + switch (obj->header.type) { + case GRN_TABLE_PAT_KEY : + io = ((grn_pat *)obj)->io; + break; + case GRN_TABLE_DAT_KEY : + io = ((grn_dat *)obj)->io; + break; + case GRN_TABLE_HASH_KEY : + io = ((grn_hash *)obj)->io; + break; + case GRN_TABLE_NO_KEY : + io = ((grn_array *)obj)->io; + break; + case GRN_COLUMN_VAR_SIZE : + io = ((grn_ja *)obj)->io; + break; + case GRN_COLUMN_FIX_SIZE : + io = ((grn_ra *)obj)->io; + break; + case GRN_COLUMN_INDEX : + io = ((grn_ii *)obj)->seg; + break; + } + + return io; +} + +size_t +grn_obj_get_disk_usage(grn_ctx *ctx, grn_obj *obj) +{ + size_t usage = 0; + + GRN_API_ENTER; + + if (!obj) { + ERR(GRN_INVALID_ARGUMENT, "[object][disk-usage] object must not be NULL"); + GRN_API_RETURN(0); + } + + switch (obj->header.type) { + case GRN_DB : + { + grn_db *db = (grn_db *)obj; + usage = grn_obj_get_disk_usage(ctx, db->keys); + if (db->specs) { + usage += grn_obj_get_disk_usage(ctx, (grn_obj *)(db->specs)); + } + usage += grn_obj_get_disk_usage(ctx, (grn_obj *)(db->config)); + } + break; + case GRN_TABLE_DAT_KEY : + usage = grn_dat_get_disk_usage(ctx, (grn_dat *)obj); + break; + case GRN_COLUMN_INDEX : + usage = grn_ii_get_disk_usage(ctx, (grn_ii *)obj); + break; + default : + { + grn_io *io; + io = grn_obj_get_io(ctx, obj); + if (io) { + usage = grn_io_get_disk_usage(ctx, io); + } + } + break; + } + + GRN_API_RETURN(usage); +} diff --git a/storage/mroonga/vendor/groonga/lib/operator.c b/storage/mroonga/vendor/groonga/lib/operator.c new file mode 100644 index 00000000..1d371fe4 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/operator.c @@ -0,0 +1,1362 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_db.h" +#include "grn_str.h" +#include "grn_normalizer.h" + +#include + +#ifdef GRN_WITH_ONIGMO +# define GRN_SUPPORT_REGEXP +#endif + +#ifdef GRN_SUPPORT_REGEXP +# include +#endif + +static const char *operator_names[] = { + "push", + "pop", + "nop", + "call", + "intern", + "get_ref", + "get_value", + "and", + "and_not", + "or", + "assign", + "star_assign", + "slash_assign", + "mod_assign", + "plus_assign", + "minus_assign", + "shiftl_assign", + "shiftr_assign", + "shiftrr_assign", + "and_assign", + "xor_assign", + "or_assign", + "jump", + "cjump", + "comma", + "bitwise_or", + "bitwise_xor", + "bitwise_and", + "bitwise_not", + "equal", + "not_equal", + "less", + "greater", + "less_equal", + "greater_equal", + "in", + "match", + "near", + "near2", + "similar", + "term_extract", + "shiftl", + "shiftr", + "shiftrr", + "plus", + "minus", + "star", + "slash", + "mod", + "delete", + "incr", + "decr", + "incr_post", + "decr_post", + "not", + "adjust", + "exact", + "lcp", + "partial", + "unsplit", + "prefix", + "suffix", + "geo_distance1", + "geo_distance2", + "geo_distance3", + "geo_distance4", + "geo_withinp5", + "geo_withinp6", + "geo_withinp8", + "obj_search", + "expr_get_var", + "table_create", + "table_select", + "table_sort", + "table_group", + "json_put", + "get_member", + "regexp", + "fuzzy" +}; + +#define GRN_OP_LAST GRN_OP_FUZZY + +const char * +grn_operator_to_string(grn_operator op) +{ + if (op <= GRN_OP_LAST) { + return operator_names[op]; + } else { + return "unknown"; + } +} + +grn_operator_exec_func * +grn_operator_to_exec_func(grn_operator op) +{ + grn_operator_exec_func *func = NULL; + + switch (op) { + case GRN_OP_EQUAL : + func = grn_operator_exec_equal; + break; + case GRN_OP_NOT_EQUAL : + func = grn_operator_exec_not_equal; + break; + case GRN_OP_LESS : + func = grn_operator_exec_less; + break; + case GRN_OP_GREATER : + func = grn_operator_exec_greater; + break; + case GRN_OP_LESS_EQUAL : + func = grn_operator_exec_less_equal; + break; + case GRN_OP_GREATER_EQUAL : + func = grn_operator_exec_greater_equal; + break; + case GRN_OP_MATCH : + func = grn_operator_exec_match; + break; + case GRN_OP_PREFIX : + func = grn_operator_exec_prefix; + break; + case GRN_OP_REGEXP : + func = grn_operator_exec_regexp; + break; + default : + break; + } + + return func; +} + +#define DO_EQ_SUB do {\ + switch (y->header.domain) {\ + case GRN_DB_INT8 :\ + r = (x_ == GRN_INT8_VALUE(y));\ + break;\ + case GRN_DB_UINT8 :\ + r = (x_ == GRN_UINT8_VALUE(y));\ + break;\ + case GRN_DB_INT16 :\ + r = (x_ == GRN_INT16_VALUE(y));\ + break;\ + case GRN_DB_UINT16 :\ + r = (x_ == GRN_UINT16_VALUE(y));\ + break;\ + case GRN_DB_INT32 :\ + r = (x_ == GRN_INT32_VALUE(y));\ + break;\ + case GRN_DB_UINT32 :\ + r = (x_ == GRN_UINT32_VALUE(y));\ + break;\ + case GRN_DB_INT64 :\ + r = (x_ == GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_TIME :\ + r = (GRN_TIME_PACK(x_,0) == GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_UINT64 :\ + r = (x_ == GRN_UINT64_VALUE(y));\ + break;\ + case GRN_DB_FLOAT :\ + r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + const char *p_ = GRN_TEXT_VALUE(y);\ + int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\ + r = (x_ == i_);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ +} while (0) + +#define DO_EQ(x,y,r) do {\ + switch (x->header.domain) {\ + case GRN_DB_VOID :\ + r = GRN_FALSE;\ + break;\ + case GRN_DB_INT8 :\ + {\ + int8_t x_ = GRN_INT8_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_UINT8 :\ + {\ + uint8_t x_ = GRN_UINT8_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_INT16 :\ + {\ + int16_t x_ = GRN_INT16_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_UINT16 :\ + {\ + uint16_t x_ = GRN_UINT16_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_INT32 :\ + {\ + int32_t x_ = GRN_INT32_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_UINT32 :\ + {\ + uint32_t x_ = GRN_UINT32_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_INT64 :\ + {\ + int64_t x_ = GRN_INT64_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_TIME :\ + {\ + int64_t x_ = GRN_INT64_VALUE(x);\ + switch (y->header.domain) {\ + case GRN_DB_INT32 :\ + r = (x_ == GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\ + break;\ + case GRN_DB_UINT32 :\ + r = (x_ == GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\ + break;\ + case GRN_DB_INT64 :\ + case GRN_DB_TIME :\ + r = (x_ == GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_UINT64 :\ + r = (x_ == GRN_UINT64_VALUE(y));\ + break;\ + case GRN_DB_FLOAT :\ + r = (x_ == GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + grn_obj time_value_;\ + GRN_TIME_INIT(&time_value_, 0);\ + if (grn_obj_cast(ctx, y, &time_value_, GRN_FALSE) == GRN_SUCCESS) {\ + r = (x_ == GRN_TIME_VALUE(&time_value_));\ + } else {\ + r = GRN_FALSE;\ + }\ + GRN_OBJ_FIN(ctx, &time_value_);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ + }\ + break;\ + case GRN_DB_UINT64 :\ + {\ + uint64_t x_ = GRN_UINT64_VALUE(x);\ + DO_EQ_SUB;\ + }\ + break;\ + case GRN_DB_FLOAT :\ + {\ + double x_ = GRN_FLOAT_VALUE(x);\ + switch (y->header.domain) {\ + case GRN_DB_INT32 :\ + r = ((x_ <= GRN_INT32_VALUE(y)) && (x_ >= GRN_INT32_VALUE(y)));\ + break;\ + case GRN_DB_UINT32 :\ + r = ((x_ <= GRN_UINT32_VALUE(y)) && (x_ >= GRN_UINT32_VALUE(y)));\ + break;\ + case GRN_DB_INT64 :\ + case GRN_DB_TIME :\ + r = ((x_ <= GRN_INT64_VALUE(y)) && (x_ >= GRN_INT64_VALUE(y)));\ + break;\ + case GRN_DB_UINT64 :\ + r = ((x_ <= GRN_UINT64_VALUE(y)) && (x_ >= GRN_UINT64_VALUE(y)));\ + break;\ + case GRN_DB_FLOAT :\ + r = ((x_ <= GRN_FLOAT_VALUE(y)) && (x_ >= GRN_FLOAT_VALUE(y)));\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + const char *p_ = GRN_TEXT_VALUE(y);\ + int i_ = grn_atoi(p_, p_ + GRN_TEXT_LEN(y), NULL);\ + r = (x_ <= i_ && x_ >= i_);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ + }\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\ + uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\ + r = (la == lb && !memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb));\ + } else {\ + const char *q_ = GRN_TEXT_VALUE(x);\ + int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\ + DO_EQ_SUB;\ + }\ + break;\ + default :\ + if ((x->header.domain == y->header.domain)) {\ + r = (GRN_BULK_VSIZE(x) == GRN_BULK_VSIZE(y) &&\ + !(memcmp(GRN_BULK_HEAD(x), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(x))));\ + } else {\ + grn_obj dest;\ + if (x->header.domain < y->header.domain) {\ + GRN_OBJ_INIT(&dest, GRN_BULK, 0, y->header.domain);\ + if (!grn_obj_cast(ctx, x, &dest, GRN_FALSE)) {\ + r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(y) &&\ + !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(y), GRN_BULK_VSIZE(y))); \ + } else {\ + r = GRN_FALSE;\ + }\ + } else {\ + GRN_OBJ_INIT(&dest, GRN_BULK, 0, x->header.domain);\ + if (!grn_obj_cast(ctx, y, &dest, GRN_FALSE)) {\ + r = (GRN_BULK_VSIZE(&dest) == GRN_BULK_VSIZE(x) &&\ + !memcmp(GRN_BULK_HEAD(&dest), GRN_BULK_HEAD(x), GRN_BULK_VSIZE(x))); \ + } else {\ + r = GRN_FALSE;\ + }\ + }\ + GRN_OBJ_FIN(ctx, &dest);\ + }\ + break;\ + }\ +} while (0) + +grn_bool +grn_operator_exec_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r = GRN_FALSE; + GRN_API_ENTER; + DO_EQ(x, y, r); + GRN_API_RETURN(r); +} + +grn_bool +grn_operator_exec_not_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r = GRN_FALSE; + GRN_API_ENTER; + DO_EQ(x, y, r); + GRN_API_RETURN(!r); +} + +#define DO_COMPARE_SCALAR_SUB_NUMERIC(y,op) do {\ + switch ((y)->header.domain) {\ + case GRN_DB_BOOL :\ + r = (x_ op (uint8_t)(GRN_BOOL_VALUE(y) ? 1 : 0));\ + break;\ + case GRN_DB_INT8 :\ + r = (x_ op GRN_INT8_VALUE(y));\ + break;\ + case GRN_DB_UINT8 :\ + r = (x_ op GRN_UINT8_VALUE(y));\ + break;\ + case GRN_DB_INT16 :\ + r = (x_ op GRN_INT16_VALUE(y));\ + break;\ + case GRN_DB_UINT16 :\ + r = (x_ op GRN_UINT16_VALUE(y));\ + break;\ + case GRN_DB_INT32 :\ + r = (x_ op GRN_INT32_VALUE(y));\ + break;\ + case GRN_DB_UINT32 :\ + r = (x_ op GRN_UINT32_VALUE(y));\ + break;\ + case GRN_DB_INT64 :\ + r = (x_ op GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_TIME :\ + r = (GRN_TIME_PACK(x_,0) op GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_UINT64 :\ + r = (x_ op GRN_UINT64_VALUE(y));\ + break;\ + case GRN_DB_FLOAT :\ + r = (x_ op GRN_FLOAT_VALUE(y));\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ +} while (0) + +#define DO_COMPARE_SCALAR_SUB_BUILTIN(op) do {\ + switch (y->header.domain) {\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + grn_obj y_;\ + GRN_OBJ_INIT(&y_, GRN_BULK, 0, x->header.domain);\ + if (grn_obj_cast(ctx, y, &y_, GRN_FALSE)) {\ + r = GRN_FALSE;\ + } else {\ + DO_COMPARE_SCALAR_SUB_NUMERIC(&y_, op);\ + }\ + GRN_OBJ_FIN(ctx, &y_);\ + }\ + break;\ + default :\ + DO_COMPARE_SCALAR_SUB_NUMERIC(y,op);\ + break;\ + }\ +} while (0) + +#define DO_COMPARE_SCALAR_SUB(op) do {\ + if (y->header.domain >= GRN_N_RESERVED_TYPES) {\ + grn_obj *y_table;\ + y_table = grn_ctx_at(ctx, y->header.domain);\ + switch (y_table->header.type) {\ + case GRN_TABLE_HASH_KEY :\ + case GRN_TABLE_PAT_KEY :\ + case GRN_TABLE_DAT_KEY :\ + {\ + grn_obj y_key;\ + int length;\ + GRN_OBJ_INIT(&y_key, GRN_BULK, 0, y_table->header.domain);\ + length = grn_table_get_key2(ctx, y_table, GRN_RECORD_VALUE(y), &y_key);\ + if (length > 0) {\ + grn_obj *y_original = y;\ + y = &y_key;\ + DO_COMPARE_SCALAR_SUB_BUILTIN(op);\ + y = y_original;\ + } else {\ + r = GRN_FALSE;\ + }\ + GRN_OBJ_FIN(ctx, &y_key);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ + grn_obj_unlink(ctx, y_table);\ + } else {\ + DO_COMPARE_SCALAR_SUB_BUILTIN(op);\ + }\ +} while (0) + +#define DO_COMPARE_SCALAR_BUILTIN(x,y,r,op) do {\ + switch (x->header.domain) {\ + case GRN_DB_BOOL :\ + {\ + uint8_t x_ = GRN_BOOL_VALUE(x) ? 1 : 0;\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_INT8 :\ + {\ + int8_t x_ = GRN_INT8_VALUE(x);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_UINT8 :\ + {\ + uint8_t x_ = GRN_UINT8_VALUE(x);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_INT16 :\ + {\ + int16_t x_ = GRN_INT16_VALUE(x);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_UINT16 :\ + {\ + uint16_t x_ = GRN_UINT16_VALUE(x);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_INT32 :\ + {\ + int32_t x_ = GRN_INT32_VALUE(x);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_UINT32 :\ + {\ + uint32_t x_ = GRN_UINT32_VALUE(x);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_TIME :\ + {\ + int64_t x_ = GRN_INT64_VALUE(x);\ + switch (y->header.domain) {\ + case GRN_DB_INT32 :\ + r = (x_ op GRN_TIME_PACK(GRN_INT32_VALUE(y), 0));\ + break;\ + case GRN_DB_UINT32 :\ + r = (x_ op GRN_TIME_PACK(GRN_UINT32_VALUE(y), 0));\ + break;\ + case GRN_DB_INT64 :\ + case GRN_DB_TIME :\ + r = (x_ op GRN_INT64_VALUE(y));\ + break;\ + case GRN_DB_UINT64 :\ + r = (x_ op GRN_UINT64_VALUE(y));\ + break;\ + case GRN_DB_FLOAT :\ + r = (x_ op GRN_TIME_PACK(GRN_FLOAT_VALUE(y), 0));\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + {\ + grn_obj time_value_;\ + GRN_TIME_INIT(&time_value_, 0);\ + if (grn_obj_cast(ctx, y, &time_value_, GRN_FALSE) == GRN_SUCCESS) {\ + r = (x_ op GRN_TIME_VALUE(&time_value_));\ + } else {\ + r = GRN_FALSE;\ + }\ + GRN_OBJ_FIN(ctx, &time_value_);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ + }\ + break;\ + case GRN_DB_INT64 :\ + {\ + int64_t x_ = GRN_INT64_VALUE(x);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_UINT64 :\ + {\ + uint64_t x_ = GRN_UINT64_VALUE(x);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_FLOAT :\ + {\ + double x_ = GRN_FLOAT_VALUE(x);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + case GRN_DB_SHORT_TEXT :\ + case GRN_DB_TEXT :\ + case GRN_DB_LONG_TEXT :\ + if (GRN_DB_SHORT_TEXT <= y->header.domain && y->header.domain <= GRN_DB_LONG_TEXT) {\ + int r_;\ + uint32_t la = GRN_TEXT_LEN(x), lb = GRN_TEXT_LEN(y);\ + if (la > lb) {\ + if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), lb))) {\ + r_ = 1;\ + }\ + } else {\ + if (!(r_ = memcmp(GRN_TEXT_VALUE(x), GRN_TEXT_VALUE(y), la))) {\ + r_ = la == lb ? 0 : -1;\ + }\ + }\ + r = (r_ op 0);\ + } else {\ + const char *q_ = GRN_TEXT_VALUE(x);\ + int x_ = grn_atoi(q_, q_ + GRN_TEXT_LEN(x), NULL);\ + DO_COMPARE_SCALAR_SUB(op);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ +} while (0) + +#define DO_COMPARE_SCALAR(x, y, r, op) do {\ + if (x->header.domain >= GRN_N_RESERVED_TYPES) {\ + grn_obj *x_table;\ + x_table = grn_ctx_at(ctx, x->header.domain);\ + switch (x_table->header.type) {\ + case GRN_TABLE_HASH_KEY :\ + case GRN_TABLE_PAT_KEY :\ + case GRN_TABLE_DAT_KEY :\ + {\ + grn_obj x_key;\ + int length;\ + GRN_OBJ_INIT(&x_key, GRN_BULK, 0, x_table->header.domain);\ + length = grn_table_get_key2(ctx, x_table, GRN_RECORD_VALUE(x), &x_key);\ + if (length > 0) {\ + grn_obj *x_original = x;\ + x = &x_key;\ + DO_COMPARE_SCALAR_BUILTIN((&x_key), y, r, op);\ + x = x_original;\ + } else {\ + r = GRN_FALSE;\ + }\ + GRN_OBJ_FIN(ctx, &x_key);\ + }\ + break;\ + default :\ + r = GRN_FALSE;\ + break;\ + }\ + grn_obj_unlink(ctx, x_table);\ + } else {\ + DO_COMPARE_SCALAR_BUILTIN(x, y, r, op);\ + }\ +} while (0) + +#define DO_COMPARE(x, y, r, op) do {\ + if (x->header.type == GRN_UVECTOR) {\ + grn_obj element_buffer;\ + unsigned int i, n;\ + unsigned int element_size;\ + GRN_VALUE_FIX_SIZE_INIT(&element_buffer, 0, x->header.domain);\ + n = grn_uvector_size(ctx, x);\ + element_size = grn_uvector_element_size(ctx, x);\ + for (i = 0; i < n; i++) {\ + grn_obj *element = &element_buffer;\ + GRN_BULK_REWIND(element);\ + grn_bulk_write(ctx, element,\ + ((uint8_t *)GRN_BULK_HEAD(x)) + (element_size * i),\ + element_size);\ + DO_COMPARE_SCALAR(element, y, r, op);\ + if (r) {\ + break;\ + }\ + }\ + GRN_OBJ_FIN(ctx, &element_buffer);\ + } else {\ + if (GRN_BULK_VSIZE(x) == 0 || GRN_BULK_VSIZE(y) == 0) {\ + r = GRN_FALSE;\ + } else {\ + DO_COMPARE_SCALAR(x, y, r, op);\ + }\ + }\ +} while (0) + +grn_bool +grn_operator_exec_less(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r = GRN_FALSE; + GRN_API_ENTER; + DO_COMPARE(x, y, r, <); + GRN_API_RETURN(r); +} + +grn_bool +grn_operator_exec_greater(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r = GRN_FALSE; + GRN_API_ENTER; + DO_COMPARE(x, y, r, >); + GRN_API_RETURN(r); +} + +grn_bool +grn_operator_exec_less_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r = GRN_FALSE; + GRN_API_ENTER; + DO_COMPARE(x, y, r, <=); + GRN_API_RETURN(r); +} + +grn_bool +grn_operator_exec_greater_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y) +{ + grn_bool r = GRN_FALSE; + GRN_API_ENTER; + DO_COMPARE(x, y, r, >=); + GRN_API_RETURN(r); +} + +static grn_bool +exec_match_uvector_bulk(grn_ctx *ctx, grn_obj *uvector, grn_obj *query) +{ + grn_bool matched = GRN_FALSE; + unsigned int i, size; + grn_obj element; + unsigned int element_size; + + size = grn_uvector_size(ctx, uvector); + element_size = grn_uvector_element_size(ctx, uvector); + GRN_VALUE_FIX_SIZE_INIT(&element, 0, uvector->header.domain); + for (i = 0; i < size; i++) { + GRN_BULK_REWIND(&element); + grn_bulk_write(ctx, &element, + GRN_BULK_HEAD(uvector) + (element_size * i), + element_size); + if (grn_operator_exec_equal(ctx, &element, query)) { + matched = GRN_TRUE; + break; + } + } + GRN_OBJ_FIN(ctx, &element); + + return matched; +} + +static grn_bool +exec_match_vector_bulk(grn_ctx *ctx, grn_obj *vector, grn_obj *query) +{ + grn_bool matched = GRN_FALSE; + unsigned int i, size; + grn_obj element; + + size = grn_vector_size(ctx, vector); + GRN_VOID_INIT(&element); + for (i = 0; i < size; i++) { + const char *content; + unsigned int content_size; + grn_id domain_id; + + content_size = grn_vector_get_element(ctx, vector, i, + &content, NULL, &domain_id); + grn_obj_reinit(ctx, &element, domain_id, 0); + grn_bulk_write(ctx, &element, content, content_size); + if (grn_operator_exec_equal(ctx, &element, query)) { + matched = GRN_TRUE; + break; + } + } + GRN_OBJ_FIN(ctx, &element); + + return matched; +} + +#ifdef GRN_SUPPORT_REGEXP +static OnigRegex +regexp_compile(grn_ctx *ctx, + const char *pattern, + unsigned int pattern_len, + const OnigSyntaxType *syntax) +{ + OnigRegex regex; + OnigEncoding onig_encoding; + int onig_result; + OnigErrorInfo onig_error_info; + + if (ctx->encoding == GRN_ENC_NONE) { + return NULL; + } + + switch (ctx->encoding) { + case GRN_ENC_EUC_JP : + onig_encoding = ONIG_ENCODING_EUC_JP; + break; + case GRN_ENC_UTF8 : + onig_encoding = ONIG_ENCODING_UTF8; + break; + case GRN_ENC_SJIS : + onig_encoding = ONIG_ENCODING_CP932; + break; + case GRN_ENC_LATIN1 : + onig_encoding = ONIG_ENCODING_ISO_8859_1; + break; + case GRN_ENC_KOI8R : + onig_encoding = ONIG_ENCODING_KOI8_R; + break; + default : + return NULL; + } + + onig_result = onig_new(®ex, + pattern, + pattern + pattern_len, + ONIG_OPTION_ASCII_RANGE | + ONIG_OPTION_MULTILINE, + onig_encoding, + syntax, + &onig_error_info); + if (onig_result != ONIG_NORMAL) { + char message[ONIG_MAX_ERROR_MESSAGE_LEN]; + onig_error_code_to_str(message, onig_result, onig_error_info); + ERR(GRN_INVALID_ARGUMENT, + "[operator][regexp] " + "failed to create regular expression object: <%.*s>: %s", + pattern_len, pattern, + message); + return NULL; + } + + return regex; +} + +static grn_bool +regexp_is_match(grn_ctx *ctx, OnigRegex regex, + const char *target, unsigned int target_len) +{ + OnigPosition position; + + position = onig_search(regex, + target, + target + target_len, + target, + target + target_len, + NULL, + ONIG_OPTION_NONE); + return position != ONIG_MISMATCH; +} +#endif /* GRN_SUPPORT_REGEXP */ + +static grn_bool +string_have_sub_text(grn_ctx *ctx, + const char *text, unsigned int text_len, + const char *sub_text, unsigned int sub_text_len) +{ + if (sub_text_len == 0) { + return GRN_FALSE; + } + + if (sub_text_len > text_len) { + return GRN_FALSE; + } + +#ifdef GRN_SUPPORT_REGEXP + { + OnigRegex regex; + grn_bool matched; + + regex = regexp_compile(ctx, sub_text, sub_text_len, ONIG_SYNTAX_ASIS); + if (!regex) { + return GRN_FALSE; + } + + matched = regexp_is_match(ctx, regex, text, text_len); + onig_free(regex); + return matched; + } +#else /* GRN_SUPPORT_REGEXP */ + { + const char *text_current = text; + const char *text_end = text + text_len; + const char *sub_text_current = sub_text; + const char *sub_text_end = sub_text + sub_text_len; + int sub_text_start_char_len; + int sub_text_char_len; + + sub_text_start_char_len = grn_charlen(ctx, sub_text, sub_text_end); + if (sub_text_start_char_len == 0) { + return GRN_FALSE; + } + sub_text_char_len = sub_text_start_char_len; + + while (text_current < text_end) { + int text_char_len; + + text_char_len = grn_charlen(ctx, text_current, text_end); + if (text_char_len == 0) { + return GRN_FALSE; + } + + if (text_char_len == sub_text_char_len && + memcmp(text_current, sub_text_current, text_char_len) == 0) { + sub_text_current += sub_text_char_len; + if (sub_text_current == sub_text_end) { + return GRN_TRUE; + } + + sub_text_char_len = grn_charlen(ctx, sub_text_current, sub_text_end); + if (sub_text_char_len == 0) { + return GRN_FALSE; + } + } else { + if (sub_text_current != sub_text) { + sub_text_current = sub_text; + sub_text_char_len = sub_text_start_char_len; + continue; + } + } + + text_current += text_char_len; + } + + return GRN_FALSE; + } +#endif /* GRN_SUPPORT_REGEXP */ +} + +static grn_bool +string_have_prefix(grn_ctx *ctx, + const char *target, unsigned int target_len, + const char *prefix, unsigned int prefix_len) +{ + return (target_len >= prefix_len && + strncmp(target, prefix, prefix_len) == 0); +} + +static grn_bool +string_match_regexp(grn_ctx *ctx, + const char *target, unsigned int target_len, + const char *pattern, unsigned int pattern_len) +{ +#ifdef GRN_SUPPORT_REGEXP + OnigRegex regex; + grn_bool matched; + + regex = regexp_compile(ctx, pattern, pattern_len, ONIG_SYNTAX_RUBY); + if (!regex) { + return GRN_FALSE; + } + + matched = regexp_is_match(ctx, regex, target, target_len); + onig_free(regex); + return matched; +#else /* GRN_SUPPORT_REGEXP */ + return GRN_FALSE; +#endif /* GRN_SUPPORT_REGEXP */ +} + +static grn_bool +exec_text_operator(grn_ctx *ctx, + grn_operator op, + const char *target, + unsigned int target_len, + const char *query, + unsigned int query_len) +{ + grn_bool matched = GRN_FALSE; + + if (target_len == 0 || query_len == 0) { + return GRN_FALSE; + } + + switch (op) { + case GRN_OP_MATCH : + matched = string_have_sub_text(ctx, target, target_len, query, query_len); + break; + case GRN_OP_PREFIX : + matched = string_have_prefix(ctx, target, target_len, query, query_len); + break; + case GRN_OP_REGEXP : + matched = string_match_regexp(ctx, target, target_len, query, query_len); + break; + default : + matched = GRN_FALSE; + break; + } + + return matched; +} + +static grn_bool +exec_text_operator_raw_text_raw_text(grn_ctx *ctx, + grn_operator op, + const char *target, + unsigned int target_len, + const char *query, + unsigned int query_len) +{ + grn_obj *normalizer; + grn_obj *norm_target; + grn_obj *norm_query; + const char *norm_target_raw; + const char *norm_query_raw; + unsigned int norm_target_raw_length_in_bytes; + unsigned int norm_query_raw_length_in_bytes; + grn_bool matched = GRN_FALSE; + + if (target_len == 0 || query_len == 0) { + return GRN_FALSE; + } + + normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + norm_target = grn_string_open(ctx, target, target_len, normalizer, 0); + grn_string_get_normalized(ctx, norm_target, + &norm_target_raw, + &norm_target_raw_length_in_bytes, + NULL); + + if (op == GRN_OP_REGEXP) { + norm_query = NULL; + norm_query_raw = query; + norm_query_raw_length_in_bytes = query_len; + } else { + norm_query = grn_string_open(ctx, query, query_len, normalizer, 0); + grn_string_get_normalized(ctx, norm_query, + &norm_query_raw, + &norm_query_raw_length_in_bytes, + NULL); + } + + matched = exec_text_operator(ctx, op, + norm_target_raw, + norm_target_raw_length_in_bytes, + norm_query_raw, + norm_query_raw_length_in_bytes); + + grn_obj_close(ctx, norm_target); + if (norm_query) { + grn_obj_close(ctx, norm_query); + } + grn_obj_unlink(ctx, normalizer); + + return matched; +} + +static grn_bool +exec_text_operator_record_text(grn_ctx *ctx, + grn_operator op, + grn_obj *record, grn_obj *table, + grn_obj *query) +{ + grn_obj *normalizer; + char record_key[GRN_TABLE_MAX_KEY_SIZE]; + int record_key_len; + grn_bool matched = GRN_FALSE; + + if (table->header.domain != GRN_DB_SHORT_TEXT) { + return GRN_FALSE; + } + + if (GRN_TEXT_LEN(query) == 0) { + return GRN_FALSE; + } + + record_key_len = grn_table_get_key(ctx, table, GRN_RECORD_VALUE(record), + record_key, GRN_TABLE_MAX_KEY_SIZE); + grn_table_get_info(ctx, table, NULL, NULL, NULL, &normalizer, NULL); + if (normalizer) { + grn_obj *norm_query; + const char *norm_query_raw; + unsigned int norm_query_raw_length_in_bytes; + + if (op == GRN_OP_REGEXP) { + norm_query = NULL; + norm_query_raw = GRN_TEXT_VALUE(query); + norm_query_raw_length_in_bytes = GRN_TEXT_LEN(query); + } else { + norm_query = grn_string_open(ctx, + GRN_TEXT_VALUE(query), + GRN_TEXT_LEN(query), + normalizer, + 0); + grn_string_get_normalized(ctx, norm_query, + &norm_query_raw, + &norm_query_raw_length_in_bytes, + NULL); + } + matched = exec_text_operator(ctx, + op, + record_key, + record_key_len, + norm_query_raw, + norm_query_raw_length_in_bytes); + if (norm_query) { + grn_obj_close(ctx, norm_query); + } + } else { + matched = exec_text_operator_raw_text_raw_text(ctx, + op, + record_key, + record_key_len, + GRN_TEXT_VALUE(query), + GRN_TEXT_LEN(query)); + } + + return matched; +} + +static grn_bool +exec_text_operator_text_text(grn_ctx *ctx, + grn_operator op, + grn_obj *target, + grn_obj *query) +{ + return exec_text_operator_raw_text_raw_text(ctx, + op, + GRN_TEXT_VALUE(target), + GRN_TEXT_LEN(target), + GRN_TEXT_VALUE(query), + GRN_TEXT_LEN(query)); +} + +static grn_bool +exec_text_operator_bulk_bulk(grn_ctx *ctx, + grn_operator op, + grn_obj *target, + grn_obj *query) +{ + switch (target->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + switch (query->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + return exec_text_operator_text_text(ctx, op, target, query); + default : + break; + } + return GRN_FALSE; + default: + { + grn_obj *domain; + domain = grn_ctx_at(ctx, target->header.domain); + if (GRN_OBJ_TABLEP(domain)) { + switch (query->header.domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + return exec_text_operator_record_text(ctx, op, target, domain, query); + default : + break; + } + } + } + return GRN_FALSE; + } +} + +grn_bool +grn_operator_exec_match(grn_ctx *ctx, grn_obj *target, grn_obj *sub_text) +{ + grn_bool matched; + GRN_API_ENTER; + switch (target->header.type) { + case GRN_UVECTOR : + matched = exec_match_uvector_bulk(ctx, target, sub_text); + break; + case GRN_VECTOR : + matched = exec_match_vector_bulk(ctx, target, sub_text); + break; + default : + matched = exec_text_operator_bulk_bulk(ctx, GRN_OP_MATCH, target, sub_text); + break; + } + GRN_API_RETURN(matched); +} + +grn_bool +grn_operator_exec_prefix(grn_ctx *ctx, grn_obj *target, grn_obj *prefix) +{ + grn_bool matched; + GRN_API_ENTER; + matched = exec_text_operator_bulk_bulk(ctx, GRN_OP_PREFIX, target, prefix); + GRN_API_RETURN(matched); +} + +static grn_bool +exec_regexp_uvector_bulk(grn_ctx *ctx, grn_obj *uvector, grn_obj *pattern) +{ +#ifdef GRN_SUPPORT_REGEXP + grn_bool matched = GRN_FALSE; + unsigned int i, size; + OnigRegex regex; + grn_obj *domain; + grn_obj *normalizer; + grn_obj *normalizer_auto = NULL; + + size = grn_uvector_size(ctx, uvector); + if (size == 0) { + return GRN_FALSE; + } + + regex = regexp_compile(ctx, + GRN_TEXT_VALUE(pattern), + GRN_TEXT_LEN(pattern), + ONIG_SYNTAX_RUBY); + if (!regex) { + return GRN_FALSE; + } + + domain = grn_ctx_at(ctx, uvector->header.domain); + if (!domain) { + onig_free(regex); + return GRN_FALSE; + } + + grn_table_get_info(ctx, domain, NULL, NULL, NULL, &normalizer, NULL); + if (!normalizer) { + normalizer_auto = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + } + + for (i = 0; i < size; i++) { + grn_id record_id; + char key[GRN_TABLE_MAX_KEY_SIZE]; + int key_size; + + record_id = grn_uvector_get_element(ctx, uvector, i, NULL); + key_size = grn_table_get_key(ctx, domain, record_id, + key, GRN_TABLE_MAX_KEY_SIZE); + if (key_size == 0) { + continue; + } + + if (normalizer) { + matched = regexp_is_match(ctx, regex, key, key_size); + } else { + grn_obj *norm_key; + const char *norm_key_raw; + unsigned int norm_key_raw_length_in_bytes; + + norm_key = grn_string_open(ctx, key, key_size, normalizer_auto, 0); + grn_string_get_normalized(ctx, norm_key, + &norm_key_raw, + &norm_key_raw_length_in_bytes, + NULL); + matched = regexp_is_match(ctx, regex, + norm_key_raw, + norm_key_raw_length_in_bytes); + grn_obj_unlink(ctx, norm_key); + } + + if (matched) { + break; + } + } + + if (normalizer_auto) { + grn_obj_unlink(ctx, normalizer_auto); + } + + grn_obj_unlink(ctx, domain); + + onig_free(regex); + + return matched; +#else /* GRN_SUPPORT_REGEXP */ + return GRN_FALSE; +#endif /* GRN_SUPPORT_REGEXP */ +} + +static grn_bool +exec_regexp_vector_bulk(grn_ctx *ctx, grn_obj *vector, grn_obj *pattern) +{ +#ifdef GRN_SUPPORT_REGEXP + grn_obj *normalizer = NULL; + grn_bool matched = GRN_FALSE; + unsigned int i, size; + OnigRegex regex; + + size = grn_vector_size(ctx, vector); + if (size == 0) { + return GRN_FALSE; + } + + regex = regexp_compile(ctx, + GRN_TEXT_VALUE(pattern), + GRN_TEXT_LEN(pattern), + ONIG_SYNTAX_RUBY); + if (!regex) { + return GRN_FALSE; + } + + normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + for (i = 0; i < size; i++) { + const char *content; + unsigned int content_size; + grn_id domain_id; + grn_obj *norm_content; + const char *norm_content_raw; + unsigned int norm_content_raw_length_in_bytes; + + content_size = grn_vector_get_element(ctx, vector, i, + &content, NULL, &domain_id); + if (content_size == 0) { + continue; + } + + norm_content = grn_string_open(ctx, content, content_size, normalizer, 0); + grn_string_get_normalized(ctx, norm_content, + &norm_content_raw, + &norm_content_raw_length_in_bytes, + NULL); + + matched = regexp_is_match(ctx, regex, + norm_content_raw, + norm_content_raw_length_in_bytes); + + grn_obj_unlink(ctx, norm_content); + + if (matched) { + break; + } + } + grn_obj_unlink(ctx, normalizer); + + onig_free(regex); + + return matched; +#else /* GRN_SUPPORT_REGEXP */ + return GRN_FALSE; +#endif /* GRN_SUPPORT_REGEXP */ +} + +grn_bool +grn_operator_exec_regexp(grn_ctx *ctx, grn_obj *target, grn_obj *pattern) +{ + grn_bool matched = GRN_FALSE; + GRN_API_ENTER; + switch (target->header.type) { + case GRN_UVECTOR : + matched = exec_regexp_uvector_bulk(ctx, target, pattern); + break; + case GRN_VECTOR : + matched = exec_regexp_vector_bulk(ctx, target, pattern); + break; + case GRN_BULK : + matched = exec_text_operator_bulk_bulk(ctx, GRN_OP_REGEXP, target, pattern); + break; + default : + matched = GRN_FALSE; + break; + } + GRN_API_RETURN(matched); +} diff --git a/storage/mroonga/vendor/groonga/lib/output.c b/storage/mroonga/vendor/groonga/lib/output.c new file mode 100644 index 00000000..3c1fb21d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/output.c @@ -0,0 +1,2880 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2009-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" + +#include +#include "grn_str.h" +#include "grn_db.h" +#include "grn_expr_code.h" +#include "grn_util.h" +#include "grn_output.h" + +#define LEVELS (&ctx->impl->output.levels) +#define DEPTH (GRN_BULK_VSIZE(LEVELS)>>2) +#define CURR_LEVEL (DEPTH ? (GRN_UINT32_VALUE_AT(LEVELS, (DEPTH - 1))) : 0) +#define INCR_DEPTH(i) GRN_UINT32_PUT(ctx, LEVELS, i) +#define DECR_DEPTH (DEPTH ? grn_bulk_truncate(ctx, LEVELS, GRN_BULK_VSIZE(LEVELS) - sizeof(uint32_t)) : 0) +#define INCR_LENGTH (DEPTH ? (GRN_UINT32_VALUE_AT(LEVELS, (DEPTH - 1)) += 2) : 0) + +static void +indent(grn_ctx *ctx, grn_obj *outbuf, size_t level) +{ + size_t i; + for (i = 0; i < level; i++) { + GRN_TEXT_PUTS(ctx, outbuf, " "); + } +} + +static void +json_array_open(grn_ctx *ctx, grn_obj *outbuf, size_t *indent_level) +{ + GRN_TEXT_PUTC(ctx, outbuf, '['); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + (*indent_level)++; + indent(ctx, outbuf, *indent_level); + } +} + +static void +json_array_close(grn_ctx *ctx, grn_obj *outbuf, size_t *indent_level) +{ + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + (*indent_level)--; + indent(ctx, outbuf, *indent_level); + } + GRN_TEXT_PUTC(ctx, outbuf, ']'); +} + +static void +json_element_end(grn_ctx *ctx, grn_obj *outbuf, size_t indent_level) +{ + GRN_TEXT_PUTC(ctx, outbuf, ','); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + indent(ctx, outbuf, indent_level); + } +} + +static void +json_map_open(grn_ctx *ctx, grn_obj *outbuf, size_t *indent_level) +{ + GRN_TEXT_PUTC(ctx, outbuf, '{'); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + (*indent_level)++; + indent(ctx, outbuf, *indent_level); + } +} + +static void +json_map_close(grn_ctx *ctx, grn_obj *outbuf, size_t *indent_level) +{ + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + (*indent_level)--; + indent(ctx, outbuf, *indent_level); + } + GRN_TEXT_PUTC(ctx, outbuf, '}'); +} + +static void +json_key_end(grn_ctx *ctx, grn_obj *outbuf) +{ + GRN_TEXT_PUTC(ctx, outbuf, ':'); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, ' '); + } +} + +static void +json_key(grn_ctx *ctx, grn_obj *outbuf, const char *key) +{ + grn_text_esc(ctx, outbuf, key, strlen(key)); + json_key_end(ctx, outbuf); +} + +static void +json_value_end(grn_ctx *ctx, grn_obj *outbuf, size_t indent_level) +{ + GRN_TEXT_PUTC(ctx, outbuf, ','); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + indent(ctx, outbuf, indent_level); + } +} + +static void +put_delimiter(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type) +{ + uint32_t level = CURR_LEVEL; + switch (output_type) { + case GRN_CONTENT_JSON: + if (level < 2) { + if (DEPTH > 0 && ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + indent(ctx, outbuf, DEPTH + 1); + } + return; + } + if ((level & 3) == 3) { + GRN_TEXT_PUTC(ctx, outbuf, ':'); + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, ' '); + } + } else { + json_element_end(ctx, outbuf, DEPTH + 1); + } + // if (DEPTH == 1 && ((level & 3) != 3)) { GRN_TEXT_PUTC(ctx, outbuf, '\n'); } + break; + case GRN_CONTENT_XML: + if (!DEPTH) { return; } + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + break; + case GRN_CONTENT_TSV: + if (level < 2) { return; } + if (DEPTH <= 2) { + GRN_TEXT_PUTC(ctx, outbuf, ((level & 3) == 3) ? '\t' : '\n'); + } else { + GRN_TEXT_PUTC(ctx, outbuf, '\t'); + } + case GRN_CONTENT_MSGPACK : + // do nothing + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + break; + case GRN_CONTENT_NONE: + break; + } +} + +void +grn_output_array_open(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + const char *name, int nelements) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + GRN_TEXT_PUTC(ctx, outbuf, '['); + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTC(ctx, outbuf, '<'); + GRN_TEXT_PUTS(ctx, outbuf, name); + GRN_TEXT_PUTC(ctx, outbuf, '>'); + grn_vector_add_element(ctx, + &ctx->impl->output.names, + name, strlen(name), + 0, GRN_DB_SHORT_TEXT); + break; + case GRN_CONTENT_TSV: + if (DEPTH > 2) { GRN_TEXT_PUTS(ctx, outbuf, "[\t"); } + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + if (nelements < 0) { + GRN_LOG(ctx, GRN_LOG_DEBUG, + "grn_output_array_open nelements (%d) for <%s>", + nelements, + name); + } + msgpack_pack_array(&ctx->impl->output.msgpacker, nelements); +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + break; + case GRN_CONTENT_NONE: + break; + } + INCR_DEPTH(0); +} + +void +grn_output_array_close(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type) +{ + switch (output_type) { + case GRN_CONTENT_JSON: + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + indent(ctx, outbuf, DEPTH); + } + GRN_TEXT_PUTC(ctx, outbuf, ']'); + break; + case GRN_CONTENT_TSV: + if (DEPTH > 3) { + if (CURR_LEVEL >= 2) { GRN_TEXT_PUTC(ctx, outbuf, '\t'); } + GRN_TEXT_PUTC(ctx, outbuf, ']'); + } + break; + case GRN_CONTENT_XML: + { + const char *name; + unsigned int name_len; + name_len = grn_vector_pop_element(ctx, + &ctx->impl->output.names, + &name, NULL, NULL); + GRN_TEXT_PUTS(ctx, outbuf, "'); + } + break; + case GRN_CONTENT_MSGPACK : + // do nothing + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + break; + case GRN_CONTENT_NONE: + break; + } + DECR_DEPTH; + INCR_LENGTH; +} + +void +grn_output_map_open(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + const char *name, int nelements) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + GRN_TEXT_PUTS(ctx, outbuf, "{"); + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTC(ctx, outbuf, '<'); + GRN_TEXT_PUTS(ctx, outbuf, name); + GRN_TEXT_PUTC(ctx, outbuf, '>'); + grn_vector_add_element(ctx, + &ctx->impl->output.names, + name, strlen(name), 0, GRN_DB_SHORT_TEXT); + break; + case GRN_CONTENT_TSV: + if (DEPTH > 2) { GRN_TEXT_PUTS(ctx, outbuf, "{\t"); } + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + if (nelements < 0) { + GRN_LOG(ctx, GRN_LOG_DEBUG, + "grn_output_map_open nelements (%d) for <%s>", + nelements, + name); + } + msgpack_pack_map(&ctx->impl->output.msgpacker, nelements); +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + break; + case GRN_CONTENT_NONE: + break; + } + INCR_DEPTH(1); +} + +void +grn_output_map_close(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type) +{ + switch (output_type) { + case GRN_CONTENT_JSON: + if (ctx->impl->output.is_pretty) { + GRN_TEXT_PUTC(ctx, outbuf, '\n'); + indent(ctx, outbuf, DEPTH); + } + GRN_TEXT_PUTS(ctx, outbuf, "}"); + break; + case GRN_CONTENT_TSV: + if (DEPTH > 3) { + if (CURR_LEVEL >= 2) { GRN_TEXT_PUTC(ctx, outbuf, '\t'); } + GRN_TEXT_PUTC(ctx, outbuf, '}'); + } + break; + case GRN_CONTENT_XML: + { + const char *name; + unsigned int name_len; + name_len = grn_vector_pop_element(ctx, + &ctx->impl->output.names, + &name, NULL, NULL); + GRN_TEXT_PUTS(ctx, outbuf, "'); + } + break; + case GRN_CONTENT_MSGPACK : + // do nothing + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + break; + case GRN_CONTENT_NONE: + break; + } + DECR_DEPTH; + INCR_LENGTH; +} + +void +grn_output_int32(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, int value) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + grn_text_itoa(ctx, outbuf, value); + break; + case GRN_CONTENT_TSV: + grn_text_itoa(ctx, outbuf, value); + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTS(ctx, outbuf, ""); + grn_text_itoa(ctx, outbuf, value); + GRN_TEXT_PUTS(ctx, outbuf, ""); + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + msgpack_pack_int32(&ctx->impl->output.msgpacker, value); +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + grn_text_itoa(ctx, outbuf, value); + break; + case GRN_CONTENT_NONE: + break; + } + INCR_LENGTH; +} + +void +grn_output_int64(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, int64_t value) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + grn_text_lltoa(ctx, outbuf, value); + break; + case GRN_CONTENT_TSV: + grn_text_lltoa(ctx, outbuf, value); + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTS(ctx, outbuf, ""); + grn_text_lltoa(ctx, outbuf, value); + GRN_TEXT_PUTS(ctx, outbuf, ""); + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + msgpack_pack_int64(&ctx->impl->output.msgpacker, value); +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + grn_text_lltoa(ctx, outbuf, value); + break; + case GRN_CONTENT_NONE: + break; + } + INCR_LENGTH; +} + +void +grn_output_uint64(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, uint64_t value) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + grn_text_ulltoa(ctx, outbuf, value); + break; + case GRN_CONTENT_TSV: + grn_text_ulltoa(ctx, outbuf, value); + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTS(ctx, outbuf, ""); + grn_text_ulltoa(ctx, outbuf, value); + GRN_TEXT_PUTS(ctx, outbuf, ""); + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + msgpack_pack_uint64(&ctx->impl->output.msgpacker, value); +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + grn_text_ulltoa(ctx, outbuf, value); + break; + case GRN_CONTENT_NONE: + break; + } + INCR_LENGTH; +} + +void +grn_output_float(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, double value) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + grn_text_ftoa(ctx, outbuf, value); + break; + case GRN_CONTENT_TSV: + grn_text_ftoa(ctx, outbuf, value); + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTS(ctx, outbuf, ""); + grn_text_ftoa(ctx, outbuf, value); + GRN_TEXT_PUTS(ctx, outbuf, ""); + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + msgpack_pack_double(&ctx->impl->output.msgpacker, value); +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + grn_text_ftoa(ctx, outbuf, value); + break; + case GRN_CONTENT_NONE: + break; + } + INCR_LENGTH; +} + +void +grn_output_str(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + const char *value, size_t value_len) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + grn_text_esc(ctx, outbuf, value, value_len); + break; + case GRN_CONTENT_TSV: + grn_text_esc(ctx, outbuf, value, value_len); + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTS(ctx, outbuf, ""); + grn_text_escape_xml(ctx, outbuf, value, value_len); + GRN_TEXT_PUTS(ctx, outbuf, ""); + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + msgpack_pack_str(&ctx->impl->output.msgpacker, value_len); + msgpack_pack_str_body(&ctx->impl->output.msgpacker, value, value_len); +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + GRN_TEXT_PUT(ctx, outbuf, value, value_len); + break; + case GRN_CONTENT_NONE: + break; + } + INCR_LENGTH; +} + +void +grn_output_cstr(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + const char *value) +{ + grn_output_str(ctx, outbuf, output_type, value, strlen(value)); +} + +void +grn_output_bool(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_bool value) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + GRN_TEXT_PUTS(ctx, outbuf, value ? "true" : "false"); + break; + case GRN_CONTENT_TSV: + GRN_TEXT_PUTS(ctx, outbuf, value ? "true" : "false"); + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTS(ctx, outbuf, ""); + GRN_TEXT_PUTS(ctx, outbuf, value ? "true" : "false"); + GRN_TEXT_PUTS(ctx, outbuf, ""); + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + if (value) { + msgpack_pack_true(&ctx->impl->output.msgpacker); + } else { + msgpack_pack_false(&ctx->impl->output.msgpacker); + } +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + GRN_TEXT_PUTS(ctx, outbuf, value ? "true" : "false"); + break; + case GRN_CONTENT_NONE: + break; + } + INCR_LENGTH; +} + +void +grn_output_null(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + GRN_TEXT_PUTS(ctx, outbuf, "null"); + break; + case GRN_CONTENT_TSV: + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTS(ctx, outbuf, ""); + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + msgpack_pack_nil(&ctx->impl->output.msgpacker); +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + break; + case GRN_CONTENT_NONE: + break; + } + INCR_LENGTH; +} + +static inline void +grn_output_bulk_void(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + const char *value, size_t value_len) +{ + if (value_len == sizeof(grn_id) && *(grn_id *)value == GRN_ID_NIL) { + grn_output_null(ctx, outbuf, output_type); + } else { + grn_output_str(ctx, outbuf, output_type, value, value_len); + } +} + +void +grn_output_time(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, int64_t value) +{ + double dv = value; + dv /= 1000000.0; + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + grn_text_ftoa(ctx, outbuf, dv); + break; + case GRN_CONTENT_TSV: + grn_text_ftoa(ctx, outbuf, dv); + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTS(ctx, outbuf, ""); + grn_text_ftoa(ctx, outbuf, dv); + GRN_TEXT_PUTS(ctx, outbuf, ""); + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + msgpack_pack_double(&ctx->impl->output.msgpacker, dv); +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + grn_text_ftoa(ctx, outbuf, dv); + break; + case GRN_CONTENT_NONE: + break; + } + INCR_LENGTH; +} + +void +grn_output_geo_point(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + grn_geo_point *value) +{ + put_delimiter(ctx, outbuf, output_type); + switch (output_type) { + case GRN_CONTENT_JSON: + if (value) { + GRN_TEXT_PUTC(ctx, outbuf, '"'); + grn_text_itoa(ctx, outbuf, value->latitude); + GRN_TEXT_PUTC(ctx, outbuf, 'x'); + grn_text_itoa(ctx, outbuf, value->longitude); + GRN_TEXT_PUTC(ctx, outbuf, '"'); + } else { + GRN_TEXT_PUTS(ctx, outbuf, "null"); + } + break; + case GRN_CONTENT_TSV: + if (value) { + GRN_TEXT_PUTC(ctx, outbuf, '"'); + grn_text_itoa(ctx, outbuf, value->latitude); + GRN_TEXT_PUTC(ctx, outbuf, 'x'); + grn_text_itoa(ctx, outbuf, value->longitude); + GRN_TEXT_PUTC(ctx, outbuf, '"'); + } else { + GRN_TEXT_PUTS(ctx, outbuf, "\"\""); + } + break; + case GRN_CONTENT_XML: + GRN_TEXT_PUTS(ctx, outbuf, ""); + if (value) { + grn_text_itoa(ctx, outbuf, value->latitude); + GRN_TEXT_PUTC(ctx, outbuf, 'x'); + grn_text_itoa(ctx, outbuf, value->longitude); + } + GRN_TEXT_PUTS(ctx, outbuf, ""); + break; + case GRN_CONTENT_MSGPACK : +#ifdef GRN_WITH_MESSAGE_PACK + if (value) { + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + grn_text_itoa(ctx, &buf, value->latitude); + GRN_TEXT_PUTC(ctx, &buf, 'x'); + grn_text_itoa(ctx, &buf, value->longitude); + msgpack_pack_str(&ctx->impl->output.msgpacker, GRN_TEXT_LEN(&buf)); + msgpack_pack_str_body(&ctx->impl->output.msgpacker, + GRN_TEXT_VALUE(&buf), + GRN_TEXT_LEN(&buf)); + grn_obj_close(ctx, &buf); + } else { + msgpack_pack_nil(&ctx->impl->output.msgpacker); + } +#endif + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + if (value) { + GRN_TEXT_PUTC(ctx, outbuf, '"'); + grn_text_itoa(ctx, outbuf, value->latitude); + GRN_TEXT_PUTC(ctx, outbuf, 'x'); + grn_text_itoa(ctx, outbuf, value->longitude); + GRN_TEXT_PUTC(ctx, outbuf, '"'); + } else { + GRN_TEXT_PUTS(ctx, outbuf, "\"\""); + } + break; + case GRN_CONTENT_NONE: + break; + } + INCR_LENGTH; +} + +static void +grn_text_atoj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + grn_obj *obj, grn_id id) +{ + uint32_t vs; + grn_obj buf; + if (obj->header.type == GRN_ACCESSOR) { + grn_accessor *a = (grn_accessor *)obj; + GRN_TEXT_INIT(&buf, 0); + for (;;) { + buf.header.domain = grn_obj_get_range(ctx, obj); + GRN_BULK_REWIND(&buf); + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + GRN_UINT32_PUT(ctx, &buf, id); + buf.header.domain = GRN_DB_UINT32; + break; + case GRN_ACCESSOR_GET_KEY : + grn_table_get_key2(ctx, a->obj, id, &buf); + buf.header.domain = DB_OBJ(a->obj)->header.domain; + break; + case GRN_ACCESSOR_GET_VALUE : + grn_obj_get_value(ctx, a->obj, id, &buf); + buf.header.domain = DB_OBJ(a->obj)->range; + break; + case GRN_ACCESSOR_GET_SCORE : + { + grn_rset_recinfo *ri = + (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + if (grn_ctx_get_command_version(ctx) == GRN_COMMAND_VERSION_1) { + int32_t int32_score = ri->score; + GRN_INT32_PUT(ctx, &buf, int32_score); + buf.header.domain = GRN_DB_INT32; + } else { + double float_score = ri->score; + GRN_FLOAT_PUT(ctx, &buf, float_score); + buf.header.domain = GRN_DB_FLOAT; + } + } + break; + case GRN_ACCESSOR_GET_NSUBRECS : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + GRN_INT32_PUT(ctx, &buf, ri->n_subrecs); + } + buf.header.domain = GRN_DB_INT32; + break; + case GRN_ACCESSOR_GET_MAX : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t max; + max = grn_rset_recinfo_get_max(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, &buf, max); + } + buf.header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_MIN : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t min; + min = grn_rset_recinfo_get_min(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, &buf, min); + } + buf.header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_SUM : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int64_t sum; + sum = grn_rset_recinfo_get_sum(ctx, ri, a->obj); + GRN_INT64_PUT(ctx, &buf, sum); + } + buf.header.domain = GRN_DB_INT64; + break; + case GRN_ACCESSOR_GET_AVG : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + double avg; + avg = grn_rset_recinfo_get_avg(ctx, ri, a->obj); + GRN_FLOAT_PUT(ctx, &buf, avg); + } + buf.header.domain = GRN_DB_FLOAT; + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + if ((a->obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) { + if (a->next) { + grn_id *idp; + grn_obj_get_value(ctx, a->obj, id, &buf); + idp = (grn_id *)GRN_BULK_HEAD(&buf); + vs = GRN_BULK_VSIZE(&buf) / sizeof(grn_id); + grn_output_array_open(ctx, outbuf, output_type, "VECTOR", vs); + for (; vs--; idp++) { + grn_text_atoj(ctx, outbuf, output_type, (grn_obj *)a->next, *idp); + } + grn_output_array_close(ctx, outbuf, output_type); + } else { + grn_text_atoj(ctx, outbuf, output_type, a->obj, id); + } + goto exit; + } else { + grn_obj_get_value(ctx, a->obj, id, &buf); + } + break; + case GRN_ACCESSOR_GET_DB_OBJ : + /* todo */ + break; + case GRN_ACCESSOR_LOOKUP : + /* todo */ + break; + case GRN_ACCESSOR_FUNCALL : + /* todo */ + break; + } + if (a->next) { + a = a->next; + if (GRN_BULK_VSIZE(&buf) >= sizeof(grn_id)) { + id = *((grn_id *)GRN_BULK_HEAD(&buf)); + } else { + id = GRN_ID_NIL; + } + } else { + break; + } + } + grn_output_obj(ctx, outbuf, output_type, &buf, NULL); + } else { + grn_obj_format *format_argument = NULL; + grn_obj_format format; + GRN_OBJ_FORMAT_INIT(&format, 0, 0, 0, 0); + switch (obj->header.type) { + case GRN_COLUMN_FIX_SIZE : + GRN_VALUE_FIX_SIZE_INIT(&buf, 0, DB_OBJ(obj)->range); + break; + case GRN_COLUMN_VAR_SIZE : + if ((obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) { + grn_obj *range = grn_ctx_at(ctx, DB_OBJ(obj)->range); + if (GRN_OBJ_TABLEP(range) || + (range->header.flags & GRN_OBJ_KEY_VAR_SIZE) == 0) { + GRN_VALUE_FIX_SIZE_INIT(&buf, GRN_OBJ_VECTOR, DB_OBJ(obj)->range); + } else { + GRN_VALUE_VAR_SIZE_INIT(&buf, GRN_OBJ_VECTOR, DB_OBJ(obj)->range); + } + if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) { + format.flags |= GRN_OBJ_FORMAT_WITH_WEIGHT; + format_argument = &format; + } + } else { + GRN_VALUE_VAR_SIZE_INIT(&buf, 0, DB_OBJ(obj)->range); + } + break; + case GRN_COLUMN_INDEX : + GRN_UINT32_INIT(&buf, 0); + break; + default: + GRN_TEXT_INIT(&buf, 0); + break; + } + grn_obj_get_value(ctx, obj, id, &buf); + grn_output_obj(ctx, outbuf, output_type, &buf, format_argument); + } +exit : + grn_obj_close(ctx, &buf); +} + +static inline void +grn_output_void(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + grn_obj *bulk, grn_obj_format *format) +{ + grn_output_null(ctx, outbuf, output_type); +} + +static inline void +grn_output_bulk(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + grn_obj *bulk, grn_obj_format *format) +{ + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + switch (bulk->header.domain) { + case GRN_DB_VOID : + grn_output_bulk_void(ctx, outbuf, output_type, GRN_BULK_HEAD(bulk), GRN_BULK_VSIZE(bulk)); + break; + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + grn_output_str(ctx, outbuf, output_type, GRN_BULK_HEAD(bulk), GRN_BULK_VSIZE(bulk)); + break; + case GRN_DB_BOOL : + grn_output_bool(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_UINT8_VALUE(bulk) : 0); + break; + case GRN_DB_INT8 : + grn_output_int32(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_INT8_VALUE(bulk) : 0); + break; + case GRN_DB_UINT8 : + grn_output_int32(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_UINT8_VALUE(bulk) : 0); + break; + case GRN_DB_INT16 : + grn_output_int32(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_INT16_VALUE(bulk) : 0); + break; + case GRN_DB_UINT16 : + grn_output_int32(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_UINT16_VALUE(bulk) : 0); + break; + case GRN_DB_INT32 : + grn_output_int32(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_INT32_VALUE(bulk) : 0); + break; + case GRN_DB_UINT32 : + grn_output_int64(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_UINT32_VALUE(bulk) : 0); + break; + case GRN_DB_INT64 : + grn_output_int64(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_INT64_VALUE(bulk) : 0); + break; + case GRN_DB_UINT64 : + grn_output_uint64(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_UINT64_VALUE(bulk) : 0); + break; + case GRN_DB_FLOAT : + grn_output_float(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_FLOAT_VALUE(bulk) : 0); + break; + case GRN_DB_TIME : + grn_output_time(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? GRN_INT64_VALUE(bulk) : 0); + break; + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + grn_output_geo_point(ctx, outbuf, output_type, + GRN_BULK_VSIZE(bulk) ? (grn_geo_point *)GRN_BULK_HEAD(bulk) : NULL); + break; + default : + if (format) { + int j; + int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *); + grn_id id = GRN_RECORD_VALUE(bulk); + grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); + if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { + grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", ncolumns); + for (j = 0; j < ncolumns; j++) { + grn_id range_id; + grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); + GRN_BULK_REWIND(&buf); + grn_column_name_(ctx, columns[j], &buf); + grn_output_obj(ctx, outbuf, output_type, &buf, NULL); + /* column range */ + range_id = grn_obj_get_range(ctx, columns[j]); + if (range_id == GRN_ID_NIL) { + GRN_TEXT_PUTS(ctx, outbuf, "null"); + } else { + int name_len; + grn_obj *range_obj; + char name_buf[GRN_TABLE_MAX_KEY_SIZE]; + + range_obj = grn_ctx_at(ctx, range_id); + name_len = grn_obj_name(ctx, range_obj, name_buf, + GRN_TABLE_MAX_KEY_SIZE); + GRN_BULK_REWIND(&buf); + GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); + grn_output_obj(ctx, outbuf, output_type, &buf, NULL); + } + grn_output_array_close(ctx, outbuf, output_type); + } + grn_output_array_close(ctx, outbuf, output_type); + } + grn_output_array_open(ctx, outbuf, output_type, "HIT", ncolumns); + for (j = 0; j < ncolumns; j++) { + grn_text_atoj(ctx, outbuf, output_type, columns[j], id); + } + grn_output_array_close(ctx, outbuf, output_type); + } else { + grn_obj *table = grn_ctx_at(ctx, bulk->header.domain); + grn_id id = GRN_RECORD_VALUE(bulk); + if (table && table->header.type != GRN_TABLE_NO_KEY) { + grn_obj *accessor = grn_obj_column(ctx, table, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + if (accessor) { + if (id == GRN_ID_NIL) { + grn_obj_reinit_for(ctx, &buf, accessor); + } else { + grn_obj_get_value(ctx, accessor, id, &buf); + } + grn_obj_unlink(ctx, accessor); + } + grn_output_obj(ctx, outbuf, output_type, &buf, format); + } else { + grn_output_int64(ctx, outbuf, output_type, id); + } + } + break; + } + GRN_OBJ_FIN(ctx, &buf); +} + +static void +grn_output_uvector_result_set(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *uvector, + grn_obj_format *format) +{ + unsigned int i_hit, n_hits; + unsigned int i_column, n_columns; + unsigned int n_elements; + grn_obj **columns; + grn_obj buf; + grn_bool with_column_names = GRN_FALSE; + + n_hits = grn_vector_size(ctx, uvector); + + n_columns = GRN_BULK_VSIZE(&format->columns) / sizeof(grn_obj *); + columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); + + GRN_TEXT_INIT(&buf, 0); + + if (n_hits > 0 && format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { + with_column_names = GRN_TRUE; + } + + n_elements = 1; /* for NHITS */ + if (with_column_names) { + n_elements += 1; /* for COLUMNS */ + } + n_elements += n_hits; /* for HITS */ + grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", n_elements); + + grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1); + grn_text_itoa(ctx, outbuf, n_hits); + grn_output_array_close(ctx, outbuf, output_type); + + if (with_column_names) { + grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", n_columns); + for (i_column = 0; i_column < n_columns; i_column++) { + grn_id range_id; + grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); + + /* name */ + GRN_BULK_REWIND(&buf); + grn_column_name_(ctx, columns[i_column], &buf); + grn_output_obj(ctx, outbuf, output_type, &buf, NULL); + + /* type */ + range_id = grn_obj_get_range(ctx, columns[i_column]); + if (range_id == GRN_ID_NIL) { + GRN_TEXT_PUTS(ctx, outbuf, "null"); + } else { + int name_len; + grn_obj *range_obj; + char name_buf[GRN_TABLE_MAX_KEY_SIZE]; + + range_obj = grn_ctx_at(ctx, range_id); + name_len = grn_obj_name(ctx, range_obj, name_buf, + GRN_TABLE_MAX_KEY_SIZE); + GRN_BULK_REWIND(&buf); + GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); + grn_output_obj(ctx, outbuf, output_type, &buf, NULL); + } + + grn_output_array_close(ctx, outbuf, output_type); + } + grn_output_array_close(ctx, outbuf, output_type); + } + + for (i_hit = 0; i_hit < n_hits++; i_hit++) { + grn_id id; + + id = grn_uvector_get_element(ctx, uvector, i_hit, NULL); + grn_output_array_open(ctx, outbuf, output_type, "HITS", n_columns); + for (i_column = 0; i_column < n_columns; i_column++) { + GRN_BULK_REWIND(&buf); + grn_obj_get_value(ctx, columns[i_column], id, &buf); + grn_output_obj(ctx, outbuf, output_type, &buf, NULL); + } + grn_output_array_close(ctx, outbuf, output_type); + } + + grn_output_array_close(ctx, outbuf, output_type); + + GRN_OBJ_FIN(ctx, &buf); +} + +static inline void +grn_output_uvector(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + grn_obj *uvector, grn_obj_format *format) +{ + grn_bool output_result_set = GRN_FALSE; + grn_bool with_weight = GRN_FALSE; + grn_obj *range; + grn_bool range_is_type; + + if (format) { + if (GRN_BULK_VSIZE(&(format->columns)) > 0) { + output_result_set = GRN_TRUE; + } + if (format->flags & GRN_OBJ_FORMAT_WITH_WEIGHT) { + with_weight = GRN_TRUE; + } + } + + if (output_result_set) { + grn_output_uvector_result_set(ctx, outbuf, output_type, uvector, format); + return; + } + + range = grn_ctx_at(ctx, uvector->header.domain); + range_is_type = (range->header.type == GRN_TYPE); + if (range_is_type) { + unsigned int i, n; + char *raw_elements; + unsigned int element_size; + grn_obj element; + + raw_elements = GRN_BULK_HEAD(uvector); + element_size = GRN_TYPE_SIZE(DB_OBJ(range)); + n = GRN_BULK_VSIZE(uvector) / element_size; + + grn_output_array_open(ctx, outbuf, output_type, "VECTOR", n); + GRN_OBJ_INIT(&element, GRN_BULK, 0, uvector->header.domain); + for (i = 0; i < n; i++) { + GRN_BULK_REWIND(&element); + grn_bulk_write_from(ctx, &element, raw_elements + (element_size * i), + 0, element_size); + grn_output_obj(ctx, outbuf, output_type, &element, NULL); + } + GRN_OBJ_FIN(ctx, &element); + grn_output_array_close(ctx, outbuf, output_type); + } else { + unsigned int i, n; + grn_obj id_value; + grn_obj key_value; + + GRN_UINT32_INIT(&id_value, 0); + GRN_OBJ_INIT(&key_value, GRN_BULK, 0, range->header.domain); + + n = grn_vector_size(ctx, uvector); + if (with_weight) { + grn_output_map_open(ctx, outbuf, output_type, "WEIGHT_VECTOR", n); + } else { + grn_output_array_open(ctx, outbuf, output_type, "VECTOR", n); + } + + for (i = 0; i < n; i++) { + grn_id id; + unsigned int weight; + + id = grn_uvector_get_element(ctx, uvector, i, &weight); + if (range->header.type == GRN_TABLE_NO_KEY) { + GRN_UINT32_SET(ctx, &id_value, id); + grn_output_obj(ctx, outbuf, output_type, &id_value, NULL); + } else { + GRN_BULK_REWIND(&key_value); + grn_table_get_key2(ctx, range, id, &key_value); + grn_output_obj(ctx, outbuf, output_type, &key_value, NULL); + } + + if (with_weight) { + grn_output_uint64(ctx, outbuf, output_type, weight); + } + } + + if (with_weight) { + grn_output_map_close(ctx, outbuf, output_type); + } else { + grn_output_array_close(ctx, outbuf, output_type); + } + + GRN_OBJ_FIN(ctx, &id_value); + GRN_OBJ_FIN(ctx, &key_value); + } + grn_obj_unlink(ctx, range); +} + +static inline void +grn_output_vector(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + grn_obj *vector, grn_obj_format *format) +{ + grn_bool with_weight = GRN_FALSE; + + if (vector->header.domain == GRN_DB_VOID) { + ERR(GRN_INVALID_ARGUMENT, "invalid obj->header.domain"); + return; + } + + if (format) { + if (format->flags & GRN_OBJ_FORMAT_WITH_WEIGHT) { + with_weight = GRN_TRUE; + } + } + + if (with_weight) { + unsigned int i, n; + grn_obj value; + + GRN_VOID_INIT(&value); + n = grn_vector_size(ctx, vector); + grn_output_map_open(ctx, outbuf, output_type, "WEIGHT_VECTOR", n); + for (i = 0; i < n; i++) { + const char *_value; + unsigned int weight, length; + grn_id domain; + + length = grn_vector_get_element(ctx, vector, i, + &_value, &weight, &domain); + if (domain != GRN_DB_VOID) { + grn_obj_reinit(ctx, &value, domain, 0); + } else { + grn_obj_reinit(ctx, &value, vector->header.domain, 0); + } + grn_bulk_write(ctx, &value, _value, length); + grn_output_obj(ctx, outbuf, output_type, &value, NULL); + grn_output_uint64(ctx, outbuf, output_type, weight); + } + grn_output_map_close(ctx, outbuf, output_type); + GRN_OBJ_FIN(ctx, &value); + } else { + unsigned int i, n; + grn_obj value; + GRN_VOID_INIT(&value); + n = grn_vector_size(ctx, vector); + grn_output_array_open(ctx, outbuf, output_type, "VECTOR", n); + for (i = 0; i < n; i++) { + const char *_value; + unsigned int weight, length; + grn_id domain; + + length = grn_vector_get_element(ctx, vector, i, + &_value, &weight, &domain); + if (domain != GRN_DB_VOID) { + grn_obj_reinit(ctx, &value, domain, 0); + } else { + grn_obj_reinit(ctx, &value, vector->header.domain, 0); + } + grn_bulk_write(ctx, &value, _value, length); + grn_output_obj(ctx, outbuf, output_type, &value, NULL); + } + grn_output_array_close(ctx, outbuf, output_type); + GRN_OBJ_FIN(ctx, &value); + } +} + +static inline void +grn_output_pvector(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + grn_obj *pvector, grn_obj_format *format) +{ + if (format) { + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "cannot print GRN_PVECTOR using grn_obj_format"); + } else { + unsigned int i, n; + grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1); + n = GRN_BULK_VSIZE(pvector) / sizeof(grn_obj *); + for (i = 0; i < n; i++) { + grn_obj *value; + + value = GRN_PTR_VALUE_AT(pvector, i); + grn_output_obj(ctx, outbuf, output_type, value, NULL); + } + grn_output_array_close(ctx, outbuf, output_type); + } +} + +static inline void +grn_output_result_set_n_hits_v1(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj_format *format) +{ + grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1); + if (output_type == GRN_CONTENT_XML) { + grn_text_itoa(ctx, outbuf, format->nhits); + } else { + grn_output_int32(ctx, outbuf, output_type, format->nhits); + } + grn_output_array_close(ctx, outbuf, output_type); +} + +static inline void +grn_output_result_set_n_hits_v3(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj_format *format) +{ + grn_output_cstr(ctx, outbuf, output_type, "n_hits"); + grn_output_int32(ctx, outbuf, output_type, format->nhits); +} + +static inline void +grn_output_result_set_n_hits(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj_format *format) +{ + if (format->nhits == -1) { + return; + } + + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + grn_output_result_set_n_hits_v1(ctx, outbuf, output_type, format); + } else { + grn_output_result_set_n_hits_v3(ctx, outbuf, output_type, format); + } +} + +static inline void +grn_output_table_column_info(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + const char *name, + const char *type) +{ + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); + if (name) { + grn_output_cstr(ctx, outbuf, output_type, name); + } else { + grn_output_null(ctx, outbuf, output_type); + } + if (type) { + grn_output_cstr(ctx, outbuf, output_type, type); + } else { + grn_output_null(ctx, outbuf, output_type); + } + grn_output_array_close(ctx, outbuf, output_type); + } else { + grn_output_map_open(ctx, outbuf, output_type, "column", 2); + grn_output_cstr(ctx, outbuf, output_type, "name"); + if (name) { + grn_output_cstr(ctx, outbuf, output_type, name); + } else { + grn_output_null(ctx, outbuf, output_type); + } + grn_output_cstr(ctx, outbuf, output_type, "type"); + if (type) { + grn_output_cstr(ctx, outbuf, output_type, type); + } else { + grn_output_null(ctx, outbuf, output_type); + } + grn_output_map_close(ctx, outbuf, output_type); + } +} + +static inline int +count_n_elements_in_expression(grn_ctx *ctx, grn_obj *expression) +{ + int n_elements = 0; + grn_bool is_first_comma = GRN_TRUE; + grn_expr *expr = (grn_expr *)expression; + grn_expr_code *code; + grn_expr_code *code_end = expr->codes + expr->codes_curr; + + for (code = expr->codes; code < code_end; code++) { + if (code->op == GRN_OP_COMMA) { + n_elements++; + if (is_first_comma) { + n_elements++; + is_first_comma = GRN_FALSE; + } + } + } + + return n_elements; +} + +static grn_bool +is_score_accessor(grn_ctx *ctx, grn_obj *obj) +{ + grn_accessor *a; + + if (obj->header.type != GRN_ACCESSOR) { + return GRN_FALSE; + } + + for (a = (grn_accessor *)obj; a->next; a = a->next) { + } + return a->action == GRN_ACCESSOR_GET_SCORE; +} + +static inline void +grn_output_table_column(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_obj *column, grn_obj *buf) +{ + grn_id range_id = GRN_ID_NIL; + + if (!column) { + grn_output_table_column_info(ctx, outbuf, output_type, NULL, NULL); + return; + } + + GRN_BULK_REWIND(buf); + grn_column_name_(ctx, column, buf); + GRN_TEXT_PUTC(ctx, buf, '\0'); + + if (column->header.type == GRN_COLUMN_INDEX) { + range_id = GRN_DB_UINT32; + } else if (is_score_accessor(ctx, column)) { + if (grn_ctx_get_command_version(ctx) == GRN_COMMAND_VERSION_1) { + range_id = GRN_DB_INT32; + } else { + range_id = GRN_DB_FLOAT; + } + } + if (range_id == GRN_ID_NIL) { + range_id = grn_obj_get_range(ctx, column); + } + if (range_id == GRN_ID_NIL) { + grn_output_table_column_info(ctx, + outbuf, + output_type, + GRN_TEXT_VALUE(buf), + NULL); + } else { + grn_obj *range_obj; + char type_name[GRN_TABLE_MAX_KEY_SIZE]; + int type_name_len; + + range_obj = grn_ctx_at(ctx, range_id); + type_name_len = grn_obj_name(ctx, + range_obj, + type_name, + GRN_TABLE_MAX_KEY_SIZE); + type_name[type_name_len] = '\0'; + grn_output_table_column_info(ctx, + outbuf, + output_type, + GRN_TEXT_VALUE(buf), + type_name); + } +} + +static inline void +grn_output_table_column_by_expression(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_expr_code *code, + grn_expr_code *code_end, + grn_obj *buf) +{ + if (code_end <= code) { + grn_output_table_column_info(ctx, + outbuf, + output_type, + NULL, + NULL); + return; + } + + switch (code_end[-1].op) { + case GRN_OP_GET_MEMBER : + if ((code_end - code) == 3) { + GRN_BULK_REWIND(buf); + grn_column_name_(ctx, code[0].value, buf); + GRN_TEXT_PUTC(ctx, buf, '['); + grn_inspect(ctx, buf, code[1].value); + GRN_TEXT_PUTC(ctx, buf, ']'); + GRN_TEXT_PUTC(ctx, buf, '\0'); + + grn_output_table_column_info(ctx, + outbuf, + output_type, + GRN_TEXT_VALUE(buf), + NULL); + } else { + grn_output_table_column(ctx, outbuf, output_type, code->value, buf); + } + break; + default : + grn_output_table_column(ctx, outbuf, output_type, code->value, buf); + break; + } +} + +static inline void +grn_output_table_columns_open(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + int n_columns) +{ + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", n_columns); + } else { + grn_output_cstr(ctx, outbuf, output_type, "columns"); + grn_output_array_open(ctx, outbuf, output_type, "columns", n_columns); + } +} + +static inline void +grn_output_table_columns_close(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type) +{ + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + grn_output_array_close(ctx, outbuf, output_type); + } else { + grn_output_array_close(ctx, outbuf, output_type); + } +} + +static inline void +grn_output_table_columns_by_expression(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, grn_obj_format *format, + grn_obj *buf) +{ + int n_elements; + int previous_comma_offset = -1; + grn_bool is_first_comma = GRN_TRUE; + grn_bool have_comma = GRN_FALSE; + grn_expr *expr = (grn_expr *)format->expression; + grn_expr_code *code; + grn_expr_code *code_end = expr->codes + expr->codes_curr; + + n_elements = count_n_elements_in_expression(ctx, format->expression); + + grn_output_table_columns_open(ctx, outbuf, output_type, n_elements); + + for (code = expr->codes; code < code_end; code++) { + int code_start_offset; + + if (code->op != GRN_OP_COMMA) { + continue; + } + + have_comma = GRN_TRUE; + if (is_first_comma) { + unsigned int n_used_codes; + int code_end_offset; + + n_used_codes = grn_expr_code_n_used_codes(ctx, expr->codes, code - 1); + code_end_offset = code - expr->codes - n_used_codes; + + grn_output_table_column_by_expression(ctx, outbuf, output_type, + expr->codes, + expr->codes + code_end_offset, + buf); + code_start_offset = code_end_offset; + is_first_comma = GRN_FALSE; + } else { + code_start_offset = previous_comma_offset + 1; + } + + grn_output_table_column_by_expression(ctx, outbuf, output_type, + expr->codes + code_start_offset, + code, + buf); + previous_comma_offset = code - expr->codes; + } + + if (!have_comma && expr->codes_curr > 0) { + grn_output_table_column_by_expression(ctx, outbuf, output_type, + expr->codes, + code_end, + buf); + } + + grn_output_table_columns_close(ctx, outbuf, output_type); +} + +static inline void +grn_output_table_columns_by_columns(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, grn_obj_format *format, + grn_obj *buf) +{ + int i; + int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *); + grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); + + grn_output_table_columns_open(ctx, outbuf, output_type, ncolumns); + for (i = 0; i < ncolumns; i++) { + grn_output_table_column(ctx, outbuf, output_type, columns[i], buf); + } + grn_output_table_columns_close(ctx, outbuf, output_type); +} + +void +grn_output_table_columns(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, grn_obj_format *format) +{ + grn_obj buf; + + GRN_TEXT_INIT(&buf, 0); + if (format->expression) { + grn_output_table_columns_by_expression(ctx, outbuf, output_type, + table, format, &buf); + } else { + grn_output_table_columns_by_columns(ctx, outbuf, output_type, + table, format, &buf); + } + GRN_OBJ_FIN(ctx, &buf); +} + +static inline void +grn_output_table_record_open(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + int n_columns) +{ + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + grn_output_array_open(ctx, outbuf, output_type, "HIT", n_columns); + } else { + grn_output_array_open(ctx, outbuf, output_type, "record", n_columns); + } +} + +static inline void +grn_output_table_record_close(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type) +{ + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + grn_output_array_close(ctx, outbuf, output_type); + } else { + grn_output_array_close(ctx, outbuf, output_type); + } +} + +static inline void +grn_output_table_record_by_column(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *column, + grn_id id) +{ + grn_text_atoj(ctx, outbuf, output_type, column, id); +} + +static inline void +grn_output_table_record_by_expression(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *expression, + grn_obj *record) +{ + grn_expr *expr = (grn_expr *)expression; + + if (expr->codes_curr == 1 && expr->codes[0].op == GRN_OP_GET_VALUE) { + grn_obj *column = expr->codes[0].value; + grn_output_table_record_by_column(ctx, + outbuf, + output_type, + column, + GRN_RECORD_VALUE(record)); + } else { + grn_obj *result; + result = grn_expr_exec(ctx, expression, 0); + if (result) { + grn_output_obj(ctx, outbuf, output_type, result, NULL); + } else { + grn_output_cstr(ctx, outbuf, output_type, ctx->errbuf); + } + } +} + +static inline void +grn_output_table_records_by_expression(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_table_cursor *tc, + grn_obj_format *format) +{ + int n_elements = 0; + grn_id id; + grn_obj *record; + grn_expr *expr = (grn_expr *)format->expression; + grn_expr_code *code; + grn_expr_code *code_end = expr->codes + expr->codes_curr; + + n_elements = count_n_elements_in_expression(ctx, format->expression); + record = grn_expr_get_var_by_offset(ctx, format->expression, 0); + while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) { + int previous_comma_offset = -1; + grn_bool is_first_comma = GRN_TRUE; + grn_bool have_comma = GRN_FALSE; + GRN_RECORD_SET(ctx, record, id); + grn_output_table_record_open(ctx, outbuf, output_type, n_elements); + for (code = expr->codes; code < code_end; code++) { + if (code->op == GRN_OP_COMMA) { + int code_start_offset = previous_comma_offset + 1; + int code_end_offset; + int original_codes_curr = expr->codes_curr; + + have_comma = GRN_TRUE; + if (is_first_comma) { + int second_code_offset; + unsigned int second_code_n_used_codes; + second_code_offset = code - expr->codes - 1; + second_code_n_used_codes = + grn_expr_code_n_used_codes(ctx, + expr->codes, + expr->codes + second_code_offset); + expr->codes_curr = second_code_offset - second_code_n_used_codes + 1; + grn_output_table_record_by_expression(ctx, + outbuf, + output_type, + format->expression, + record); + code_start_offset = expr->codes_curr; + is_first_comma = GRN_FALSE; + } + code_end_offset = code - expr->codes - code_start_offset; + expr->codes += code_start_offset; + expr->codes_curr = code_end_offset; + grn_output_table_record_by_expression(ctx, + outbuf, + output_type, + format->expression, + record); + expr->codes -= code_start_offset; + expr->codes_curr = original_codes_curr; + previous_comma_offset = code - expr->codes; + } + } + + if (!have_comma && expr->codes_curr > 0) { + grn_output_table_record_by_expression(ctx, + outbuf, + output_type, + format->expression, + record); + } + + grn_output_table_record_close(ctx, outbuf, output_type); + } +} + +static inline void +grn_output_table_records_by_columns(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_table_cursor *tc, + grn_obj_format *format) +{ + int i; + grn_id id; + int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *); + grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); + while ((id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL) { + grn_output_table_record_open(ctx, outbuf, output_type, ncolumns); + for (i = 0; i < ncolumns; i++) { + grn_output_table_record_by_column(ctx, + outbuf, + output_type, + columns[i], + id); + } + grn_output_table_record_close(ctx, outbuf, output_type); + } +} + +static inline void +grn_output_table_records_open(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + int n_records) +{ + if (grn_ctx_get_command_version(ctx) >= GRN_COMMAND_VERSION_3) { + grn_output_cstr(ctx, outbuf, output_type, "records"); + grn_output_array_open(ctx, outbuf, output_type, "records", n_records); + } +} + +static inline void +grn_output_table_records_close(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type) +{ + if (grn_ctx_get_command_version(ctx) >= GRN_COMMAND_VERSION_3) { + grn_output_array_close(ctx, outbuf, output_type); + } +} + +void +grn_output_table_records(grn_ctx *ctx, grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, grn_obj_format *format) +{ + grn_table_cursor *tc; + + grn_output_table_records_open(ctx, outbuf, output_type, format->limit); + tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, + format->offset, format->limit, + GRN_CURSOR_ASCENDING); + if (tc) { + if (format->expression) { + grn_output_table_records_by_expression(ctx, outbuf, output_type, + tc, format); + } else { + grn_output_table_records_by_columns(ctx, outbuf, output_type, + tc, format); + } + grn_table_cursor_close(ctx, tc); + } else { + ERRCLR(ctx); + } + grn_output_table_records_close(ctx, outbuf, output_type); +} + +static void +grn_output_result_set_open_v1(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, + grn_obj_format *format, + uint32_t n_additional_elements) +{ + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + if (format) { + int resultset_size = 1; + /* resultset: [NHITS, (COLUMNS), (HITS)] */ + if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { + resultset_size++; + } + resultset_size += format->limit; + resultset_size += n_additional_elements; + grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", resultset_size); + grn_output_result_set_n_hits(ctx, outbuf, output_type, format); + if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { + grn_output_table_columns(ctx, outbuf, output_type, table, format); + } + grn_output_table_records(ctx, outbuf, output_type, table, format); + } else { + int i; + grn_obj *column = grn_obj_column(ctx, table, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + grn_table_cursor *tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, + 0, -1, GRN_CURSOR_ASCENDING); + grn_output_array_open(ctx, outbuf, output_type, "HIT", -1); + if (tc) { + grn_id id; + for (i = 0; (id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL; i++) { + GRN_BULK_REWIND(&buf); + grn_obj_get_value(ctx, column, id, &buf); + grn_text_esc(ctx, outbuf, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf)); + } + grn_table_cursor_close(ctx, tc); + } + grn_obj_unlink(ctx, column); + } + GRN_OBJ_FIN(ctx, &buf); +} + +static void +grn_output_result_set_close_v1(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *table, + grn_obj_format *format) +{ + grn_output_array_close(ctx, outbuf, output_type); +} + +static void +grn_output_result_set_open_v3(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *result_set, + grn_obj_format *format, + uint32_t n_additional_elements) +{ + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + if (format) { + int n_elements = 2; + /* result_set: {"n_hits": N, ("columns": COLUMNS,) "records": records} */ + if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { + n_elements++; + } + n_elements += n_additional_elements; + grn_output_map_open(ctx, outbuf, output_type, "result_set", n_elements); + grn_output_result_set_n_hits(ctx, outbuf, output_type, format); + if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { + grn_output_table_columns(ctx, outbuf, output_type, result_set, format); + } + grn_output_table_records(ctx, outbuf, output_type, result_set, format); + } else { + grn_obj *column; + int n_records; + int n_elements = 1; + + column = grn_obj_column(ctx, + result_set, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + n_elements += n_additional_elements; + grn_output_map_open(ctx, outbuf, output_type, "result_set", n_elements); + n_records = grn_table_size(ctx, result_set); + grn_output_cstr(ctx, outbuf, output_type, "keys"); + grn_output_array_open(ctx, outbuf, output_type, "keys", n_records); + GRN_TABLE_EACH_BEGIN(ctx, result_set, cursor, id) { + GRN_BULK_REWIND(&buf); + grn_obj_get_value(ctx, column, id, &buf); + grn_text_esc(ctx, outbuf, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf)); + } GRN_TABLE_EACH_END(ctx, cursor); + grn_output_array_close(ctx, outbuf, output_type); + grn_obj_unlink(ctx, column); + } + GRN_OBJ_FIN(ctx, &buf); +} + +static void +grn_output_result_set_close_v3(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *result_set, + grn_obj_format *format) +{ + grn_output_map_close(ctx, outbuf, output_type); +} + +void +grn_output_result_set_open(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *result_set, + grn_obj_format *format, + uint32_t n_additional_elements) +{ + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + grn_output_result_set_open_v1(ctx, + outbuf, + output_type, + result_set, + format, + n_additional_elements); + } else { + grn_output_result_set_open_v3(ctx, + outbuf, + output_type, + result_set, + format, + n_additional_elements); + } +} + +void +grn_output_result_set_close(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *result_set, + grn_obj_format *format) +{ + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + grn_output_result_set_close_v1(ctx, outbuf, output_type, result_set, format); + } else { + grn_output_result_set_close_v3(ctx, outbuf, output_type, result_set, format); + } +} + +void +grn_output_result_set(grn_ctx *ctx, + grn_obj *outbuf, + grn_content_type output_type, + grn_obj *result_set, + grn_obj_format *format) +{ + uint32_t n_additional_elements = 0; + + grn_output_result_set_open(ctx, + outbuf, + output_type, + result_set, + format, + n_additional_elements); + grn_output_result_set_close(ctx, outbuf, output_type, result_set, format); +} + +void +grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, + grn_obj *obj, grn_obj_format *format) +{ + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + switch (obj->header.type) { + case GRN_VOID : + grn_output_void(ctx, outbuf, output_type, obj, format); + break; + case GRN_BULK : + grn_output_bulk(ctx, outbuf, output_type, obj, format); + break; + case GRN_UVECTOR : + grn_output_uvector(ctx, outbuf, output_type, obj, format); + break; + case GRN_VECTOR : + grn_output_vector(ctx, outbuf, output_type, obj, format); + break; + case GRN_PVECTOR : + grn_output_pvector(ctx, outbuf, output_type, obj, format); + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + /* Deprecated. Use grn_output_result_set() directly. */ + grn_output_result_set(ctx, outbuf, output_type, obj, format); + break; + } + GRN_OBJ_FIN(ctx, &buf); +} + +typedef enum { + XML_START, + XML_START_ELEMENT, + XML_END_ELEMENT, + XML_TEXT +} xml_status; + +typedef enum { + XML_PLACE_NONE, + XML_PLACE_COLUMN, + XML_PLACE_HIT +} xml_place; + +static char * +transform_xml_next_column(grn_obj *columns, int n) +{ + char *column = GRN_TEXT_VALUE(columns); + while (n--) { + while (*column) { + column++; + } + column++; + } + return column; +} + +static void +transform_xml(grn_ctx *ctx, grn_obj *output, grn_obj *transformed) +{ + char *s, *e; + xml_status status = XML_START; + xml_place place = XML_PLACE_NONE; + grn_obj buf, name, columns, *expr; + unsigned int len; + int offset = 0, limit = 0, record_n = 0; + int column_n = 0, column_text_n = 0, result_set_n = -1; + grn_bool in_vector = GRN_FALSE; + unsigned int vector_element_n = 0; + grn_bool in_weight_vector = GRN_FALSE; + unsigned int weight_vector_item_n = 0; + + s = GRN_TEXT_VALUE(output); + e = GRN_BULK_CURR(output); + GRN_TEXT_INIT(&buf, 0); + GRN_TEXT_INIT(&name, 0); + GRN_TEXT_INIT(&columns, 0); + + expr = ctx->impl->curr_expr; + +#define EQUAL_NAME_P(_name) \ + (GRN_TEXT_LEN(&name) == strlen(_name) && \ + !memcmp(GRN_TEXT_VALUE(&name), _name, strlen(_name))) + + while (s < e) { + switch (*s) { + case '<' : + s++; + switch (*s) { + case '/' : + status = XML_END_ELEMENT; + s++; + break; + default : + status = XML_START_ELEMENT; + break; + } + GRN_BULK_REWIND(&name); + break; + case '>' : + switch (status) { + case XML_START_ELEMENT : + if (EQUAL_NAME_P("COLUMN")) { + place = XML_PLACE_COLUMN; + column_text_n = 0; + } else if (EQUAL_NAME_P("HIT")) { + place = XML_PLACE_HIT; + column_n = 0; + if (result_set_n == 0) { + GRN_TEXT_PUTS(ctx, transformed, "\n"); + } else { + GRN_TEXT_PUTS(ctx, transformed, "\n"); + } + } else if (EQUAL_NAME_P("VECTOR")) { + char *c = transform_xml_next_column(&columns, column_n++); + in_vector = GRN_TRUE; + vector_element_n = 0; + GRN_TEXT_PUTS(ctx, transformed, ""); + } else if (EQUAL_NAME_P("WEIGHT_VECTOR")) { + char *c = transform_xml_next_column(&columns, column_n++); + in_weight_vector = GRN_TRUE; + weight_vector_item_n = 0; + GRN_TEXT_PUTS(ctx, transformed, ""); + } + break; + case XML_END_ELEMENT : + if (EQUAL_NAME_P("HIT")) { + place = XML_PLACE_NONE; + if (result_set_n == 0) { + GRN_TEXT_PUTS(ctx, transformed, "\n"); + } else { + GRN_TEXT_PUTS(ctx, transformed, "/>\n"); + } + } else if (EQUAL_NAME_P("RESULTSET")) { + place = XML_PLACE_NONE; + if (result_set_n == 0) { + GRN_TEXT_PUTS(ctx, transformed, "\n"); + } else { + GRN_TEXT_PUTS(ctx, transformed, + "\n" + "\n"); + } + } else if (EQUAL_NAME_P("RESULT")) { + GRN_TEXT_PUTS(ctx, transformed, + "\n" + "\n" + "\n"); + } else if (EQUAL_NAME_P("VECTOR")) { + in_vector = GRN_FALSE; + GRN_TEXT_PUTS(ctx, transformed, "\n"); + } else if (EQUAL_NAME_P("WEIGHT_VECTOR")) { + in_weight_vector = GRN_FALSE; + GRN_TEXT_PUTS(ctx, transformed, "\n"); + } else { + switch (place) { + case XML_PLACE_HIT : + if (result_set_n == 0) { + if (in_vector) { + if (vector_element_n > 0) { + GRN_TEXT_PUTS(ctx, transformed, ", "); + } + GRN_TEXT_PUT(ctx, transformed, + GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); + vector_element_n++; + } else if (in_weight_vector) { + grn_bool is_key; + is_key = ((weight_vector_item_n % 2) == 0); + if (is_key) { + unsigned int weight_vector_key_n; + weight_vector_key_n = weight_vector_item_n / 2; + if (weight_vector_key_n > 0) { + GRN_TEXT_PUTS(ctx, transformed, ", "); + } + } else { + GRN_TEXT_PUTS(ctx, transformed, ":"); + } + GRN_TEXT_PUT(ctx, transformed, + GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); + weight_vector_item_n++; + } else { + char *c = transform_xml_next_column(&columns, column_n++); + GRN_TEXT_PUTS(ctx, transformed, ""); + GRN_TEXT_PUT(ctx, transformed, + GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); + GRN_TEXT_PUTS(ctx, transformed, "\n"); + } + } else { + char *c = transform_xml_next_column(&columns, column_n++); + GRN_TEXT_PUTS(ctx, transformed, c); + GRN_TEXT_PUTS(ctx, transformed, "=\""); + GRN_TEXT_PUT(ctx, transformed, + GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); + GRN_TEXT_PUTS(ctx, transformed, "\" "); + } + break; + default : + if (EQUAL_NAME_P("NHITS")) { + if (result_set_n == 0) { + uint32_t nhits; + grn_obj *offset_value, *limit_value; + + nhits = grn_atoui(GRN_TEXT_VALUE(&buf), GRN_BULK_CURR(&buf), + NULL); + offset_value = grn_expr_get_var(ctx, expr, + "offset", strlen("offset")); + limit_value = grn_expr_get_var(ctx, expr, + "limit", strlen("limit")); + if (GRN_TEXT_LEN(offset_value)) { + offset = grn_atoi(GRN_TEXT_VALUE(offset_value), + GRN_BULK_CURR(offset_value), + NULL); + } else { + offset = 0; + } + if (GRN_TEXT_LEN(limit_value)) { + limit = grn_atoi(GRN_TEXT_VALUE(limit_value), + GRN_BULK_CURR(limit_value), + NULL); + } else { +#define DEFAULT_LIMIT 10 + limit = DEFAULT_LIMIT; +#undef DEFAULT_LIMIT + } + grn_normalize_offset_and_limit(ctx, nhits, &offset, &limit); + record_n = offset + 1; + GRN_TEXT_PUTS(ctx, transformed, + "\n" + "\n" + "\n" + "\n" + "\n"); + } else { + GRN_TEXT_PUTS(ctx, transformed, + "\n"); + } + } else if (EQUAL_NAME_P("TEXT")) { + switch (place) { + case XML_PLACE_COLUMN : + if (column_text_n == 0) { + GRN_TEXT_PUT(ctx, &columns, + GRN_TEXT_VALUE(&buf), GRN_TEXT_LEN(&buf)); + GRN_TEXT_PUTC(ctx, &columns, '\0'); + } + column_text_n++; + break; + default : + break; + } + } + } + } + default : + break; + } + s++; + GRN_BULK_REWIND(&buf); + status = XML_TEXT; + break; + default : + len = grn_charlen(ctx, s, e); + switch (status) { + case XML_START_ELEMENT : + case XML_END_ELEMENT : + GRN_TEXT_PUT(ctx, &name, s, len); + break; + default : + GRN_TEXT_PUT(ctx, &buf, s, len); + break; + } + s += len; + break; + } + } +#undef EQUAL_NAME_P + + GRN_OBJ_FIN(ctx, &buf); + GRN_OBJ_FIN(ctx, &name); + GRN_OBJ_FIN(ctx, &columns); +} + +#ifdef GRN_WITH_MESSAGE_PACK +typedef struct { + grn_ctx *ctx; + grn_obj *buffer; +} msgpack_writer_ctx; + +static inline int +msgpack_buffer_writer(void* data, const char* buf, msgpack_size_t len) +{ + msgpack_writer_ctx *writer_ctx = (msgpack_writer_ctx *)data; + return grn_bulk_write(writer_ctx->ctx, writer_ctx->buffer, buf, len); +} +#endif + +#define JSON_CALLBACK_PARAM "callback" + +static void +grn_output_envelope_json_v1(grn_ctx *ctx, + grn_rc rc, + grn_obj *head, + grn_obj *body, + grn_obj *foot, + double started, + double elapsed, + const char *file, + int line) +{ + size_t indent_level = 0; + + json_array_open(ctx, head, &indent_level); + { + json_array_open(ctx, head, &indent_level); + { + grn_text_itoa(ctx, head, rc); + + json_element_end(ctx, head, indent_level); + grn_text_ftoa(ctx, head, started); + + json_element_end(ctx, head, indent_level); + grn_text_ftoa(ctx, head, elapsed); + + if (rc != GRN_SUCCESS) { + json_element_end(ctx, head, indent_level); + grn_text_esc(ctx, head, ctx->errbuf, strlen(ctx->errbuf)); + + if (ctx->errfunc && ctx->errfile) { + grn_obj *command; + + json_element_end(ctx, head, indent_level); + json_array_open(ctx, head, &indent_level); + { + json_array_open(ctx, head, &indent_level); + { + grn_text_esc(ctx, head, ctx->errfunc, strlen(ctx->errfunc)); + + json_element_end(ctx, head, indent_level); + grn_text_esc(ctx, head, ctx->errfile, strlen(ctx->errfile)); + + json_element_end(ctx, head, indent_level); + grn_text_itoa(ctx, head, ctx->errline); + } + json_array_close(ctx, head, &indent_level); + + if (file && (command = GRN_CTX_USER_DATA(ctx)->ptr)) { + json_element_end(ctx, head, indent_level); + json_array_open(ctx, head, &indent_level); + { + grn_text_esc(ctx, head, file, strlen(file)); + + json_element_end(ctx, head, indent_level); + grn_text_itoa(ctx, head, line); + + json_element_end(ctx, head, indent_level); + grn_text_esc(ctx, head, + GRN_TEXT_VALUE(command), GRN_TEXT_LEN(command)); + } + json_array_close(ctx, head, &indent_level); + } + } + json_array_close(ctx, head, &indent_level); + } + } + } + json_array_close(ctx, head, &indent_level); + } + + if (GRN_TEXT_LEN(body)) { + json_element_end(ctx, head, indent_level); + } + + json_array_close(ctx, foot, &indent_level); +} + +static void +grn_output_envelope_json(grn_ctx *ctx, + grn_rc rc, + grn_obj *head, + grn_obj *body, + grn_obj *foot, + double started, + double elapsed, + const char *file, + int line) +{ + size_t indent_level = 0; + + json_map_open(ctx, head, &indent_level); + { + json_key(ctx, head, "header"); + json_map_open(ctx, head, &indent_level); + { + json_key(ctx, head, "return_code"); + grn_text_itoa(ctx, head, rc); + + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "start_time"); + grn_text_ftoa(ctx, head, started); + + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "elapsed_time"); + grn_text_ftoa(ctx, head, elapsed); + + if (rc != GRN_SUCCESS) { + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "error"); + json_map_open(ctx, head, &indent_level); + { + json_key(ctx, head, "message"); + grn_text_esc(ctx, head, ctx->errbuf, strlen(ctx->errbuf)); + + if (ctx->errfunc && ctx->errfile) { + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "function"); + grn_text_esc(ctx, head, ctx->errfunc, strlen(ctx->errfunc)); + + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "file"); + grn_text_esc(ctx, head, ctx->errfile, strlen(ctx->errfile)); + + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "line"); + grn_text_itoa(ctx, head, ctx->errline); + } + + if (file) { + grn_obj *command; + + command = GRN_CTX_USER_DATA(ctx)->ptr; + if (command) { + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "input"); + json_map_open(ctx, head, &indent_level); + { + json_key(ctx, head, "file"); + grn_text_esc(ctx, head, file, strlen(file)); + + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "line"); + grn_text_itoa(ctx, head, line); + + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "command"); + grn_text_esc(ctx, head, + GRN_TEXT_VALUE(command), GRN_TEXT_LEN(command)); + } + json_map_close(ctx, head, &indent_level); + } + } + } + json_map_close(ctx, head, &indent_level); + } + } + json_map_close(ctx, head, &indent_level); + + if (GRN_TEXT_LEN(body)) { + json_value_end(ctx, head, indent_level); + json_key(ctx, head, "body"); + } + + json_map_close(ctx, foot, &indent_level); + } +} + +#ifdef GRN_WITH_MESSAGE_PACK +static void +msgpack_pack_cstr(msgpack_packer *packer, + const char *string) +{ + size_t size; + + size = strlen(string); + msgpack_pack_str(packer, size); + msgpack_pack_str_body(packer, string, size); +} + +static void +grn_output_envelope_msgpack_v1(grn_ctx *ctx, + grn_rc rc, + grn_obj *head, + grn_obj *body, + grn_obj *foot, + double started, + double elapsed, + const char *file, + int line) +{ + msgpack_writer_ctx head_writer_ctx; + msgpack_packer header_packer; + int header_size; + + head_writer_ctx.ctx = ctx; + head_writer_ctx.buffer = head; + msgpack_packer_init(&header_packer, &head_writer_ctx, msgpack_buffer_writer); + + /* [HEADER, (BODY)] */ + if (GRN_TEXT_LEN(body) > 0) { + msgpack_pack_array(&header_packer, 2); + } else { + msgpack_pack_array(&header_packer, 1); + } + + /* HEADER := [rc, started, elapsed, (error, (ERROR DETAIL))] */ + header_size = 3; + if (rc != GRN_SUCCESS) { + header_size++; + if (ctx->errfunc && ctx->errfile) { + header_size++; + } + } + msgpack_pack_array(&header_packer, header_size); + msgpack_pack_int(&header_packer, rc); + + msgpack_pack_double(&header_packer, started); + msgpack_pack_double(&header_packer, elapsed); + + if (rc != GRN_SUCCESS) { + msgpack_pack_str(&header_packer, strlen(ctx->errbuf)); + msgpack_pack_str_body(&header_packer, ctx->errbuf, strlen(ctx->errbuf)); + if (ctx->errfunc && ctx->errfile) { + grn_obj *command = GRN_CTX_USER_DATA(ctx)->ptr; + int error_detail_size; + + /* ERROR DETAIL : = [[errfunc, errfile, errline, + (file, line, command)]] */ + /* TODO: output backtrace */ + msgpack_pack_array(&header_packer, 1); + error_detail_size = 3; + if (command) { + error_detail_size += 3; + } + msgpack_pack_array(&header_packer, error_detail_size); + + msgpack_pack_str(&header_packer, strlen(ctx->errfunc)); + msgpack_pack_str_body(&header_packer, ctx->errfunc, strlen(ctx->errfunc)); + + msgpack_pack_str(&header_packer, strlen(ctx->errfile)); + msgpack_pack_str_body(&header_packer, ctx->errfile, strlen(ctx->errfile)); + + msgpack_pack_int(&header_packer, ctx->errline); + + if (command) { + if (file) { + msgpack_pack_str(&header_packer, strlen(file)); + msgpack_pack_str_body(&header_packer, file, strlen(file)); + } else { + msgpack_pack_str(&header_packer, 7); + msgpack_pack_str_body(&header_packer, "(stdin)", 7); + } + + msgpack_pack_int(&header_packer, line); + + msgpack_pack_str(&header_packer, GRN_TEXT_LEN(command)); + msgpack_pack_str_body(&header_packer, GRN_TEXT_VALUE(command), GRN_TEXT_LEN(command)); + } + } + } +} + +static void +grn_output_envelope_msgpack(grn_ctx *ctx, + grn_rc rc, + grn_obj *head, + grn_obj *body, + grn_obj *foot, + double started, + double elapsed, + const char *file, + int line) +{ + msgpack_writer_ctx writer_ctx; + msgpack_packer packer; + int n_elements; + + writer_ctx.ctx = ctx; + writer_ctx.buffer = head; + msgpack_packer_init(&packer, &writer_ctx, msgpack_buffer_writer); + + /* + * ENVELOPE := { + * "header": HEADER, + * "body": BODY (optional) + * } + */ + if (GRN_TEXT_LEN(body) > 0) { + n_elements = 2; + } else { + n_elements = 1; + } + + msgpack_pack_map(&packer, n_elements); + { + int n_header_elements = 3; + + /* + * HEADER := { + * "return_code": rc, + * "start_time": started, + * "elapsed_time": elapsed, + " "error": { (optional) + * "message": errbuf, + * "function": errfunc, + * "file": errfile, + * "line": errline, + * "input": { (optional) + * "file": input_file, + * "line": line, + * "command": command + * } + * } + * } + */ + + if (rc != GRN_SUCCESS) { + n_header_elements++; + } + + msgpack_pack_cstr(&packer, "header"); + msgpack_pack_map(&packer, n_header_elements); + { + msgpack_pack_cstr(&packer, "return_code"); + msgpack_pack_int(&packer, rc); + + msgpack_pack_cstr(&packer, "start_time"); + msgpack_pack_double(&packer, started); + + msgpack_pack_cstr(&packer, "elapsed_time"); + msgpack_pack_double(&packer, elapsed); + + if (rc != GRN_SUCCESS) { + int n_error_elements = 1; + grn_obj *command; + + if (ctx->errfunc) { + n_error_elements++; + } + if (ctx->errfile) { + n_error_elements += 2; + } + + command = GRN_CTX_USER_DATA(ctx)->ptr; + if (file || command) { + n_error_elements++; + } + + msgpack_pack_cstr(&packer, "error"); + msgpack_pack_map(&packer, n_error_elements); + { + msgpack_pack_cstr(&packer, "message"); + msgpack_pack_cstr(&packer, ctx->errbuf); + + if (ctx->errfunc) { + msgpack_pack_cstr(&packer, "function"); + msgpack_pack_cstr(&packer, ctx->errfunc); + } + + if (ctx->errfile) { + msgpack_pack_cstr(&packer, "file"); + msgpack_pack_cstr(&packer, ctx->errfile); + + msgpack_pack_cstr(&packer, "line"); + msgpack_pack_int(&packer, ctx->errline); + } + + if (file || command) { + int n_input_elements = 0; + + if (file) { + n_input_elements += 2; + } + if (command) { + n_input_elements++; + } + + msgpack_pack_cstr(&packer, "input"); + msgpack_pack_map(&packer, n_input_elements); + + if (file) { + msgpack_pack_cstr(&packer, "file"); + msgpack_pack_cstr(&packer, file); + + msgpack_pack_cstr(&packer, "line"); + msgpack_pack_int(&packer, line); + } + + if (command) { + msgpack_pack_cstr(&packer, "command"); + msgpack_pack_str(&packer, GRN_TEXT_LEN(command)); + msgpack_pack_str_body(&packer, + GRN_TEXT_VALUE(command), + GRN_TEXT_LEN(command)); + } + } + } + } + } + + if (GRN_TEXT_LEN(body) > 0) { + msgpack_pack_cstr(&packer, "body"); + } + } +} +#endif /* GRN_WITH_MESSAGE_PACK */ + +void +grn_output_envelope(grn_ctx *ctx, + grn_rc rc, + grn_obj *head, + grn_obj *body, + grn_obj *foot, + const char *file, + int line) +{ + double started, finished, elapsed; + + grn_timeval tv_now; + grn_timeval_now(ctx, &tv_now); + started = ctx->impl->tv.tv_sec; + started += ctx->impl->tv.tv_nsec / GRN_TIME_NSEC_PER_SEC_F; + finished = tv_now.tv_sec; + finished += tv_now.tv_nsec / GRN_TIME_NSEC_PER_SEC_F; + elapsed = finished - started; + + switch (ctx->impl->output.type) { + case GRN_CONTENT_JSON: + { + grn_obj *expr; + grn_obj *jsonp_func = NULL; + + expr = ctx->impl->curr_expr; + if (expr) { + jsonp_func = grn_expr_get_var(ctx, expr, JSON_CALLBACK_PARAM, + strlen(JSON_CALLBACK_PARAM)); + } + if (jsonp_func && GRN_TEXT_LEN(jsonp_func)) { + GRN_TEXT_PUT(ctx, head, + GRN_TEXT_VALUE(jsonp_func), GRN_TEXT_LEN(jsonp_func)); + GRN_TEXT_PUTC(ctx, head, '('); + } + + if (grn_ctx_get_command_version(ctx) <= GRN_COMMAND_VERSION_2) { + grn_output_envelope_json_v1(ctx, rc, + head, body, foot, + started, elapsed, + file, line); + } else { + grn_output_envelope_json(ctx, rc, + head, body, foot, + started, elapsed, + file, line); + } + + if (jsonp_func && GRN_TEXT_LEN(jsonp_func)) { + GRN_TEXT_PUTS(ctx, foot, ");"); + } + } + break; + case GRN_CONTENT_TSV: + grn_text_itoa(ctx, head, rc); + GRN_TEXT_PUTC(ctx, head, '\t'); + grn_text_ftoa(ctx, head, started); + GRN_TEXT_PUTC(ctx, head, '\t'); + grn_text_ftoa(ctx, head, elapsed); + if (rc != GRN_SUCCESS) { + GRN_TEXT_PUTC(ctx, head, '\t'); + grn_text_esc(ctx, head, ctx->errbuf, strlen(ctx->errbuf)); + if (ctx->errfunc && ctx->errfile) { + /* TODO: output backtrace */ + GRN_TEXT_PUTC(ctx, head, '\t'); + grn_text_esc(ctx, head, ctx->errfunc, strlen(ctx->errfunc)); + GRN_TEXT_PUTC(ctx, head, '\t'); + grn_text_esc(ctx, head, ctx->errfile, strlen(ctx->errfile)); + GRN_TEXT_PUTC(ctx, head, '\t'); + grn_text_itoa(ctx, head, ctx->errline); + } + } + GRN_TEXT_PUTS(ctx, head, "\n"); + GRN_TEXT_PUTS(ctx, foot, "\nEND"); + break; + case GRN_CONTENT_XML: + { + char buf[GRN_TABLE_MAX_KEY_SIZE]; + int is_select = 0; + if (!rc && ctx->impl->curr_expr) { + int len = grn_obj_name(ctx, ctx->impl->curr_expr, + buf, GRN_TABLE_MAX_KEY_SIZE); + buf[len] = '\0'; + is_select = strcmp(buf, "select") == 0; + } + if (is_select) { + grn_obj transformed; + GRN_TEXT_INIT(&transformed, 0); + transform_xml(ctx, body, &transformed); + GRN_TEXT_SET(ctx, body, + GRN_TEXT_VALUE(&transformed), GRN_TEXT_LEN(&transformed)); + GRN_OBJ_FIN(ctx, &transformed); + } else { + GRN_TEXT_PUTS(ctx, head, "\n\n"); + if (rc != GRN_SUCCESS) { + GRN_TEXT_PUTS(ctx, head, ""); + grn_text_escape_xml(ctx, head, ctx->errbuf, strlen(ctx->errbuf)); + if (ctx->errfunc && ctx->errfile) { + /* TODO: output backtrace */ + GRN_TEXT_PUTS(ctx, head, "errfunc, strlen(ctx->errfunc)); + GRN_TEXT_PUTS(ctx, head, "\" FILE=\""); + grn_text_escape_xml(ctx, head, ctx->errfile, strlen(ctx->errfile)); + GRN_TEXT_PUTS(ctx, head, "\" LINE=\""); + grn_text_itoa(ctx, head, ctx->errline); + GRN_TEXT_PUTS(ctx, head, "\"/>"); + } + GRN_TEXT_PUTS(ctx, head, ""); + } + GRN_TEXT_PUTS(ctx, foot, "\n"); + } + } + break; + case GRN_CONTENT_MSGPACK: +#ifdef GRN_WITH_MESSAGE_PACK + if (grn_ctx_get_command_version(ctx) <= GRN_COMMAND_VERSION_2) { + grn_output_envelope_msgpack_v1(ctx, rc, + head, body, foot, + started, elapsed, + file, line); + } else { + grn_output_envelope_msgpack(ctx, rc, + head, body, foot, + started, elapsed, + file, line); + } +#endif /* GRN_WITH_MESSAGE_PACK */ + break; + case GRN_CONTENT_GROONGA_COMMAND_LIST : + break; + case GRN_CONTENT_NONE: + break; + } +} + +static inline grn_bool +is_output_columns_format_v1(grn_ctx *ctx, + const char *output_columns, + unsigned int output_columns_len) +{ + const char *current; + const char *end; + grn_bool in_identifier = GRN_FALSE; + + current = output_columns; + end = current + output_columns_len; + while (current < end) { + int char_length; + + char_length = grn_charlen(ctx, current, end); + if (char_length != 1) { + return GRN_FALSE; + } + + switch (current[0]) { + case ' ' : + case ',' : + in_identifier = GRN_FALSE; + break; + case '_' : + in_identifier = GRN_TRUE; + break; + case '.' : + case '-' : + case '#' : + case '@' : + if (!in_identifier) { + return GRN_FALSE; + } + break; + default : + if ('a' <= current[0] && current[0] <= 'z') { + in_identifier = GRN_TRUE; + break; + } else if ('A' <= current[0] && current[0] <= 'Z') { + in_identifier = GRN_TRUE; + break; + } else if ('0' <= current[0] && current[0] <= '9') { + in_identifier = GRN_TRUE; + break; + } else { + return GRN_FALSE; + } + } + + current += char_length; + } + + return GRN_TRUE; +} + +grn_rc +grn_output_format_set_columns(grn_ctx *ctx, grn_obj_format *format, + grn_obj *table, + const char *columns, int columns_len) +{ + grn_rc rc; + + if (is_output_columns_format_v1(ctx, columns, columns_len)) { + rc = grn_obj_columns(ctx, table, columns, columns_len, &(format->columns)); + } else { + grn_obj *variable; + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, format->expression, variable); + rc = grn_expr_parse(ctx, format->expression, + columns, columns_len, NULL, + GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_OUTPUT_COLUMNS); + } + + return rc; +} diff --git a/storage/mroonga/vendor/groonga/lib/pat.c b/storage/mroonga/vendor/groonga/lib/pat.c new file mode 100644 index 00000000..01f6108f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/pat.c @@ -0,0 +1,3674 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include +#include +#include "grn_pat.h" +#include "grn_output.h" +#include "grn_util.h" +#include "grn_normalizer.h" + +#define GRN_PAT_DELETED (GRN_ID_MAX + 1) + +#define GRN_PAT_SEGMENT_SIZE 0x400000 +#define W_OF_KEY_IN_A_SEGMENT 22 +#define W_OF_PAT_IN_A_SEGMENT 18 +#define W_OF_SIS_IN_A_SEGMENT 19 +#define KEY_MASK_IN_A_SEGMENT 0x3fffff +#define PAT_MASK_IN_A_SEGMENT 0x3ffff +#define SIS_MASK_IN_A_SEGMENT 0x7ffff +#define SEG_NOT_ASSIGNED 0xffff +#define GRN_PAT_MAX_SEGMENT 0x1000 +#define GRN_PAT_MDELINFOS (GRN_PAT_NDELINFOS - 1) + +#define GRN_PAT_BIN_KEY 0x70000 + +typedef struct { + grn_id lr[2]; + /* + lr[0]: the left node. + lr[1]: the right node. + + The left node has 0 at the nth bit at the nth byte. + The right node has 1 at the nth bit at the nth byte. + 'check' value indicate 'at the nth bit at the nth byte'. + + The both available nodes has larger check value rather + than the current node. + + The first node (PAT_AT(pat, GRN_ID_NIL, node)) has only + the right node and the node is the start point. + */ + uint32_t key; + /* + PAT_IMD(node) == 0: key bytes offset in memory map. + PAT_IMD(node) == 1: the key bytes. + */ + uint16_t check; + /* + nth byte: 12, nth bit: 3, terminated: 1 + + nth byte is different in key bytes: (check >> 4): max == 4095 + the left most byte is the 0th byte and the right most byte is the 11th byte. + + nth bit is different in nth byte: ((check >> 1) & 0b111) + the left most bit is the 0th bit and the right most bit is the 7th bit. + + terminated: (check & 0b1) + terminated == 1: key is terminated. + */ + uint16_t bits; + /* length: 13, immediate: 1, deleting: 1 */ +} pat_node; + +#define PAT_DELETING (1<<1) +#define PAT_IMMEDIATE (1<<2) + +#define PAT_DEL(x) ((x)->bits & PAT_DELETING) +#define PAT_IMD(x) ((x)->bits & PAT_IMMEDIATE) +#define PAT_LEN(x) (((x)->bits >> 3) + 1) +#define PAT_CHK(x) ((x)->check) +#define PAT_DEL_ON(x) ((x)->bits |= PAT_DELETING) +#define PAT_IMD_ON(x) ((x)->bits |= PAT_IMMEDIATE) +#define PAT_DEL_OFF(x) ((x)->bits &= ~PAT_DELETING) +#define PAT_IMD_OFF(x) ((x)->bits &= ~PAT_IMMEDIATE) +#define PAT_LEN_SET(x,v) ((x)->bits = ((x)->bits & ((1<<3) - 1))|(((v) - 1) << 3)) +#define PAT_CHK_SET(x,v) ((x)->check = (v)) + +typedef struct { + grn_id children; + grn_id sibling; +} sis_node; + +enum { + segment_key = 0, + segment_pat = 1, + segment_sis = 2 +}; + +void grn_p_pat_node(grn_ctx *ctx, grn_pat *pat, pat_node *node); + +/* error utilities */ +inline static int +grn_pat_name(grn_ctx *ctx, grn_pat *pat, char *buffer, int buffer_size) +{ + int name_size; + + if (DB_OBJ(pat)->id == GRN_ID_NIL) { + grn_strcpy(buffer, buffer_size, "(anonymous)"); + name_size = strlen(buffer); + } else { + name_size = grn_obj_name(ctx, (grn_obj *)pat, buffer, buffer_size); + } + + return name_size; +} + +/* bit operation */ + +#define nth_bit(key,n,l) ((((key)[(n)>>4]) >> (7 - (((n)>>1) & 7))) & 1) + +/* segment operation */ + +/* patricia array operation */ + +#define PAT_AT(pat,id,n) do {\ + int flags = 0;\ + GRN_IO_ARRAY_AT(pat->io, segment_pat, id, &flags, n);\ +} while (0) + +inline static pat_node * +pat_get(grn_ctx *ctx, grn_pat *pat, grn_id id) +{ + pat_node *res; + int flags = GRN_TABLE_ADD; + if (id > GRN_ID_MAX) { return NULL; } + GRN_IO_ARRAY_AT(pat->io, segment_pat, id, &flags, res); + return res; +} + +/* sis operation */ + +inline static sis_node * +sis_at(grn_ctx *ctx, grn_pat *pat, grn_id id) +{ + sis_node *res; + int flags = 0; + if (id > GRN_ID_MAX) { return NULL; } + GRN_IO_ARRAY_AT(pat->io, segment_sis, id, &flags, res); + return res; +} + +inline static sis_node * +sis_get(grn_ctx *ctx, grn_pat *pat, grn_id id) +{ + sis_node *res; + int flags = GRN_TABLE_ADD; + if (id > GRN_ID_MAX) { return NULL; } + GRN_IO_ARRAY_AT(pat->io, segment_sis, id, &flags, res); + return res; +} + +#define MAX_LEVEL 16 + +static void +sis_collect(grn_ctx *ctx, grn_pat *pat, grn_hash *h, grn_id id, uint32_t level) +{ + uint32_t *offset; + sis_node *sl = sis_at(ctx, pat, id); + if (sl) { + grn_id sid = sl->children; + while (sid && sid != id) { + if (grn_hash_add(ctx, h, &sid, sizeof(grn_id), (void **) &offset, NULL)) { + *offset = level; + if (level < MAX_LEVEL) { sis_collect(ctx, pat, h, sid, level + 1); } + if (!(sl = sis_at(ctx, pat, sid))) { break; } + sid = sl->sibling; + } else { + /* todo : must be handled */ + } + } + } +} + +/* key operation */ + +#define KEY_AT(pat,pos,ptr,addp) do {\ + int flags = addp;\ + GRN_IO_ARRAY_AT(pat->io, segment_key, pos, &flags, ptr);\ +} while (0) + +inline static uint32_t +key_put(grn_ctx *ctx, grn_pat *pat, const uint8_t *key, uint32_t len) +{ + uint32_t res, ts; +// if (len >= GRN_PAT_SEGMENT_SIZE) { return 0; /* error */ } + res = pat->header->curr_key; + if (res < GRN_PAT_MAX_TOTAL_KEY_SIZE && + len > GRN_PAT_MAX_TOTAL_KEY_SIZE - res) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_NOT_ENOUGH_SPACE, + "[pat][key][put] total key size is over: <%.*s>: " + "max=%u: current=%u: new key size=%u", + name_size, name, + GRN_PAT_MAX_TOTAL_KEY_SIZE, + res, + len); + return 0; + } + + ts = (res + len) >> W_OF_KEY_IN_A_SEGMENT; + if (res >> W_OF_KEY_IN_A_SEGMENT != ts) { + res = pat->header->curr_key = ts << W_OF_KEY_IN_A_SEGMENT; + } + { + uint8_t *dest; + KEY_AT(pat, res, dest, GRN_TABLE_ADD); + if (!dest) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + name_size = grn_pat_name(ctx, pat, name, GRN_TABLE_MAX_KEY_SIZE); + ERR(GRN_NO_MEMORY_AVAILABLE, + "[pat][key][put] failed to allocate memory for new key: <%.*s>: " + "new offset:%u key size:%u", + name_size, name, + res, + len); + return 0; + } + grn_memcpy(dest, key, len); + } + pat->header->curr_key += len; + return res; +} + +inline static uint8_t * +pat_node_get_key(grn_ctx *ctx, grn_pat *pat, pat_node *n) +{ + if (PAT_IMD(n)) { + return (uint8_t *) &n->key; + } else { + uint8_t *res; + KEY_AT(pat, n->key, res, 0); + return res; + } +} + +inline static grn_rc +pat_node_set_key(grn_ctx *ctx, grn_pat *pat, pat_node *n, const uint8_t *key, uint32_t len) +{ + grn_rc rc; + if (!key || !len) { return GRN_INVALID_ARGUMENT; } + PAT_LEN_SET(n, len); + if (len <= sizeof(uint32_t)) { + PAT_IMD_ON(n); + grn_memcpy(&n->key, key, len); + rc = GRN_SUCCESS; + } else { + PAT_IMD_OFF(n); + n->key = key_put(ctx, pat, key, len); + rc = ctx->rc; + } + return rc; +} + +/* delinfo operation */ + +enum { + /* The delinfo is currently not used. */ + DL_EMPTY = 0, + /* + * stat->d refers to a deleting node (in a tree). + * The deletion requires an additional operation. + */ + DL_PHASE1, + /* + * stat->d refers to a deleted node (not in a tree). + * The node is pending for safety. + */ + DL_PHASE2 +}; + +inline static grn_pat_delinfo * +delinfo_search(grn_pat *pat, grn_id id) +{ + int i; + grn_pat_delinfo *di; + for (i = (pat->header->curr_del2) & GRN_PAT_MDELINFOS; + i != pat->header->curr_del; + i = (i + 1) & GRN_PAT_MDELINFOS) { + di = &pat->header->delinfos[i]; + if (di->stat != DL_PHASE1) { continue; } + if (di->ld == id) { return di; } + if (di->d == id) { return di; } + } + return NULL; +} + +inline static grn_rc +delinfo_turn_2(grn_ctx *ctx, grn_pat *pat, grn_pat_delinfo *di) +{ + grn_id d, *p = NULL; + pat_node *ln, *dn; + // grn_log("delinfo_turn_2> di->d=%d di->ld=%d stat=%d", di->d, di->ld, di->stat); + if (di->stat != DL_PHASE1) { + return GRN_SUCCESS; + } + PAT_AT(pat, di->ld, ln); + if (!ln) { + return GRN_INVALID_ARGUMENT; + } + d = di->d; + if (!d) { + return GRN_INVALID_ARGUMENT; + } + PAT_AT(pat, d, dn); + if (!dn) { + return GRN_INVALID_ARGUMENT; + } + PAT_DEL_OFF(ln); + PAT_DEL_OFF(dn); + { + grn_id *p0; + pat_node *rn; + int c0 = -1, c; + uint32_t len = PAT_LEN(dn) * 16; + const uint8_t *key = pat_node_get_key(ctx, pat, dn); + if (!key) { + return GRN_INVALID_ARGUMENT; + } + PAT_AT(pat, 0, rn); + p0 = &rn->lr[1]; + for (;;) { + grn_id r = *p0; + if (!r) { + break; + } + if (r == d) { + p = p0; + break; + } + PAT_AT(pat, r, rn); + if (!rn) { + return GRN_FILE_CORRUPT; + } + c = PAT_CHK(rn); + if (c <= c0 || len <= c) { + break; + } + if (c & 1) { + p0 = (c + 1 < len) ? &rn->lr[1] : &rn->lr[0]; + } else { + p0 = &rn->lr[nth_bit((uint8_t *)key, c, len)]; + } + c0 = c; + } + } + if (p) { + PAT_CHK_SET(ln, PAT_CHK(dn)); + ln->lr[1] = dn->lr[1]; + ln->lr[0] = dn->lr[0]; + *p = di->ld; + } else { + /* debug */ + int j; + grn_id dd; + grn_pat_delinfo *ddi; + GRN_LOG(ctx, GRN_LOG_DEBUG, "failed to find d=%d", d); + for (j = (pat->header->curr_del2 + 1) & GRN_PAT_MDELINFOS; + j != pat->header->curr_del; + j = (j + 1) & GRN_PAT_MDELINFOS) { + ddi = &pat->header->delinfos[j]; + if (ddi->stat != DL_PHASE1) { continue; } + PAT_AT(pat, ddi->ld, ln); + if (!ln) { continue; } + if (!(dd = ddi->d)) { continue; } + if (d == ddi->ld) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "found!!!, d(%d) become ld of (%d)", d, dd); + } + } + /* debug */ + } + di->stat = DL_PHASE2; + di->d = d; + // grn_log("delinfo_turn_2< di->d=%d di->ld=%d", di->d, di->ld); + return GRN_SUCCESS; +} + +inline static grn_rc +delinfo_turn_3(grn_ctx *ctx, grn_pat *pat, grn_pat_delinfo *di) +{ + pat_node *dn; + uint32_t size; + if (di->stat != DL_PHASE2) { return GRN_SUCCESS; } + PAT_AT(pat, di->d, dn); + if (!dn) { return GRN_INVALID_ARGUMENT; } + if (di->shared) { + PAT_IMD_ON(dn); + size = 0; + } else { + if (PAT_IMD(dn)) { + size = 0; + } else { + size = PAT_LEN(dn); + } + } + di->stat = DL_EMPTY; + // dn->lr[1] = GRN_PAT_DELETED; + dn->lr[0] = pat->header->garbages[size]; + pat->header->garbages[size] = di->d; + return GRN_SUCCESS; +} + +inline static grn_pat_delinfo * +delinfo_new(grn_ctx *ctx, grn_pat *pat) +{ + grn_pat_delinfo *res = &pat->header->delinfos[pat->header->curr_del]; + uint32_t n = (pat->header->curr_del + 1) & GRN_PAT_MDELINFOS; + int gap = ((n + GRN_PAT_NDELINFOS - pat->header->curr_del2) & GRN_PAT_MDELINFOS) + - (GRN_PAT_NDELINFOS / 2); + while (gap-- > 0) { + if (delinfo_turn_2(ctx, pat, &pat->header->delinfos[pat->header->curr_del2])) { + GRN_LOG(ctx, GRN_LOG_CRIT, "d2 failed: %d", pat->header->delinfos[pat->header->curr_del2].ld); + } + pat->header->curr_del2 = (pat->header->curr_del2 + 1) & GRN_PAT_MDELINFOS; + } + if (n == pat->header->curr_del3) { + if (delinfo_turn_3(ctx, pat, &pat->header->delinfos[pat->header->curr_del3])) { + GRN_LOG(ctx, GRN_LOG_CRIT, "d3 failed: %d", pat->header->delinfos[pat->header->curr_del3].ld); + } + pat->header->curr_del3 = (pat->header->curr_del3 + 1) & GRN_PAT_MDELINFOS; + } + pat->header->curr_del = n; + return res; +} + +/* pat operation */ + +inline static grn_pat * +_grn_pat_create(grn_ctx *ctx, grn_pat *pat, + const char *path, uint32_t key_size, + uint32_t value_size, uint32_t flags) { + grn_io *io; + pat_node *node0; + struct grn_pat_header *header; + uint32_t entry_size, w_of_element; + grn_encoding encoding = ctx->encoding; + if (flags & GRN_OBJ_KEY_WITH_SIS) { + entry_size = sizeof(sis_node) + value_size; + } else { + entry_size = value_size; + } + for (w_of_element = 0; (1 << w_of_element) < entry_size; w_of_element++) { + /* nop */ + } + { + grn_io_array_spec array_spec[3]; + array_spec[segment_key].w_of_element = 0; + array_spec[segment_key].max_n_segments = 0x400; + array_spec[segment_pat].w_of_element = 4; + array_spec[segment_pat].max_n_segments = 1 << (30 - (22 - 4)); + array_spec[segment_sis].w_of_element = w_of_element; + array_spec[segment_sis].max_n_segments = 1 << (30 - (22 - w_of_element)); + io = grn_io_create_with_array(ctx, path, sizeof(struct grn_pat_header), + GRN_PAT_SEGMENT_SIZE, grn_io_auto, 3, array_spec); + } + if (!io) { return NULL; } + if (encoding == GRN_ENC_DEFAULT) { encoding = grn_gctx.encoding; } + header = grn_io_header(io); + grn_io_set_type(io, GRN_TABLE_PAT_KEY); + header->flags = flags; + header->encoding = encoding; + header->key_size = key_size; + header->value_size = value_size; + header->n_entries = 0; + header->curr_rec = 0; + header->curr_key = 0; + header->curr_del = 0; + header->curr_del2 = 0; + header->curr_del3 = 0; + header->n_garbages = 0; + header->tokenizer = GRN_ID_NIL; + if (header->flags & GRN_OBJ_KEY_NORMALIZE) { + header->flags &= ~GRN_OBJ_KEY_NORMALIZE; + pat->normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + header->normalizer = grn_obj_id(ctx, pat->normalizer); + } else { + pat->normalizer = NULL; + header->normalizer = GRN_ID_NIL; + } + header->truncated = GRN_FALSE; + GRN_PTR_INIT(&(pat->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL); + pat->io = io; + pat->header = header; + pat->key_size = key_size; + pat->value_size = value_size; + pat->tokenizer = NULL; + pat->encoding = encoding; + pat->obj.header.flags = header->flags; + if (!(node0 = pat_get(ctx, pat, 0))) { + grn_io_close(ctx, io); + return NULL; + } + node0->lr[1] = 0; + node0->lr[0] = 0; + node0->key = 0; + return pat; +} + +grn_pat * +grn_pat_create(grn_ctx *ctx, const char *path, uint32_t key_size, + uint32_t value_size, uint32_t flags) +{ + grn_pat *pat; + if (!(pat = GRN_CALLOC(sizeof(grn_pat)))) { + return NULL; + } + GRN_DB_OBJ_SET_TYPE(pat, GRN_TABLE_PAT_KEY); + if (!_grn_pat_create(ctx, pat, path, key_size, value_size, flags)) { + GRN_FREE(pat); + return NULL; + } + pat->cache = NULL; + pat->cache_size = 0; + pat->is_dirty = GRN_FALSE; + CRITICAL_SECTION_INIT(pat->lock); + return pat; +} + +/* + grn_pat_cache_enable() and grn_pat_cache_disable() are not thread-safe. + So far, they can be used only from single threaded programs. + */ + +grn_rc +grn_pat_cache_enable(grn_ctx *ctx, grn_pat *pat, uint32_t cache_size) +{ + if (pat->cache || pat->cache_size) { + ERR(GRN_INVALID_ARGUMENT, "cache is already enabled"); + return ctx->rc; + } + if (cache_size & (cache_size - 1)) { + ERR(GRN_INVALID_ARGUMENT, "cache_size(%u) must be a power of two", cache_size); + return ctx->rc; + } + if (!(pat->cache = GRN_CALLOC(cache_size * sizeof(grn_id)))) { + return ctx->rc; + } + pat->cache_size = cache_size; + return GRN_SUCCESS; +} + +void +grn_pat_cache_disable(grn_ctx *ctx, grn_pat *pat) +{ + if (pat->cache) { + GRN_FREE(pat->cache); + pat->cache_size = 0; + pat->cache = NULL; + } +} + +grn_pat * +grn_pat_open(grn_ctx *ctx, const char *path) +{ + grn_io *io; + grn_pat *pat; + pat_node *node0; + struct grn_pat_header *header; + uint32_t io_type; + io = grn_io_open(ctx, path, grn_io_auto); + if (!io) { return NULL; } + header = grn_io_header(io); + io_type = grn_io_get_type(io); + if (io_type != GRN_TABLE_PAT_KEY) { + ERR(GRN_INVALID_FORMAT, "[table][pat] file type must be %#04x: <%#04x>", + GRN_TABLE_PAT_KEY, io_type); + grn_io_close(ctx, io); + return NULL; + } + if (!(pat = GRN_MALLOC(sizeof(grn_pat)))) { + grn_io_close(ctx, io); + return NULL; + } + GRN_DB_OBJ_SET_TYPE(pat, GRN_TABLE_PAT_KEY); + pat->io = io; + pat->header = header; + pat->key_size = header->key_size; + pat->value_size = header->value_size; + pat->encoding = header->encoding; + pat->tokenizer = grn_ctx_at(ctx, header->tokenizer); + if (header->flags & GRN_OBJ_KEY_NORMALIZE) { + header->flags &= ~GRN_OBJ_KEY_NORMALIZE; + pat->normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + header->normalizer = grn_obj_id(ctx, pat->normalizer); + } else { + pat->normalizer = grn_ctx_at(ctx, header->normalizer); + } + GRN_PTR_INIT(&(pat->token_filters), GRN_OBJ_VECTOR, GRN_ID_NIL); + pat->obj.header.flags = header->flags; + PAT_AT(pat, 0, node0); + if (!node0) { + grn_io_close(ctx, io); + GRN_FREE(pat); + return NULL; + } + pat->cache = NULL; + pat->cache_size = 0; + pat->is_dirty = GRN_FALSE; + CRITICAL_SECTION_INIT(pat->lock); + return pat; +} + +/* + * grn_pat_error_if_truncated() logs an error and returns its error code if + * a pat is truncated by another process. + * Otherwise, this function returns GRN_SUCCESS. + * Note that `ctx` and `pat` must be valid. + * + * FIXME: A pat should be reopened if possible. + */ +static grn_rc +grn_pat_error_if_truncated(grn_ctx *ctx, grn_pat *pat) +{ + if (pat->header->truncated) { + ERR(GRN_FILE_CORRUPT, + "pat is truncated, please unmap or reopen the database"); + return GRN_FILE_CORRUPT; + } + return GRN_SUCCESS; +} + +grn_rc +grn_pat_close(grn_ctx *ctx, grn_pat *pat) +{ + grn_rc rc; + + CRITICAL_SECTION_FIN(pat->lock); + + if (pat->is_dirty) { + uint32_t n_dirty_opens; + GRN_ATOMIC_ADD_EX(&(pat->header->n_dirty_opens), -1, n_dirty_opens); + } + + if ((rc = grn_io_close(ctx, pat->io))) { + ERR(rc, "grn_io_close failed"); + } else { + grn_pvector_fin(ctx, &pat->token_filters); + if (pat->cache) { grn_pat_cache_disable(ctx, pat); } + GRN_FREE(pat); + } + + return rc; +} + +grn_rc +grn_pat_remove(grn_ctx *ctx, const char *path) +{ + if (!path) { + ERR(GRN_INVALID_ARGUMENT, "path is null"); + return GRN_INVALID_ARGUMENT; + } + return grn_io_remove(ctx, path); +} + +grn_rc +grn_pat_truncate(grn_ctx *ctx, grn_pat *pat) +{ + grn_rc rc; + const char *io_path; + char *path; + uint32_t key_size, value_size, flags; + + rc = grn_pat_error_if_truncated(ctx, pat); + if (rc != GRN_SUCCESS) { + return rc; + } + if ((io_path = grn_io_path(pat->io)) && *io_path != '\0') { + if (!(path = GRN_STRDUP(io_path))) { + ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path); + return GRN_NO_MEMORY_AVAILABLE; + } + } else { + path = NULL; + } + key_size = pat->key_size; + value_size = pat->value_size; + flags = pat->obj.header.flags; + if (path) { + pat->header->truncated = GRN_TRUE; + } + if ((rc = grn_io_close(ctx, pat->io))) { goto exit; } + grn_pvector_fin(ctx, &pat->token_filters); + pat->io = NULL; + if (path && (rc = grn_io_remove(ctx, path))) { goto exit; } + if (!_grn_pat_create(ctx, pat, path, key_size, value_size, flags)) { + rc = GRN_UNKNOWN_ERROR; + } + if (pat->cache && pat->cache_size) { + memset(pat->cache, 0, pat->cache_size * sizeof(grn_id)); + } +exit: + if (path) { GRN_FREE(path); } + return rc; +} + +inline static grn_id +_grn_pat_add(grn_ctx *ctx, grn_pat *pat, const uint8_t *key, uint32_t size, uint32_t *new, uint32_t *lkey) +{ + grn_id r, r0, *p0, *p1 = NULL; + pat_node *rn, *rn0; + int c, c0 = -1, c1 = -1, len; + uint32_t cache_id = 0; + + *new = 0; + if (pat->cache) { + const uint8_t *p = key; + uint32_t length = size; + for (cache_id = 0; length--; p++) { cache_id = (cache_id * 37) + *p; } + cache_id &= (pat->cache_size - 1); + if (pat->cache[cache_id]) { + PAT_AT(pat, pat->cache[cache_id], rn); + if (rn) { + const uint8_t *k = pat_node_get_key(ctx, pat, rn); + if (k && size == PAT_LEN(rn) && !memcmp(k, key, size)) { + return pat->cache[cache_id]; + } + } + } + } + + len = (int)size * 16; + PAT_AT(pat, 0, rn0); + p0 = &rn0->lr[1]; + if (*p0) { + uint32_t size2; + int xor, mask; + const uint8_t *s, *d; + for (;;) { + if (!(r0 = *p0)) { + if (!(s = pat_node_get_key(ctx, pat, rn0))) { return GRN_ID_NIL; } + size2 = PAT_LEN(rn0); + break; + } + PAT_AT(pat, r0, rn0); + if (!rn0) { return GRN_ID_NIL; } + if (c0 < rn0->check && rn0->check < len) { + c1 = c0; c0 = rn0->check; + p1 = p0; + if (c0 & 1) { + p0 = (c0 + 1 < len) ? &rn0->lr[1] : &rn0->lr[0]; + } else { + p0 = &rn0->lr[nth_bit(key, c0, len)]; + } + } else { + if (!(s = pat_node_get_key(ctx, pat, rn0))) { return GRN_ID_NIL; } + size2 = PAT_LEN(rn0); + if (size == size2 && !memcmp(s, key, size)) { + if (pat->cache) { pat->cache[cache_id] = r0; } + return r0; + } + break; + } + } + { + uint32_t min = size > size2 ? size2 : size; + for (c = 0, d = key; min && *s == *d; c += 16, s++, d++, min--); + if (min) { + for (xor = *s ^ *d, mask = 0x80; !(xor & mask); mask >>= 1, c += 2); + } else { + c--; + } + } + if (c == c0 && !*p0) { + if (c < len - 2) { c += 2; } + } else { + if (c < c0) { + if (c > c1) { + p0 = p1; + } else { + PAT_AT(pat, 0, rn0); + p0 = &rn0->lr[1]; + while ((r0 = *p0)) { + PAT_AT(pat, r0, rn0); + if (!rn0) { return GRN_ID_NIL; } + c0 = PAT_CHK(rn0); + if (c < c0) { break; } + if (c0 & 1) { + p0 = (c0 + 1 < len) ? &rn0->lr[1] : &rn0->lr[0]; + } else { + p0 = &rn0->lr[nth_bit(key, c0, len)]; + } + } + } + } + } + if (c >= len) { return GRN_ID_NIL; } + } else { + c = len - 2; + } + { + uint32_t size2 = size > sizeof(uint32_t) ? size : 0; + if (*lkey && size2) { + if (pat->header->garbages[0]) { + r = pat->header->garbages[0]; + PAT_AT(pat, r, rn); + if (!rn) { return GRN_ID_NIL; } + pat->header->n_entries++; + pat->header->n_garbages--; + pat->header->garbages[0] = rn->lr[0]; + } else { + r = pat->header->curr_rec + 1; + rn = pat_get(ctx, pat, r); + if (!rn) { return GRN_ID_NIL; } + pat->header->curr_rec = r; + pat->header->n_entries++; + } + PAT_IMD_OFF(rn); + PAT_LEN_SET(rn, size); + rn->key = *lkey; + } else { + if (pat->header->garbages[size2]) { + uint8_t *keybuf; + r = pat->header->garbages[size2]; + PAT_AT(pat, r, rn); + if (!rn) { return GRN_ID_NIL; } + if (!(keybuf = pat_node_get_key(ctx, pat, rn))) { return GRN_ID_NIL; } + pat->header->n_entries++; + pat->header->n_garbages--; + pat->header->garbages[size2] = rn->lr[0]; + PAT_LEN_SET(rn, size); + grn_memcpy(keybuf, key, size); + } else { + r = pat->header->curr_rec + 1; + rn = pat_get(ctx, pat, r); + if (!rn) { return GRN_ID_NIL; } + if (pat_node_set_key(ctx, pat, rn, key, size)) { return GRN_ID_NIL; } + pat->header->curr_rec = r; + pat->header->n_entries++; + } + *lkey = rn->key; + } + } + PAT_CHK_SET(rn, c); + PAT_DEL_OFF(rn); + if ((c & 1) ? (c + 1 < len) : nth_bit(key, c, len)) { + rn->lr[1] = r; + rn->lr[0] = *p0; + } else { + rn->lr[1] = *p0; + rn->lr[0] = r; + } + // smp_wmb(); + *p0 = r; + *new = 1; + if (pat->cache) { pat->cache[cache_id] = r; } + return r; +} + +inline static grn_bool +chop(grn_ctx *ctx, grn_pat *pat, const char **key, const char *end, uint32_t *lkey) +{ + size_t len = grn_charlen(ctx, *key, end); + if (len) { + *lkey += len; + *key += len; + return (end - *key) > 0; + } else { + return GRN_FALSE; + } +} + +#define MAX_FIXED_KEY_SIZE (sizeof(int64_t)) + +#define KEY_NEEDS_CONVERT(pat,size) \ + (!((pat)->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE) && (size) <= MAX_FIXED_KEY_SIZE) + +#define KEY_ENC(pat,keybuf,key,size) do {\ + switch ((pat)->obj.header.flags & GRN_OBJ_KEY_MASK) {\ + case GRN_OBJ_KEY_UINT :\ + if (((pat)->obj.header.domain != GRN_DB_TOKYO_GEO_POINT) &&\ + ((pat)->obj.header.domain != GRN_DB_WGS84_GEO_POINT)) {\ + grn_hton((keybuf), (key), (size));\ + break;\ + }\ + case GRN_OBJ_KEY_GEO_POINT :\ + grn_gton((keybuf), (key), (size));\ + break;\ + case GRN_OBJ_KEY_INT :\ + grn_hton((keybuf), (key), (size));\ + *((uint8_t *)(keybuf)) ^= 0x80;\ + break;\ + case GRN_OBJ_KEY_FLOAT :\ + if ((size) == sizeof(int64_t)) {\ + int64_t v = *(int64_t *)(key);\ + v ^= ((v >> 63)|(1ULL << 63));\ + grn_hton((keybuf), &v, (size));\ + }\ + break;\ + }\ +} while (0) + +#define KEY_DEC(pat,keybuf,key,size) do {\ + switch ((pat)->obj.header.flags & GRN_OBJ_KEY_MASK) {\ + case GRN_OBJ_KEY_UINT :\ + if (((pat)->obj.header.domain != GRN_DB_TOKYO_GEO_POINT) &&\ + ((pat)->obj.header.domain != GRN_DB_WGS84_GEO_POINT)) {\ + grn_ntoh((keybuf), (key), (size));\ + break;\ + }\ + case GRN_OBJ_KEY_GEO_POINT :\ + grn_ntog((keybuf), (key), (size));\ + break;\ + case GRN_OBJ_KEY_INT :\ + grn_ntohi((keybuf), (key), (size));\ + break;\ + case GRN_OBJ_KEY_FLOAT :\ + if ((size) == sizeof(int64_t)) {\ + int64_t v;\ + grn_hton(&v, (key), (size));\ + *((int64_t *)(keybuf)) = v ^ ((((int64_t)(v^(1ULL<<63)))>> 63)|(1ULL<<63)); \ + }\ + break;\ + }\ +} while (0) + +#define KEY_ENCODE(pat,keybuf,key,size) do {\ + if (KEY_NEEDS_CONVERT(pat,size)) {\ + KEY_ENC((pat), (keybuf), (key), (size));\ + (key) = (keybuf);\ + }\ +} while (0) + +grn_id +grn_pat_add(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size, + void **value, int *added) +{ + uint32_t new, lkey = 0; + grn_id r0; + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + if (!key || !key_size) { return GRN_ID_NIL; } + if (key_size > GRN_TABLE_MAX_KEY_SIZE) { + ERR(GRN_INVALID_ARGUMENT, "too long key: (%u)", key_size); + return GRN_ID_NIL; + } + KEY_ENCODE(pat, keybuf, key, key_size); + r0 = _grn_pat_add(ctx, pat, (uint8_t *)key, key_size, &new, &lkey); + if (r0 == GRN_ID_NIL) { return GRN_ID_NIL; } + if (added) { *added = new; } + if (r0 && (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) && + (*((uint8_t *)key) & 0x80)) { // todo: refine!! + sis_node *sl, *sr; + grn_id l = r0, r; + if (new && (sl = sis_get(ctx, pat, l))) { + const char *sis = key, *end = sis + key_size; + sl->children = l; + sl->sibling = 0; + while (chop(ctx, pat, &sis, end, &lkey)) { + if (!(*sis & 0x80)) { break; } + if (!(r = _grn_pat_add(ctx, pat, (uint8_t *)sis, end - sis, &new, &lkey))) { + break; + } + if (!(sr = sis_get(ctx, pat, r))) { break; } + if (new) { + sl->sibling = r; + sr->children = l; + sr->sibling = 0; + } else { + sl->sibling = sr->children; + sr->children = l; + break; + } + l = r; + sl = sr; + } + } + } + if (r0 && value) { + byte *v = (byte *)sis_get(ctx, pat, r0); + if (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) { + *value = v + sizeof(sis_node); + } else { + *value = v; + } + } + return r0; +} + +inline static grn_id +_grn_pat_get(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size, void **value) +{ + grn_id r; + pat_node *rn; + int c0 = -1, c; + uint32_t len = key_size * 16; + PAT_AT(pat, 0, rn); + for (r = rn->lr[1]; r;) { + PAT_AT(pat, r, rn); + if (!rn) { break; /* corrupt? */ } + c = PAT_CHK(rn); + if (len <= c) { break; } + if (c <= c0) { + const uint8_t *k = pat_node_get_key(ctx, pat, rn); + if (k && key_size == PAT_LEN(rn) && !memcmp(k, key, key_size)) { + if (value) { + byte *v = (byte *)sis_get(ctx, pat, r); + if (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) { + *value = v + sizeof(sis_node); + } else { + *value = v; + } + } + return r; + } + break; + } + if (c & 1) { + r = (c + 1 < len) ? rn->lr[1] : rn->lr[0]; + } else { + r = rn->lr[nth_bit((uint8_t *)key, c, len)]; + } + c0 = c; + } + return GRN_ID_NIL; +} + +grn_id +grn_pat_get(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size, void **value) +{ + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + KEY_ENCODE(pat, keybuf, key, key_size); + return _grn_pat_get(ctx, pat, key, key_size, value); +} + +grn_id +grn_pat_nextid(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size) +{ + grn_id r = GRN_ID_NIL; + if (pat && key) { + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + if (!(r = pat->header->garbages[key_size > sizeof(uint32_t) ? key_size : 0])) { + r = pat->header->curr_rec + 1; + } + } + return r; +} + +static void +get_tc(grn_ctx *ctx, grn_pat *pat, grn_hash *h, pat_node *rn) +{ + grn_id id; + pat_node *node; + id = rn->lr[1]; + if (id) { + PAT_AT(pat, id, node); + if (node) { + if (PAT_CHK(node) > PAT_CHK(rn)) { + get_tc(ctx, pat, h, node); + } else { + grn_hash_add(ctx, h, &id, sizeof(grn_id), NULL, NULL); + } + } + } + id = rn->lr[0]; + if (id) { + PAT_AT(pat, id, node); + if (node) { + if (PAT_CHK(node) > PAT_CHK(rn)) { + get_tc(ctx, pat, h, node); + } else { + grn_hash_add(ctx, h, &id, sizeof(grn_id), NULL, NULL); + } + } + } +} + +grn_rc +grn_pat_prefix_search(grn_ctx *ctx, grn_pat *pat, + const void *key, uint32_t key_size, grn_hash *h) +{ + int c0 = -1, c; + const uint8_t *k; + uint32_t len = key_size * 16; + grn_id r; + pat_node *rn; + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + grn_rc rc = grn_pat_error_if_truncated(ctx, pat); + if (rc != GRN_SUCCESS) { + return rc; + } + KEY_ENCODE(pat, keybuf, key, key_size); + PAT_AT(pat, 0, rn); + r = rn->lr[1]; + while (r) { + PAT_AT(pat, r, rn); + if (!rn) { return GRN_FILE_CORRUPT; } + c = PAT_CHK(rn); + if (c0 < c && c < len - 1) { + if (c & 1) { + r = (c + 1 < len) ? rn->lr[1] : rn->lr[0]; + } else { + r = rn->lr[nth_bit((uint8_t *)key, c, len)]; + } + c0 = c; + continue; + } + if (!(k = pat_node_get_key(ctx, pat, rn))) { break; } + if (PAT_LEN(rn) < key_size) { break; } + if (!memcmp(k, key, key_size)) { + if (c >= len - 1) { + get_tc(ctx, pat, h, rn); + } else { + grn_hash_add(ctx, h, &r, sizeof(grn_id), NULL, NULL); + } + return GRN_SUCCESS; + } + break; + } + return GRN_END_OF_DATA; +} + +grn_hash * +grn_pat_prefix_search2(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size) +{ + grn_hash *h; + if (!pat || !key) { return NULL; } + if ((h = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, 0))) { + if (grn_pat_prefix_search(ctx, pat, key, key_size, h)) { + grn_hash_close(ctx, h); + h = NULL; + } + } + return h; +} + +grn_rc +grn_pat_suffix_search(grn_ctx *ctx, grn_pat *pat, + const void *key, uint32_t key_size, grn_hash *h) +{ + grn_id r; + if ((r = grn_pat_get(ctx, pat, key, key_size, NULL))) { + uint32_t *offset; + if (grn_hash_add(ctx, h, &r, sizeof(grn_id), (void **) &offset, NULL)) { + *offset = 0; + if (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) { sis_collect(ctx, pat, h, r, 1); } + return GRN_SUCCESS; + } + } + return GRN_END_OF_DATA; +} + +grn_hash * +grn_pat_suffix_search2(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size) +{ + grn_hash *h; + if (!pat || !key) { return NULL; } + if ((h = grn_hash_create(ctx, NULL, sizeof(grn_id), sizeof(uint32_t), 0))) { + if (grn_pat_suffix_search(ctx, pat, key, key_size, h)) { + grn_hash_close(ctx, h); + h = NULL; + } + } + return h; +} + +grn_id +grn_pat_lcp_search(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size) +{ + pat_node *rn; + grn_id r, r2 = GRN_ID_NIL; + uint32_t len = key_size * 16; + int c0 = -1, c; + if (!pat || !key) { + return GRN_ID_NIL; + } + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + if (!(pat->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE)) { return GRN_ID_NIL; } + PAT_AT(pat, 0, rn); + for (r = rn->lr[1]; r;) { + PAT_AT(pat, r, rn); + if (!rn) { break; /* corrupt? */ } + c = PAT_CHK(rn); + if (c <= c0) { + if (PAT_LEN(rn) <= key_size) { + uint8_t *p = pat_node_get_key(ctx, pat, rn); + if (!p) { break; } + if (!memcmp(p, key, PAT_LEN(rn))) { return r; } + } + break; + } + if (len <= c) { break; } + if (c & 1) { + uint8_t *p; + pat_node *rn0; + grn_id r0 = rn->lr[0]; + PAT_AT(pat, r0, rn0); + if (!rn0) { break; /* corrupt? */ } + p = pat_node_get_key(ctx, pat, rn0); + if (!p) { break; } + if (PAT_LEN(rn0) <= key_size && !memcmp(p, key, PAT_LEN(rn0))) { r2 = r0; } + r = (c + 1 < len) ? rn->lr[1] : rn->lr[0]; + } else { + r = rn->lr[nth_bit((uint8_t *)key, c, len)]; + } + c0 = c; + } + return r2; +} + +static grn_id +common_prefix_pat_node_get(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size) +{ + int c0 = -1, c; + const uint8_t *k; + uint32_t len = key_size * 16; + grn_id r; + pat_node *rn; + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + + KEY_ENCODE(pat, keybuf, key, key_size); + PAT_AT(pat, 0, rn); + r = rn->lr[1]; + while (r) { + PAT_AT(pat, r, rn); + if (!rn) { return GRN_ID_NIL; } + c = PAT_CHK(rn); + if (c0 < c && c < len - 1) { + if (c & 1) { + r = (c + 1 < len) ? rn->lr[1] : rn->lr[0]; + } else { + r = rn->lr[nth_bit((uint8_t *)key, c, len)]; + } + c0 = c; + continue; + } + if (!(k = pat_node_get_key(ctx, pat, rn))) { break; } + if (PAT_LEN(rn) < key_size) { break; } + if (!memcmp(k, key, key_size)) { + return r; + } + break; + } + return GRN_ID_NIL; +} + +typedef struct { + grn_id id; + uint16_t distance; +} fuzzy_heap_node; + +typedef struct { + int n_entries; + int limit; + fuzzy_heap_node *nodes; +} fuzzy_heap; + +static inline fuzzy_heap * +fuzzy_heap_open(grn_ctx *ctx, int max) +{ + fuzzy_heap *h = GRN_MALLOC(sizeof(fuzzy_heap)); + if (!h) { return NULL; } + h->nodes = GRN_MALLOC(sizeof(fuzzy_heap_node) * max); + if (!h->nodes) { + GRN_FREE(h); + return NULL; + } + h->n_entries = 0; + h->limit = max; + return h; +} + +static inline grn_bool +fuzzy_heap_push(grn_ctx *ctx, fuzzy_heap *h, grn_id id, uint16_t distance) +{ + int n, n2; + fuzzy_heap_node node = {id, distance}; + fuzzy_heap_node node2; + if (h->n_entries >= h->limit) { + int max = h->limit * 2; + fuzzy_heap_node *nodes = GRN_REALLOC(h->nodes, sizeof(fuzzy_heap) * max); + if (!h) { + return GRN_FALSE; + } + h->limit = max; + h->nodes = nodes; + } + h->nodes[h->n_entries] = node; + n = h->n_entries++; + while (n) { + n2 = (n - 1) >> 1; + if (h->nodes[n2].distance <= h->nodes[n].distance) { break; } + node2 = h->nodes[n]; + h->nodes[n] = h->nodes[n2]; + h->nodes[n2] = node2; + n = n2; + } + return GRN_TRUE; +} + +static inline void +fuzzy_heap_close(grn_ctx *ctx, fuzzy_heap *h) +{ + GRN_FREE(h->nodes); + GRN_FREE(h); +} + +#define DIST(ox,oy) (dists[((lx + 1) * (oy)) + (ox)]) + +inline static uint16_t +calc_edit_distance_by_offset(grn_ctx *ctx, + const char *sx, const char *ex, + const char *sy, const char *ey, + uint16_t *dists, uint32_t lx, + uint32_t offset, uint32_t max_distance, + grn_bool *can_transition, int flags) +{ + uint32_t cx, cy, x, y; + const char *px, *py; + + /* Skip already calculated rows */ + for (py = sy, y = 1; py < ey && (cy = grn_charlen(ctx, py, ey)); py += cy, y++) { + if (py - sy >= offset) { + break; + } + } + for (; py < ey && (cy = grn_charlen(ctx, py, ey)); py += cy, y++) { + /* children nodes will be no longer smaller than max distance + * with only insertion costs. + * This is end of row on allocated memory. */ + if (y > lx + max_distance) { + *can_transition = GRN_FALSE; + return max_distance + 1; + } + + for (px = sx, x = 1; px < ex && (cx = grn_charlen(ctx, px, ex)); px += cx, x++) { + if (cx == cy && !memcmp(px, py, cx)) { + DIST(x, y) = DIST(x - 1, y - 1); + } else { + uint32_t a, b, c; + a = DIST(x - 1, y) + 1; + b = DIST(x, y - 1) + 1; + c = DIST(x - 1, y - 1) + 1; + DIST(x, y) = ((a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c)); + if (flags & GRN_TABLE_FUZZY_SEARCH_WITH_TRANSPOSITION && + x > 1 && y > 1 && + cx == cy && + memcmp(px, py - cy, cx) == 0 && + memcmp(px - cx, py, cx) == 0) { + uint32_t t = DIST(x - 2, y - 2) + 1; + DIST(x, y) = ((DIST(x, y) < t) ? DIST(x, y) : t); + } + } + } + } + if (lx) { + /* If there is no cell which is smaller than equal to max distance on end of row, + * children nodes will be no longer smaller than max distance */ + *can_transition = GRN_FALSE; + for (x = 1; x <= lx; x++) { + if (DIST(x, y - 1) <= max_distance) { + *can_transition = GRN_TRUE; + break; + } + } + } + return DIST(lx, y - 1); +} + +typedef struct { + const char *key; + int key_length; + grn_bool can_transition; +} fuzzy_node; + +inline static void +_grn_pat_fuzzy_search(grn_ctx *ctx, grn_pat *pat, grn_id id, + const char *key, uint32_t key_size, + uint16_t *dists, uint32_t lx, + int last_check, fuzzy_node *last_node, + uint32_t max_distance, int flags, fuzzy_heap *heap) +{ + pat_node *node = NULL; + int check, len; + const char *k; + uint32_t offset = 0; + + PAT_AT(pat, id, node); + if (!node) { + return; + } + check = PAT_CHK(node); + len = PAT_LEN(node); + k = pat_node_get_key(ctx, pat, node); + + if (check > last_check) { + if (len >= last_node->key_length && + !memcmp(k, last_node->key, last_node->key_length)) { + if (last_node->can_transition == GRN_FALSE) { + return; + } + } + _grn_pat_fuzzy_search(ctx, pat, node->lr[0], + key, key_size, dists, lx, + check, last_node, + max_distance, flags, heap); + + _grn_pat_fuzzy_search(ctx, pat, node->lr[1], + key, key_size, dists, lx, + check, last_node, + max_distance, flags, heap); + } else { + if (id) { + /* Set already calculated common prefix length */ + if (len >= last_node->key_length && + !memcmp(k, last_node->key, last_node->key_length)) { + if (last_node->can_transition == GRN_FALSE) { + return; + } + offset = last_node->key_length; + } else { + if (last_node->can_transition == GRN_FALSE) { + last_node->can_transition = GRN_TRUE; + } + if (last_node->key_length) { + const char *kp = k; + const char *ke = k + len; + const char *p = last_node->key; + const char *e = last_node->key + last_node->key_length; + int lp; + for (;p < e && kp < ke && (lp = grn_charlen(ctx, p, e)); + p += lp, kp += lp) { + if (p + lp <= e && kp + lp <= ke && memcmp(p, kp, lp)) { + break; + } + } + offset = kp - k; + } + } + if (len - offset) { + uint16_t distance; + distance = + calc_edit_distance_by_offset(ctx, + key, key + key_size, + k, k + len, + dists, lx, + offset, max_distance, + &(last_node->can_transition), flags); + if (distance <= max_distance) { + fuzzy_heap_push(ctx, heap, id, distance); + } + } + last_node->key = k; + last_node->key_length = len; + } + } + return; +} + +#define HEAP_SIZE 256 + +grn_rc +grn_pat_fuzzy_search(grn_ctx *ctx, grn_pat *pat, + const void *key, uint32_t key_size, + grn_fuzzy_search_optarg *args, grn_hash *h) +{ + pat_node *node; + grn_id id; + uint16_t *dists; + uint32_t lx, len, x, y, i; + const char *s = key; + const char *e = (const char *)key + key_size; + fuzzy_node last_node; + fuzzy_heap *heap; + uint32_t max_distance = 1; + uint32_t max_expansion = 0; + uint32_t prefix_match_size = 0; + int flags = 0; + grn_rc rc = grn_pat_error_if_truncated(ctx, pat); + if (rc != GRN_SUCCESS) { + return rc; + } + if (args) { + max_distance = args->max_distance; + max_expansion = args->max_expansion; + prefix_match_size = args->prefix_match_size; + flags = args->flags; + } + if (key_size > GRN_TABLE_MAX_KEY_SIZE || + max_distance > GRN_TABLE_MAX_KEY_SIZE || + prefix_match_size > key_size) { + return GRN_INVALID_ARGUMENT; + } + + heap = fuzzy_heap_open(ctx, HEAP_SIZE); + if (!heap) { + return GRN_NO_MEMORY_AVAILABLE; + } + + PAT_AT(pat, GRN_ID_NIL, node); + id = node->lr[1]; + + if (prefix_match_size) { + grn_id tid; + tid = common_prefix_pat_node_get(ctx, pat, key, prefix_match_size); + if (tid != GRN_ID_NIL) { + id = tid; + } else { + return GRN_END_OF_DATA; + } + } + for (lx = 0; s < e && (len = grn_charlen(ctx, s, e)); s += len) { + lx++; + } + dists = GRN_MALLOC((lx + 1) * (lx + max_distance + 1) * sizeof(uint16_t)); + if (!dists) { + return GRN_NO_MEMORY_AVAILABLE; + } + + for (x = 0; x <= lx; x++) { DIST(x, 0) = x; } + for (y = 0; y <= lx + max_distance ; y++) { DIST(0, y) = y; } + + last_node.key = NULL; + last_node.key_length = 0; + last_node.can_transition = GRN_TRUE; + _grn_pat_fuzzy_search(ctx, pat, id, + key, key_size, dists, lx, + -1, &last_node, max_distance, flags, heap); + GRN_FREE(dists); + for (i = 0; i < heap->n_entries; i++) { + if (max_expansion > 0 && i >= max_expansion) { + break; + } + if (DB_OBJ(h)->header.flags & GRN_OBJ_WITH_SUBREC) { + grn_rset_recinfo *ri; + if (grn_hash_add(ctx, h, &(heap->nodes[i].id), sizeof(grn_id), (void **)&ri, NULL)) { + ri->score = max_distance - heap->nodes[i].distance + 1; + } + } else { + grn_hash_add(ctx, h, &(heap->nodes[i].id), sizeof(grn_id), NULL, NULL); + } + } + fuzzy_heap_close(ctx, heap); + if (grn_hash_size(ctx, h)) { + return GRN_SUCCESS; + } else { + return GRN_END_OF_DATA; + } +} + +inline static grn_rc +_grn_pat_del(grn_ctx *ctx, grn_pat *pat, const char *key, uint32_t key_size, int shared, + grn_table_delete_optarg *optarg) +{ + grn_pat_delinfo *di; + pat_node *rn, *rn0 = NULL, *rno = NULL; + int c = -1, c0 = -1, ch; + uint32_t len = key_size * 16; + grn_id r, otherside, *proot, *p, *p0 = NULL; + + /* delinfo_new() must be called before searching for rn. */ + di = delinfo_new(ctx, pat); + di->shared = shared; + + /* + * Search a patricia tree for a given key. + * If the key exists, get its output node. + * + * rn, rn0: the output node and its previous node. + * rno: the other side of rn (the other destination of rn0). + * c, c0: checks of rn0 and its previous node. + * p, p0: pointers to transitions (IDs) that refer to rn and rn0. + */ + PAT_AT(pat, 0, rn); + proot = p = &rn->lr[1]; + for (;;) { + r = *p; + if (!r) { + return GRN_INVALID_ARGUMENT; + } + PAT_AT(pat, r, rn); + if (!rn) { + return GRN_FILE_CORRUPT; + } + ch = PAT_CHK(rn); + if (len <= ch) { + return GRN_INVALID_ARGUMENT; + } + if (c >= ch) { + /* Output node found. */ + const uint8_t *k = pat_node_get_key(ctx, pat, rn); + if (!k) { + return GRN_INVALID_ARGUMENT; + } + if (key_size != PAT_LEN(rn) || memcmp(k, key, key_size)) { + return GRN_INVALID_ARGUMENT; + } + /* Given key found. */ + break; + } + c0 = c; + p0 = p; + c = ch; + if (c & 1) { + p = (c + 1 < len) ? &rn->lr[1] : &rn->lr[0]; + } else { + p = &rn->lr[nth_bit((uint8_t *)key, c, len)]; + } + rn0 = rn; + } + if (optarg && optarg->func && + !optarg->func(ctx, (grn_obj *)pat, r, optarg->func_arg)) { + return GRN_SUCCESS; + } + if (rn0->lr[0] == rn0->lr[1]) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "*p0 (%d), rn0->lr[0] == rn0->lr[1] (%d)", + *p0, rn0->lr[0]); + return GRN_FILE_CORRUPT; + } + otherside = (rn0->lr[1] == r) ? rn0->lr[0] : rn0->lr[1]; + if (otherside) { + PAT_AT(pat, otherside, rno); + if (!rno) { + return GRN_FILE_CORRUPT; + } + } + + if (rn == rn0) { + /* The last transition (p) is a self-loop. */ + di->stat = DL_PHASE2; + di->d = r; + if (otherside) { + if (c0 < PAT_CHK(rno) && PAT_CHK(rno) <= c) { + /* To keep rno as an output node, its check is set to zero. */ + if (!delinfo_search(pat, otherside)) { + GRN_LOG(ctx, GRN_LOG_DEBUG, "no delinfo found %d", otherside); + } + PAT_CHK_SET(rno, 0); + } + if (proot == p0 && !rno->check) { + /* + * Update rno->lr because the first node, rno becomes the new first + * node, is not an output node even if its check is zero. + */ + const uint8_t *k = pat_node_get_key(ctx, pat, rno); + int direction = k ? (*k >> 7) : 1; + rno->lr[direction] = otherside; + rno->lr[!direction] = 0; + } + } + *p0 = otherside; + } else if ((!rn->lr[0] && rn->lr[1] == r) || + (!rn->lr[1] && rn->lr[0] == r)) { + /* The output node has only a disabled self-loop. */ + di->stat = DL_PHASE2; + di->d = r; + *p = 0; + } else { + /* The last transition (p) is not a self-loop. */ + grn_pat_delinfo *ldi = NULL, *ddi = NULL; + if (PAT_DEL(rn)) { + ldi = delinfo_search(pat, r); + } + if (PAT_DEL(rn0)) { + ddi = delinfo_search(pat, *p0); + } + if (ldi) { + PAT_DEL_OFF(rn); + di->stat = DL_PHASE2; + if (ddi) { + PAT_DEL_OFF(rn0); + ddi->stat = DL_PHASE2; + if (ddi == ldi) { + if (r != ddi->ld) { + GRN_LOG(ctx, GRN_LOG_ERROR, "r(%d) != ddi->ld(%d)", r, ddi->ld); + } + di->d = r; + } else { + ldi->ld = ddi->ld; + di->d = r; + } + } else { + PAT_DEL_ON(rn0); + ldi->ld = *p0; + di->d = r; + } + } else { + PAT_DEL_ON(rn); + if (ddi) { + if (ddi->d != *p0) { + GRN_LOG(ctx, GRN_LOG_ERROR, "ddi->d(%d) != *p0(%d)", ddi->d, *p0); + } + PAT_DEL_OFF(rn0); + ddi->stat = DL_PHASE2; + di->stat = DL_PHASE1; + di->ld = ddi->ld; + di->d = r; + /* + PAT_DEL_OFF(rn0); + ddi->d = r; + di->stat = DL_PHASE2; + di->d = *p0; + */ + } else { + PAT_DEL_ON(rn0); + di->stat = DL_PHASE1; + di->ld = *p0; + di->d = r; + // grn_log("pat_del d=%d ld=%d stat=%d", r, *p0, DL_PHASE1); + } + } + if (*p0 == otherside) { + /* The previous node (*p0) has a self-loop (rn0 == rno). */ + PAT_CHK_SET(rno, 0); + if (proot == p0) { + /* + * Update rno->lr because the first node, rno becomes the new first + * node, is not an output node even if its check is zero. + */ + const uint8_t *k = pat_node_get_key(ctx, pat, rno); + int direction = k ? (*k >> 7) : 1; + rno->lr[direction] = otherside; + rno->lr[!direction] = 0; + } + } else { + if (otherside) { + if (c0 < PAT_CHK(rno) && PAT_CHK(rno) <= c) { + /* To keep rno as an output node, its check is set to zero. */ + if (!delinfo_search(pat, otherside)) { + GRN_LOG(ctx, GRN_LOG_ERROR, "no delinfo found %d", otherside); + } + PAT_CHK_SET(rno, 0); + } + if (proot == p0 && !rno->check) { + /* + * Update rno->lr because the first node, rno becomes the new first + * node, is not an output node even if its check is zero. + */ + const uint8_t *k = pat_node_get_key(ctx, pat, rno); + int direction = k ? (*k >> 7) : 1; + rno->lr[direction] = otherside; + rno->lr[!direction] = 0; + } + } + *p0 = otherside; + } + } + pat->header->n_entries--; + pat->header->n_garbages++; + return GRN_SUCCESS; +} + +static grn_rc +_grn_pat_delete(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size, + grn_table_delete_optarg *optarg) +{ + if (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) { + grn_id id = grn_pat_get(ctx, pat, key, key_size, NULL); + if (id && grn_pat_delete_with_sis(ctx, pat, id, optarg)) { + return GRN_SUCCESS; + } + return GRN_INVALID_ARGUMENT; + } + return _grn_pat_del(ctx, pat, key, key_size, 0, optarg); +} + +grn_rc +grn_pat_delete(grn_ctx *ctx, grn_pat *pat, const void *key, uint32_t key_size, + grn_table_delete_optarg *optarg) +{ + grn_rc rc; + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + if (!pat || !key || !key_size) { return GRN_INVALID_ARGUMENT; } + rc = grn_pat_error_if_truncated(ctx, pat); + if (rc != GRN_SUCCESS) { + return rc; + } + KEY_ENCODE(pat, keybuf, key, key_size); + return _grn_pat_delete(ctx, pat, key, key_size, optarg); +} + +uint32_t +grn_pat_size(grn_ctx *ctx, grn_pat *pat) +{ + if (!pat) { return GRN_INVALID_ARGUMENT; } + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return 0; + } + return pat->header->n_entries; +} + +const char * +_grn_pat_key(grn_ctx *ctx, grn_pat *pat, grn_id id, uint32_t *key_size) +{ + pat_node *node; + uint8_t *key; + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + *key_size = 0; + return NULL; + } + PAT_AT(pat, id, node); + if (!node) { + *key_size = 0; + return NULL; + } + key = pat_node_get_key(ctx, pat, node); + if (key) { + *key_size = PAT_LEN(node); + } else { + *key_size = 0; + } + return (const char *)key; +} + +grn_rc +grn_pat_delete_by_id(grn_ctx *ctx, grn_pat *pat, grn_id id, + grn_table_delete_optarg *optarg) +{ + grn_rc rc; + if (!pat || !id) { return GRN_INVALID_ARGUMENT; } + rc = grn_pat_error_if_truncated(ctx, pat); + if (rc != GRN_SUCCESS) { + return rc; + } + { + uint32_t key_size; + const char *key = _grn_pat_key(ctx, pat, id, &key_size); + return _grn_pat_delete(ctx, pat, key, key_size, optarg); + } +} + +int +grn_pat_get_key(grn_ctx *ctx, grn_pat *pat, grn_id id, void *keybuf, int bufsize) +{ + int len; + uint8_t *key; + pat_node *node; + if (!pat) { return 0; } + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return 0; + } + if (!id) { return 0; } + PAT_AT(pat, id, node); + if (!node) { return 0; } + if (!(key = pat_node_get_key(ctx, pat, node))) { return 0; } + len = PAT_LEN(node); + if (keybuf && bufsize >= len) { + if (KEY_NEEDS_CONVERT(pat, len)) { + KEY_DEC(pat, keybuf, key, len); + } else { + grn_memcpy(keybuf, key, len); + } + } + return len; +} + +int +grn_pat_get_key2(grn_ctx *ctx, grn_pat *pat, grn_id id, grn_obj *bulk) +{ + uint32_t len; + uint8_t *key; + pat_node *node; + if (!pat) { return GRN_INVALID_ARGUMENT; } + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return 0; + } + if (!id) { return 0; } + PAT_AT(pat, id, node); + if (!node) { return 0; } + if (!(key = pat_node_get_key(ctx, pat, node))) { return 0; } + len = PAT_LEN(node); + if (KEY_NEEDS_CONVERT(pat, len)) { + if (bulk->header.impl_flags & GRN_OBJ_REFER) { + GRN_TEXT_INIT(bulk, 0); + } + if (!grn_bulk_reserve(ctx, bulk, len)) { + char *curr = GRN_BULK_CURR(bulk); + KEY_DEC(pat, curr, key, len); + grn_bulk_truncate(ctx, bulk, GRN_BULK_VSIZE(bulk) + len); + } + } else { + if (bulk->header.impl_flags & GRN_OBJ_REFER) { + bulk->u.b.head = (char *)key; + bulk->u.b.curr = (char *)key + len; + } else { + grn_bulk_write(ctx, bulk, (char *)key, len); + } + } + return len; +} + +int +grn_pat_get_value(grn_ctx *ctx, grn_pat *pat, grn_id id, void *valuebuf) +{ + int value_size; + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return 0; + } + value_size = (int)pat->value_size; + if (value_size) { + byte *v = (byte *)sis_at(ctx, pat, id); + if (v) { + if (valuebuf) { + if (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) { + grn_memcpy(valuebuf, v + sizeof(sis_node), value_size); + } else { + grn_memcpy(valuebuf, v, value_size); + } + } + return value_size; + } + } + return 0; +} + +const char * +grn_pat_get_value_(grn_ctx *ctx, grn_pat *pat, grn_id id, uint32_t *size) +{ + const char *value = NULL; + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return NULL; + } + if ((*size = pat->value_size)) { + if ((value = (const char *)sis_at(ctx, pat, id)) + && (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS)) { + value += sizeof(sis_node); + } + } + return value; +} + +grn_rc +grn_pat_set_value(grn_ctx *ctx, grn_pat *pat, grn_id id, + const void *value, int flags) +{ + grn_rc rc = grn_pat_error_if_truncated(ctx, pat); + if (rc != GRN_SUCCESS) { + return rc; + } + if (value) { + uint32_t value_size = pat->value_size; + if (value_size) { + byte *v = (byte *)sis_get(ctx, pat, id); + if (v) { + if (pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) { v += sizeof(sis_node); } + switch ((flags & GRN_OBJ_SET_MASK)) { + case GRN_OBJ_SET : + grn_memcpy(v, value, value_size); + return GRN_SUCCESS; + case GRN_OBJ_INCR : + switch (value_size) { + case sizeof(int32_t) : + *((int32_t *)v) += *((int32_t *)value); + return GRN_SUCCESS; + case sizeof(int64_t) : + *((int64_t *)v) += *((int64_t *)value); + return GRN_SUCCESS; + default : + return GRN_INVALID_ARGUMENT; + } + break; + case GRN_OBJ_DECR : + switch (value_size) { + case sizeof(int32_t) : + *((int32_t *)v) -= *((int32_t *)value); + return GRN_SUCCESS; + case sizeof(int64_t) : + *((int64_t *)v) -= *((int64_t *)value); + return GRN_SUCCESS; + default : + return GRN_INVALID_ARGUMENT; + } + break; + default : + // todo : support other types. + return GRN_INVALID_ARGUMENT; + } + } else { + return GRN_NO_MEMORY_AVAILABLE; + } + } + } + return GRN_INVALID_ARGUMENT; +} + +grn_rc +grn_pat_info(grn_ctx *ctx, grn_pat *pat, int *key_size, unsigned int *flags, + grn_encoding *encoding, unsigned int *n_entries, unsigned int *file_size) +{ + grn_rc rc; + ERRCLR(NULL); + if (!pat) { return GRN_INVALID_ARGUMENT; } + rc = grn_pat_error_if_truncated(ctx, pat); + if (rc != GRN_SUCCESS) { + return rc; + } + if (key_size) { *key_size = pat->key_size; } + if (flags) { *flags = pat->obj.header.flags; } + if (encoding) { *encoding = pat->encoding; } + if (n_entries) { *n_entries = pat->header->n_entries; } + if (file_size) { + uint64_t tmp = 0; + if ((rc = grn_io_size(ctx, pat->io, &tmp))) { + return rc; + } + *file_size = (unsigned int) tmp; /* FIXME: inappropriate cast */ + } + return GRN_SUCCESS; +} + +int +grn_pat_delete_with_sis(grn_ctx *ctx, grn_pat *pat, grn_id id, + grn_table_delete_optarg *optarg) +{ + int level = 0, shared; + const char *key = NULL, *_key; + sis_node *sp, *ss = NULL, *si; + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return 0; + } + si = sis_at(ctx, pat, id); + while (id) { + pat_node *rn; + uint32_t key_size; + if ((si && si->children && si->children != id) || + (optarg && optarg->func && + !optarg->func(ctx, (grn_obj *)pat, id, optarg->func_arg))) { + break; + } + PAT_AT(pat, id, rn); + if (!(_key = (char *)pat_node_get_key(ctx, pat, rn))) { return 0; } + if (_key == key) { + shared = 1; + } else { + key = _key; + shared = 0; + } + key_size = PAT_LEN(rn); + if (key && key_size) { _grn_pat_del(ctx, pat, key, key_size, shared, NULL); } + if (si) { + grn_id *p, sid; + uint32_t lkey = 0; + if ((*key & 0x80) && chop(ctx, pat, &key, key + key_size, &lkey)) { + if ((sid = grn_pat_get(ctx, pat, key, key_size - lkey, NULL)) && + (ss = sis_at(ctx, pat, sid))) { + for (p = &ss->children; *p && *p != sid; p = &sp->sibling) { + if (*p == id) { + *p = si->sibling; + break; + } + if (!(sp = sis_at(ctx, pat, *p))) { break; } + } + } + } else { + sid = GRN_ID_NIL; + } + si->sibling = 0; + si->children = 0; + id = sid; + si = ss; + } else { + id = GRN_ID_NIL; + } + level++; + } + if (level) { + uint32_t lkey = 0; + while (id && key) { + uint32_t key_size; + if (_grn_pat_key(ctx, pat, id, &key_size) != key) { break; } + { + pat_node *rn; + PAT_AT(pat, id, rn); + if (!rn) { break; } + if (lkey) { + rn->key = lkey; + } else { + pat_node_set_key(ctx, pat, rn, (uint8_t *)key, key_size); + lkey = rn->key; + } + } + { + const char *end = key + key_size; + if (!((*key & 0x80) && chop(ctx, pat, &key, end, &lkey))) { break; } + id = grn_pat_get(ctx, pat, key, end - key, NULL); + } + } + } + return level; +} + +grn_id +grn_pat_next(grn_ctx *ctx, grn_pat *pat, grn_id id) +{ + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + while (++id <= pat->header->curr_rec) { + uint32_t key_size; + const char *key = _grn_pat_key(ctx, pat, id, &key_size); + if (id == grn_pat_get(ctx, pat, key, key_size, NULL)) { + return id; + } + } + return GRN_ID_NIL; +} + +grn_id +grn_pat_at(grn_ctx *ctx, grn_pat *pat, grn_id id) +{ + uint32_t key_size; + const char *key = _grn_pat_key(ctx, pat, id, &key_size); + if (key && (id == _grn_pat_get(ctx, pat, key, key_size, NULL))) { return id; } + return GRN_ID_NIL; +} + +grn_id +grn_pat_curr_id(grn_ctx *ctx, grn_pat *pat) +{ + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return GRN_ID_NIL; + } + return pat->header->curr_rec; +} + +int +grn_pat_scan(grn_ctx *ctx, grn_pat *pat, const char *str, unsigned int str_len, + grn_pat_scan_hit *sh, unsigned int sh_size, const char **rest) +{ + int n = 0; + grn_id tid; + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return 0; + } + if (pat->normalizer) { + int flags = + GRN_STRING_REMOVE_BLANK | + GRN_STRING_WITH_TYPES | + GRN_STRING_WITH_CHECKS; + grn_obj *nstr = grn_string_open(ctx, str, str_len, + pat->normalizer, flags); + if (nstr) { + const short *cp = grn_string_get_checks(ctx, nstr); + const unsigned char *tp = grn_string_get_types(ctx, nstr); + unsigned int offset = 0, offset0 = 0; + unsigned int normalized_length_in_bytes; + const char *sp, *se; + grn_string_get_normalized(ctx, nstr, &sp, &normalized_length_in_bytes, + NULL); + se = sp + normalized_length_in_bytes; + while (n < sh_size) { + if ((tid = grn_pat_lcp_search(ctx, pat, sp, se - sp))) { + const char *key; + uint32_t len; + int first_key_char_len; + key = _grn_pat_key(ctx, pat, tid, &len); + sh[n].id = tid; + sh[n].offset = (*cp > 0) ? offset : offset0; + first_key_char_len = grn_charlen(ctx, key, key + len); + if (sh[n].offset > 0 && + GRN_CHAR_IS_BLANK(tp[-1]) && + ((first_key_char_len == 1 && key[0] != ' ') || + first_key_char_len > 1)){ + /* Remove leading spaces. */ + const char *original_str = str + sh[n].offset; + while (grn_charlen(ctx, original_str, str + str_len) == 1 && + original_str[0] == ' ') { + original_str++; + sh[n].offset++; + } + } + { + grn_bool blank_in_alnum = GRN_FALSE; + const unsigned char *start_tp = tp; + const unsigned char *blank_in_alnum_check_tp; + while (len--) { + if (*cp > 0) { offset0 = offset; offset += *cp; tp++; } + sp++; cp++; + } + sh[n].length = offset - sh[n].offset; + for (blank_in_alnum_check_tp = start_tp + 1; + blank_in_alnum_check_tp < tp; + blank_in_alnum_check_tp++) { +#define GRN_CHAR_IS_ALNUM(char_type) \ + (GRN_CHAR_TYPE(char_type) == GRN_CHAR_ALPHA || \ + GRN_CHAR_TYPE(char_type) == GRN_CHAR_DIGIT) + if (GRN_CHAR_IS_BLANK(blank_in_alnum_check_tp[0]) && + GRN_CHAR_IS_ALNUM(blank_in_alnum_check_tp[-1]) && + (blank_in_alnum_check_tp + 1) < tp && + GRN_CHAR_IS_ALNUM(blank_in_alnum_check_tp[1])) { + blank_in_alnum = GRN_TRUE; + } +#undef GRN_CHAR_IS_ALNUM + } + if (!blank_in_alnum) { + n++; + } + } + } else { + if (*cp > 0) { offset0 = offset; offset += *cp; tp++; } + do { + sp++; cp++; + } while (sp < se && !*cp); + } + if (se <= sp) { offset = str_len; break; } + } + if (rest) { + grn_string_get_original(ctx, nstr, rest, NULL); + *rest += offset; + } + grn_obj_close(ctx, nstr); + } else { + n = -1; + if (rest) { *rest = str; } + } + } else { + uint32_t len; + const char *sp, *se = str + str_len; + for (sp = str; sp < se && n < sh_size; sp += len) { + if ((tid = grn_pat_lcp_search(ctx, pat, sp, se - sp))) { + _grn_pat_key(ctx, pat, tid, &len); + sh[n].id = tid; + sh[n].offset = sp - str; + sh[n].length = len; + n++; + } else { + len = grn_charlen(ctx, sp, se); + } + if (!len) { break; } + } + if (rest) { *rest = sp; } + } + return n; +} + +#define INITIAL_SIZE 512 + +inline static void +push(grn_pat_cursor *c, grn_id id, uint16_t check) +{ + grn_ctx *ctx = c->ctx; + grn_pat_cursor_entry *se; + if (c->size <= c->sp) { + if (c->ss) { + uint32_t size = c->size * 4; + grn_pat_cursor_entry *ss = GRN_REALLOC(c->ss, size); + if (!ss) { return; /* give up */ } + c->ss = ss; + c->size = size; + } else { + if (!(c->ss = GRN_MALLOC(sizeof(grn_pat_cursor_entry) * INITIAL_SIZE))) { + return; /* give up */ + } + c->size = INITIAL_SIZE; + } + } + se = &c->ss[c->sp++]; + se->id = id; + se->check = check; +} + +inline static grn_pat_cursor_entry * +pop(grn_pat_cursor *c) +{ + return c->sp ? &c->ss[--c->sp] : NULL; +} + +static grn_id +grn_pat_cursor_next_by_id(grn_ctx *ctx, grn_pat_cursor *c) +{ + grn_pat *pat = c->pat; + int dir = (c->obj.header.flags & GRN_CURSOR_DESCENDING) ? -1 : 1; + while (c->curr_rec != c->tail) { + c->curr_rec += dir; + if (pat->header->n_garbages) { + uint32_t key_size; + const void *key = _grn_pat_key(ctx, pat, c->curr_rec, &key_size); + if (_grn_pat_get(ctx, pat, key, key_size, NULL) != c->curr_rec) { + continue; + } + } + c->rest--; + return c->curr_rec; + } + return GRN_ID_NIL; +} + +grn_id +grn_pat_cursor_next(grn_ctx *ctx, grn_pat_cursor *c) +{ + pat_node *node; + grn_pat_cursor_entry *se; + if (!c->rest) { return GRN_ID_NIL; } + if ((c->obj.header.flags & GRN_CURSOR_BY_ID)) { + return grn_pat_cursor_next_by_id(ctx, c); + } + while ((se = pop(c))) { + grn_id id = se->id; + int check = se->check, ch; + while (id) { + PAT_AT(c->pat, id, node); + if (!node) { + break; + } + ch = PAT_CHK(node); + if (ch > check) { + if (c->obj.header.flags & GRN_CURSOR_DESCENDING) { + push(c, node->lr[0], ch); + id = node->lr[1]; + } else { + push(c, node->lr[1], ch); + id = node->lr[0]; + } + check = ch; + continue; + } else { + if (id == c->tail) { + c->sp = 0; + } else { + if (!c->curr_rec && c->tail) { + uint32_t lmin, lmax; + pat_node *nmin, *nmax; + const uint8_t *kmin, *kmax; + if (c->obj.header.flags & GRN_CURSOR_DESCENDING) { + PAT_AT(c->pat, c->tail, nmin); + PAT_AT(c->pat, id, nmax); + } else { + PAT_AT(c->pat, id, nmin); + PAT_AT(c->pat, c->tail, nmax); + } + lmin = PAT_LEN(nmin); + lmax = PAT_LEN(nmax); + kmin = pat_node_get_key(ctx, c->pat, nmin); + kmax = pat_node_get_key(ctx, c->pat, nmax); + if ((lmin < lmax) ? + (memcmp(kmin, kmax, lmin) > 0) : + (memcmp(kmin, kmax, lmax) >= 0)) { + c->sp = 0; + break; + } + } + } + c->curr_rec = id; + c->rest--; + return id; + } + } + } + return GRN_ID_NIL; +} + +void +grn_pat_cursor_close(grn_ctx *ctx, grn_pat_cursor *c) +{ + GRN_ASSERT(c->ctx == ctx); + if (c->ss) { GRN_FREE(c->ss); } + GRN_FREE(c); +} + +inline static int +bitcmp(const void *s1, const void *s2, int offset, int length) +{ + int r, rest = length + (offset & 7) - 8, bl = offset >> 3, mask = 0xff >> (offset & 7); + unsigned char *a = (unsigned char *)s1 + bl, *b = (unsigned char *)s2 + bl; + if (rest <= 0) { + mask &= 0xff << -rest; + return (*a & mask) - (*b & mask); + } + if ((r = (*a & mask) - (*b & mask))) { return r; } + a++; b++; + if ((bl = rest >> 3)) { + if ((r = memcmp(a, b, bl))) { return r; } + a += bl; b += bl; + } + mask = 0xff << (8 - (rest & 7)); + return (*a & mask) - (*b & mask); +} + +inline static grn_rc +set_cursor_prefix(grn_ctx *ctx, grn_pat *pat, grn_pat_cursor *c, + const void *key, uint32_t key_size, int flags) +{ + int c0 = -1, ch; + const uint8_t *k; + uint32_t len, byte_len; + grn_id id; + pat_node *node; + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + if (flags & GRN_CURSOR_SIZE_BY_BIT) { + len = key_size * 2; + byte_len = key_size >> 3; + } else { + len = key_size * 16; + byte_len = key_size; + } + KEY_ENCODE(pat, keybuf, key, byte_len); + PAT_AT(pat, 0, node); + id = node->lr[1]; + while (id) { + PAT_AT(pat, id, node); + if (!node) { return GRN_FILE_CORRUPT; } + ch = PAT_CHK(node); + if (c0 < ch && ch < len - 1) { + if (ch & 1) { + id = (ch + 1 < len) ? node->lr[1] : node->lr[0]; + } else { + id = node->lr[nth_bit((uint8_t *)key, ch, len)]; + } + c0 = ch; + continue; + } + if (!(k = pat_node_get_key(ctx, pat, node))) { break; } + if (PAT_LEN(node) < byte_len) { break; } + if ((flags & GRN_CURSOR_SIZE_BY_BIT) + ? !bitcmp(k, key, 0, key_size) + : !memcmp(k, key, key_size)) { + if (c0 < ch) { + if (flags & GRN_CURSOR_DESCENDING) { + if ((ch > len - 1) || !(flags & GRN_CURSOR_GT)) { + push(c, node->lr[0], ch); + } + push(c, node->lr[1], ch); + } else { + push(c, node->lr[1], ch); + if ((ch > len - 1) || !(flags & GRN_CURSOR_GT)) { + push(c, node->lr[0], ch); + } + } + } else { + if (PAT_LEN(node) * 16 > len || !(flags & GRN_CURSOR_GT)) { + push(c, id, ch); + } + } + } + break; + } + return GRN_SUCCESS; +} + +inline static grn_rc +set_cursor_near(grn_ctx *ctx, grn_pat *pat, grn_pat_cursor *c, + uint32_t min_size, const void *key, int flags) +{ + grn_id id; + pat_node *node; + const uint8_t *k; + int r, check = -1, ch; + uint32_t min = min_size * 16; + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + KEY_ENCODE(pat, keybuf, key, pat->key_size); + PAT_AT(pat, 0, node); + for (id = node->lr[1]; id;) { + PAT_AT(pat, id, node); + if (!node) { return GRN_FILE_CORRUPT; } + ch = PAT_CHK(node); + if (ch <= check) { + if (check >= min) { push(c, id, check); } + break; + } + if ((check += 2) < ch) { + if (!(k = pat_node_get_key(ctx, pat, node))) { return GRN_FILE_CORRUPT; } + if ((r = bitcmp(key, k, check >> 1, (ch - check) >> 1))) { + if (ch >= min) { + push(c, node->lr[1], ch); + push(c, node->lr[0], ch); + } + break; + } + } + check = ch; + if (nth_bit((uint8_t *)key, check, pat->key_size)) { + if (check >= min) { push(c, node->lr[0], check); } + id = node->lr[1]; + } else { + if (check >= min) { push(c, node->lr[1], check); } + id = node->lr[0]; + } + } + return GRN_SUCCESS; +} + +inline static grn_rc +set_cursor_common_prefix(grn_ctx *ctx, grn_pat *pat, grn_pat_cursor *c, + uint32_t min_size, const void *key, uint32_t key_size, int flags) +{ + grn_id id; + pat_node *node; + const uint8_t *k; + int check = -1, ch; + uint32_t len = key_size * 16; + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + KEY_ENCODE(pat, keybuf, key, key_size); + PAT_AT(pat, 0, node); + for (id = node->lr[1]; id;) { + PAT_AT(pat, id, node); + if (!node) { return GRN_FILE_CORRUPT; } + ch = PAT_CHK(node); + if (ch <= check) { + if (!(k = pat_node_get_key(ctx, pat, node))) { return GRN_FILE_CORRUPT; } + { + uint32_t l = PAT_LEN(node); + if (min_size <= l && l <= key_size) { + if (!memcmp(key, k, l)) { push(c, id, check); } + } + } + break; + } + check = ch; + if (len <= check) { break; } + if (check & 1) { + grn_id id0 = node->lr[0]; + pat_node *node0; + PAT_AT(pat, id0, node0); + if (!node0) { return GRN_FILE_CORRUPT; } + if (!(k = pat_node_get_key(ctx, pat, node0))) { return GRN_FILE_CORRUPT; } + { + uint32_t l = PAT_LEN(node0); + if (memcmp(key, k, l)) { break; } + if (min_size <= l) { + push(c, id0, check); + } + } + id = node->lr[1]; + } else { + id = node->lr[nth_bit((uint8_t *)key, check, len)]; + } + } + return GRN_SUCCESS; +} + +inline static grn_rc +set_cursor_ascend(grn_ctx *ctx, grn_pat *pat, grn_pat_cursor *c, + const void *key, uint32_t key_size, int flags) +{ + grn_id id; + pat_node *node; + const uint8_t *k; + int r, check = -1, ch, c2; + uint32_t len = key_size * 16; + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + KEY_ENCODE(pat, keybuf, key, key_size); + PAT_AT(pat, 0, node); + for (id = node->lr[1]; id;) { + PAT_AT(pat, id, node); + if (!node) { return GRN_FILE_CORRUPT; } + ch = PAT_CHK(node); + if (ch <= check) { + if (!(k = pat_node_get_key(ctx, pat, node))) { return GRN_FILE_CORRUPT; } + { + uint32_t l = PAT_LEN(node); + if (l == key_size) { + if (flags & GRN_CURSOR_GT) { + if (memcmp(key, k, l) < 0) { push(c, id, check); } + } else { + if (memcmp(key, k, l) <= 0) { push(c, id, check); } + } + } else if (l < key_size) { + if (memcmp(key, k, l) < 0) { push(c, id, check); } + } else { + if (memcmp(key, k, key_size) <= 0) { push(c, id, check); } + } + } + break; + } + c2 = len < ch ? len : ch; + if ((check += 2) < c2) { + if (!(k = pat_node_get_key(ctx, pat, node))) { return GRN_FILE_CORRUPT; } + if ((r = bitcmp(key, k, check >> 1, ((c2 + 1) >> 1) - (check >> 1)))) { + if (r < 0) { + push(c, node->lr[1], ch); + push(c, node->lr[0], ch); + } + break; + } + } + check = ch; + if (len <= check) { + push(c, node->lr[1], ch); + push(c, node->lr[0], ch); + break; + } + if (check & 1) { + if (check + 1 < len) { + id = node->lr[1]; + } else { + push(c, node->lr[1], check); + id = node->lr[0]; + } + } else { + if (nth_bit((uint8_t *)key, check, len)) { + id = node->lr[1]; + } else { + push(c, node->lr[1], check); + id = node->lr[0]; + } + } + } + return GRN_SUCCESS; +} + +inline static grn_rc +set_cursor_descend(grn_ctx *ctx, grn_pat *pat, grn_pat_cursor *c, + const void *key, uint32_t key_size, int flags) +{ + grn_id id; + pat_node *node; + const uint8_t *k; + int r, check = -1, ch, c2; + uint32_t len = key_size * 16; + uint8_t keybuf[MAX_FIXED_KEY_SIZE]; + KEY_ENCODE(pat, keybuf, key, key_size); + PAT_AT(pat, 0, node); + for (id = node->lr[1]; id;) { + PAT_AT(pat, id, node); + if (!node) { return GRN_FILE_CORRUPT; } + ch = PAT_CHK(node); + if (ch <= check) { + if (!(k = pat_node_get_key(ctx, pat, node))) { return GRN_FILE_CORRUPT; } + { + uint32_t l = PAT_LEN(node); + if (l <= key_size) { + if ((flags & GRN_CURSOR_LT) && l == key_size) { + if (memcmp(key, k, l) > 0) { push(c, id, check); } + } else { + if (memcmp(key, k, l) >= 0) { push(c, id, check); } + } + } else { + if (memcmp(key, k, key_size) > 0) { push(c, id, check); } + } + } + break; + } + c2 = len < ch ? len : ch; + if ((check += 2) < c2) { + if (!(k = pat_node_get_key(ctx, pat, node))) { return GRN_FILE_CORRUPT; } + if ((r = bitcmp(key, k, check >> 1, ((c2 + 1) >> 1) - (check >> 1)))) { + if (r >= 0) { + push(c, node->lr[0], ch); + push(c, node->lr[1], ch); + } + break; + } + } + check = ch; + if (len <= check) { break; } + if (check & 1) { + if (check + 1 < len) { + push(c, node->lr[0], check); + id = node->lr[1]; + } else { + id = node->lr[0]; + } + } else { + if (nth_bit((uint8_t *)key, check, len)) { + push(c, node->lr[0], check); + id = node->lr[1]; + } else { + id = node->lr[0]; + } + } + } + return GRN_SUCCESS; +} + +static grn_pat_cursor * +grn_pat_cursor_open_by_id(grn_ctx *ctx, grn_pat *pat, + const void *min, uint32_t min_size, + const void *max, uint32_t max_size, + int offset, int limit, int flags) +{ + int dir; + grn_pat_cursor *c; + if (!pat || !ctx) { return NULL; } + if (!(c = GRN_MALLOCN(grn_pat_cursor, 1))) { return NULL; } + GRN_DB_OBJ_SET_TYPE(c, GRN_CURSOR_TABLE_PAT_KEY); + c->pat = pat; + c->ctx = ctx; + c->obj.header.flags = flags; + c->obj.header.domain = GRN_ID_NIL; + c->size = 0; + c->sp = 0; + c->ss = NULL; + c->tail = 0; + if (flags & GRN_CURSOR_DESCENDING) { + dir = -1; + if (max) { + if (!(c->curr_rec = grn_pat_get(ctx, pat, max, max_size, NULL))) { + c->tail = GRN_ID_NIL; + goto exit; + } + if (!(flags & GRN_CURSOR_LT)) { c->curr_rec++; } + } else { + c->curr_rec = pat->header->curr_rec + 1; + } + if (min) { + if (!(c->tail = grn_pat_get(ctx, pat, min, min_size, NULL))) { + c->curr_rec = GRN_ID_NIL; + goto exit; + } + if ((flags & GRN_CURSOR_GT)) { c->tail++; } + } else { + c->tail = GRN_ID_NIL + 1; + } + if (c->curr_rec < c->tail) { c->tail = c->curr_rec; } + } else { + dir = 1; + if (min) { + if (!(c->curr_rec = grn_pat_get(ctx, pat, min, min_size, NULL))) { + c->tail = GRN_ID_NIL; + goto exit; + } + if (!(flags & GRN_CURSOR_GT)) { c->curr_rec--; } + } else { + c->curr_rec = GRN_ID_NIL; + } + if (max) { + if (!(c->tail = grn_pat_get(ctx, pat, max, max_size, NULL))) { + c->curr_rec = GRN_ID_NIL; + goto exit; + } + if ((flags & GRN_CURSOR_LT)) { c->tail--; } + } else { + c->tail = pat->header->curr_rec; + } + if (c->tail < c->curr_rec) { c->tail = c->curr_rec; } + } + if (pat->header->n_garbages) { + while (offset && c->curr_rec != c->tail) { + uint32_t key_size; + const void *key; + c->curr_rec += dir; + key = _grn_pat_key(ctx, pat, c->curr_rec, &key_size); + if (_grn_pat_get(ctx, pat, key, key_size, NULL) == c->curr_rec) { + offset--; + } + } + } else { + if ((dir * (c->tail - c->curr_rec)) < offset) { + c->curr_rec = c->tail; + } else { + c->curr_rec += dir * offset; + } + } + c->rest = (limit < 0) ? GRN_ID_MAX : limit; +exit : + return c; +} + +static grn_rc set_cursor_rk(grn_ctx *ctx, grn_pat *pat, grn_pat_cursor *c, + const void *key, uint32_t key_size, int flags); + +grn_pat_cursor * +grn_pat_cursor_open(grn_ctx *ctx, grn_pat *pat, + const void *min, uint32_t min_size, + const void *max, uint32_t max_size, + int offset, int limit, int flags) +{ + grn_id id; + pat_node *node; + grn_pat_cursor *c; + if (!pat || !ctx) { return NULL; } + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return NULL; + } + if ((flags & GRN_CURSOR_BY_ID)) { + return grn_pat_cursor_open_by_id(ctx, pat, min, min_size, max, max_size, + offset, limit, flags); + } + if (!(c = GRN_MALLOCN(grn_pat_cursor, 1))) { return NULL; } + GRN_DB_OBJ_SET_TYPE(c, GRN_CURSOR_TABLE_PAT_KEY); + c->pat = pat; + c->ctx = ctx; + c->size = 0; + c->sp = 0; + c->ss = NULL; + c->tail = 0; + c->rest = GRN_ID_MAX; + c->curr_rec = GRN_ID_NIL; + c->obj.header.domain = GRN_ID_NIL; + if (flags & GRN_CURSOR_PREFIX) { + if (max && max_size) { + if ((pat->obj.header.flags & GRN_OBJ_KEY_VAR_SIZE)) { + set_cursor_common_prefix(ctx, pat, c, min_size, max, max_size, flags); + } else { + set_cursor_near(ctx, pat, c, min_size, max, flags); + } + goto exit; + } else { + if (min && min_size) { + if (flags & GRN_CURSOR_RK) { + set_cursor_rk(ctx, pat, c, min, min_size, flags); + } else { + set_cursor_prefix(ctx, pat, c, min, min_size, flags); + } + goto exit; + } + } + } + if (flags & GRN_CURSOR_DESCENDING) { + if (min && min_size) { + set_cursor_ascend(ctx, pat, c, min, min_size, flags); + c->obj.header.flags = GRN_CURSOR_ASCENDING; + c->tail = grn_pat_cursor_next(ctx, c); + c->sp = 0; + if (!c->tail) { goto exit; } + } + if (max && max_size) { + set_cursor_descend(ctx, pat, c, max, max_size, flags); + } else { + PAT_AT(pat, 0, node); + if (!node) { + grn_pat_cursor_close(ctx, c); + return NULL; + } + if ((id = node->lr[1])) { + PAT_AT(pat, id, node); + if (node) { + int ch = PAT_CHK(node); + push(c, node->lr[0], ch); + push(c, node->lr[1], ch); + } + } + } + } else { + if (max && max_size) { + set_cursor_descend(ctx, pat, c, max, max_size, flags); + c->obj.header.flags = GRN_CURSOR_DESCENDING; + c->tail = grn_pat_cursor_next(ctx, c); + c->sp = 0; + if (!c->tail) { goto exit; } + } + if (min && min_size) { + set_cursor_ascend(ctx, pat, c, min, min_size, flags); + } else { + PAT_AT(pat, 0, node); + if (!node) { + grn_pat_cursor_close(ctx, c); + return NULL; + } + if ((id = node->lr[1])) { + PAT_AT(pat, id, node); + if (node) { + int ch = PAT_CHK(node); + push(c, node->lr[1], ch); + push(c, node->lr[0], ch); + } + } + } + } +exit : + c->obj.header.flags = flags; + c->curr_rec = GRN_ID_NIL; + while (offset--) { grn_pat_cursor_next(ctx, c); } + c->rest = (limit < 0) ? GRN_ID_MAX : limit; + return c; +} + +int +grn_pat_cursor_get_key(grn_ctx *ctx, grn_pat_cursor *c, void **key) +{ + *key = c->curr_key; + return grn_pat_get_key(ctx, c->pat, c->curr_rec, *key, GRN_TABLE_MAX_KEY_SIZE); +} + +int +grn_pat_cursor_get_value(grn_ctx *ctx, grn_pat_cursor *c, void **value) +{ + int value_size = (int)c->pat->value_size; + if (value_size) { + byte *v = (byte *)sis_at(ctx, c->pat, c->curr_rec); + if (v) { + if (c->pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) { + *value = v + sizeof(sis_node); + } else { + *value = v; + } + } else { + *value = NULL; + } + } + return value_size; +} + +int +grn_pat_cursor_get_key_value(grn_ctx *ctx, grn_pat_cursor *c, + void **key, uint32_t *key_size, void **value) +{ + int value_size = (int)c->pat->value_size; + if (key_size) { + *key_size = (uint32_t) grn_pat_get_key(ctx, c->pat, c->curr_rec, c->curr_key, + GRN_TABLE_MAX_KEY_SIZE); + if (key) { *key = c->curr_key; } + } + if (value && value_size) { + byte *v = (byte *)sis_at(ctx, c->pat, c->curr_rec); + if (v) { + if (c->pat->obj.header.flags & GRN_OBJ_KEY_WITH_SIS) { + *value = v + sizeof(sis_node); + } else { + *value = v; + } + } else { + *value = NULL; + } + } + return value_size; +} + +grn_rc +grn_pat_cursor_set_value(grn_ctx *ctx, grn_pat_cursor *c, + const void *value, int flags) +{ + return grn_pat_set_value(ctx, c->pat, c->curr_rec, value, flags); +} + +grn_rc +grn_pat_cursor_delete(grn_ctx *ctx, grn_pat_cursor *c, + grn_table_delete_optarg *optarg) +{ + return grn_pat_delete_by_id(ctx, c->pat, c->curr_rec, optarg); +} + +void +grn_pat_check(grn_ctx *ctx, grn_pat *pat) +{ + char buf[8]; + struct grn_pat_header *h = pat->header; + if (grn_pat_error_if_truncated(ctx, pat) != GRN_SUCCESS) { + return; + } + GRN_OUTPUT_ARRAY_OPEN("RESULT", 1); + GRN_OUTPUT_MAP_OPEN("SUMMARY", 23); + GRN_OUTPUT_CSTR("flags"); + grn_itoh(h->flags, buf, 8); + GRN_OUTPUT_STR(buf, 8); + GRN_OUTPUT_CSTR("key size"); + GRN_OUTPUT_INT64(h->key_size); + GRN_OUTPUT_CSTR("value_size"); + GRN_OUTPUT_INT64(h->value_size); + GRN_OUTPUT_CSTR("tokenizer"); + GRN_OUTPUT_INT64(h->tokenizer); + GRN_OUTPUT_CSTR("normalizer"); + GRN_OUTPUT_INT64(h->normalizer); + GRN_OUTPUT_CSTR("n_entries"); + GRN_OUTPUT_INT64(h->n_entries); + GRN_OUTPUT_CSTR("curr_rec"); + GRN_OUTPUT_INT64(h->curr_rec); + GRN_OUTPUT_CSTR("curr_key"); + GRN_OUTPUT_INT64(h->curr_key); + GRN_OUTPUT_CSTR("curr_del"); + GRN_OUTPUT_INT64(h->curr_del); + GRN_OUTPUT_CSTR("curr_del2"); + GRN_OUTPUT_INT64(h->curr_del2); + GRN_OUTPUT_CSTR("curr_del3"); + GRN_OUTPUT_INT64(h->curr_del3); + GRN_OUTPUT_CSTR("n_garbages"); + GRN_OUTPUT_INT64(h->n_garbages); + GRN_OUTPUT_MAP_CLOSE(); + GRN_OUTPUT_ARRAY_CLOSE(); +} + +/* utilities */ +void +grn_p_pat_node(grn_ctx *ctx, grn_pat *pat, pat_node *node) +{ + uint8_t *key = NULL; + + if (!node) { + printf("#\n"); + return; + } + + if (PAT_IMD(node)) { + key = (uint8_t *)&(node->key); + } else { + KEY_AT(pat, node->key, key, 0); + } + + printf("#" + ">\n", + node, + node->lr[0], + node->lr[1], + PAT_DEL(node) ? "true" : "false", + PAT_IMD(node) ? "true" : "false", + PAT_LEN(node), + PAT_CHK(node) >> 4, + (PAT_CHK(node) >> 1) & 0x7, + (PAT_CHK(node) & 0x1) ? "true" : "false", + PAT_LEN(node), + (char *)key); +} + +static void +grn_pat_inspect_check(grn_ctx *ctx, grn_obj *buf, int check) +{ + GRN_TEXT_PUTS(ctx, buf, "{"); + grn_text_lltoa(ctx, buf, check >> 4); + GRN_TEXT_PUTS(ctx, buf, ","); + grn_text_lltoa(ctx, buf, (check >> 1) & 7); + GRN_TEXT_PUTS(ctx, buf, ","); + grn_text_lltoa(ctx, buf, check & 1); + GRN_TEXT_PUTS(ctx, buf, "}"); +} + +static void +grn_pat_inspect_node(grn_ctx *ctx, grn_pat *pat, grn_id id, int check, + grn_obj *key_buf, int indent, const char *prefix, + grn_obj *buf) +{ + pat_node *node = NULL; + int i, c; + + PAT_AT(pat, id, node); + c = PAT_CHK(node); + + for (i = 0; i < indent; i++) { + GRN_TEXT_PUTC(ctx, buf, ' '); + } + GRN_TEXT_PUTS(ctx, buf, prefix); + grn_text_lltoa(ctx, buf, id); + grn_pat_inspect_check(ctx, buf, c); + + if (c > check) { + GRN_TEXT_PUTS(ctx, buf, "\n"); + grn_pat_inspect_node(ctx, pat, node->lr[0], c, key_buf, + indent + 2, "L:", buf); + GRN_TEXT_PUTS(ctx, buf, "\n"); + grn_pat_inspect_node(ctx, pat, node->lr[1], c, key_buf, + indent + 2, "R:", buf); + } else if (id) { + int key_size; + uint8_t *key; + + key_size = PAT_LEN(node); + GRN_BULK_REWIND(key_buf); + grn_bulk_space(ctx, key_buf, key_size); + grn_pat_get_key(ctx, pat, id, GRN_BULK_HEAD(key_buf), key_size); + GRN_TEXT_PUTS(ctx, buf, "("); + grn_inspect(ctx, buf, key_buf); + GRN_TEXT_PUTS(ctx, buf, ")"); + + GRN_TEXT_PUTS(ctx, buf, "["); + key = pat_node_get_key(ctx, pat, node); + for (i = 0; i < key_size; i++) { + int j; + uint8_t byte = key[i]; + if (i != 0) { + GRN_TEXT_PUTS(ctx, buf, " "); + } + for (j = 0; j < 8; j++) { + grn_text_lltoa(ctx, buf, (byte >> (7 - j)) & 1); + } + } + GRN_TEXT_PUTS(ctx, buf, "]"); + } +} + +void +grn_pat_inspect_nodes(grn_ctx *ctx, grn_pat *pat, grn_obj *buf) +{ + pat_node *node; + grn_obj key_buf; + + GRN_TEXT_PUTS(ctx, buf, "{"); + PAT_AT(pat, GRN_ID_NIL, node); + if (node->lr[1]) { + GRN_TEXT_PUTS(ctx, buf, "\n"); + GRN_OBJ_INIT(&key_buf, GRN_BULK, 0, pat->obj.header.domain); + grn_pat_inspect_node(ctx, pat, node->lr[1], -1, &key_buf, 0, "", buf); + GRN_OBJ_FIN(ctx, &key_buf); + GRN_TEXT_PUTS(ctx, buf, "\n"); + } + GRN_TEXT_PUTS(ctx, buf, "}"); +} + +static void +grn_pat_cursor_inspect_entries(grn_ctx *ctx, grn_pat_cursor *c, grn_obj *buf) +{ + int i; + GRN_TEXT_PUTS(ctx, buf, "["); + for (i = 0; i < c->sp; i++) { + grn_pat_cursor_entry *e = c->ss + i; + if (i != 0) { + GRN_TEXT_PUTS(ctx, buf, ", "); + } + GRN_TEXT_PUTS(ctx, buf, "["); + grn_text_lltoa(ctx, buf, e->id); + GRN_TEXT_PUTS(ctx, buf, ","); + grn_pat_inspect_check(ctx, buf, e->check); + GRN_TEXT_PUTS(ctx, buf, "]"); + } + GRN_TEXT_PUTS(ctx, buf, "]"); +} + +void +grn_pat_cursor_inspect(grn_ctx *ctx, grn_pat_cursor *c, grn_obj *buf) +{ + GRN_TEXT_PUTS(ctx, buf, "#pat)); + + GRN_TEXT_PUTS(ctx, buf, " "); + GRN_TEXT_PUTS(ctx, buf, "current:"); + grn_text_lltoa(ctx, buf, c->curr_rec); + + GRN_TEXT_PUTS(ctx, buf, " "); + GRN_TEXT_PUTS(ctx, buf, "tail:"); + grn_text_lltoa(ctx, buf, c->tail); + + GRN_TEXT_PUTS(ctx, buf, " "); + GRN_TEXT_PUTS(ctx, buf, "flags:"); + if (c->obj.header.flags & GRN_CURSOR_PREFIX) { + GRN_TEXT_PUTS(ctx, buf, "prefix"); + } else { + if (c->obj.header.flags & GRN_CURSOR_DESCENDING) { + GRN_TEXT_PUTS(ctx, buf, "descending"); + } else { + GRN_TEXT_PUTS(ctx, buf, "ascending"); + } + GRN_TEXT_PUTS(ctx, buf, "|"); + if (c->obj.header.flags & GRN_CURSOR_GT) { + GRN_TEXT_PUTS(ctx, buf, "greater-than"); + } else { + GRN_TEXT_PUTS(ctx, buf, "greater"); + } + GRN_TEXT_PUTS(ctx, buf, "|"); + if (c->obj.header.flags & GRN_CURSOR_LT) { + GRN_TEXT_PUTS(ctx, buf, "less-than"); + } else { + GRN_TEXT_PUTS(ctx, buf, "less"); + } + if (c->obj.header.flags & GRN_CURSOR_BY_ID) { + GRN_TEXT_PUTS(ctx, buf, "|by-id"); + } + if (c->obj.header.flags & GRN_CURSOR_BY_KEY) { + GRN_TEXT_PUTS(ctx, buf, "|by-key"); + } + } + + GRN_TEXT_PUTS(ctx, buf, " "); + GRN_TEXT_PUTS(ctx, buf, "rest:"); + grn_text_lltoa(ctx, buf, c->rest); + + GRN_TEXT_PUTS(ctx, buf, " "); + GRN_TEXT_PUTS(ctx, buf, "entries:"); + grn_pat_cursor_inspect_entries(ctx, c, buf); + + GRN_TEXT_PUTS(ctx, buf, ">"); +} + +typedef struct { + uint8_t code; + uint8_t next; + uint8_t emit; + uint8_t attr; +} rk_tree_node; + +static uint16_t rk_str_idx[] = { + 0x0003, 0x0006, 0x0009, 0x000c, 0x0012, 0x0015, 0x0018, 0x001e, 0x0024, 0x002a, + 0x0030, 0x0036, 0x003c, 0x0042, 0x0048, 0x004e, 0x0054, 0x005a, 0x0060, 0x0066, + 0x006c, 0x0072, 0x0078, 0x007e, 0x0084, 0x008a, 0x0090, 0x0096, 0x009c, 0x00a2, + 0x00a8, 0x00ae, 0x00b4, 0x00ba, 0x00c0, 0x00c3, 0x00c6, 0x00c9, 0x00cc, 0x00cf, + 0x00d2, 0x00d5, 0x00db, 0x00e1, 0x00e7, 0x00ea, 0x00f0, 0x00f6, 0x00fc, 0x00ff, + 0x0105, 0x0108, 0x010e, 0x0111, 0x0114, 0x0117, 0x011a, 0x011d, 0x0120, 0x0123, + 0x0129, 0x012f, 0x0135, 0x013b, 0x013e, 0x0144, 0x014a, 0x0150, 0x0156, 0x0159, + 0x015c, 0x015f, 0x0162, 0x0165, 0x0168, 0x016b, 0x016e, 0x0171, 0x0177, 0x017d, + 0x0183, 0x0189, 0x018c, 0x0192, 0x0198, 0x019e, 0x01a1, 0x01a4, 0x01aa, 0x01b0, + 0x01b6, 0x01bc, 0x01bf, 0x01c2, 0x01c8, 0x01ce, 0x01d1, 0x01d7, 0x01dd, 0x01e0, + 0x01e6, 0x01e9, 0x01ef, 0x01f2, 0x01f5, 0x01fb, 0x0201, 0x0207, 0x020d, 0x0213, + 0x0216, 0x0219, 0x021c, 0x021f, 0x0222, 0x0225, 0x0228, 0x022e, 0x0234, 0x023a, + 0x023d, 0x0243, 0x0249, 0x024f, 0x0252, 0x0258, 0x025e, 0x0264, 0x0267, 0x026d, + 0x0273, 0x0279, 0x027f, 0x0285, 0x0288, 0x028b, 0x028e, 0x0291, 0x0294, 0x0297, + 0x029a, 0x029d, 0x02a0, 0x02a3, 0x02a9, 0x02af, 0x02b5, 0x02b8, 0x02bb, 0x02be, + 0x02c1, 0x02c4, 0x02c7, 0x02ca, 0x02cd, 0x02d0, 0x02d3, 0x02d6, 0x02dc, 0x02e2, + 0x02e8, 0x02eb, 0x02ee, 0x02f1, 0x02f4, 0x02f7, 0x02fa, 0x02fd, 0x0300, 0x0303, + 0x0309, 0x030c, 0x0312, 0x0318, 0x031e, 0x0324, 0x0327, 0x032a, 0x032d +}; +static char rk_str[] = { + 0xe3, 0x82, 0xa1, 0xe3, 0x82, 0xa2, 0xe3, 0x82, 0xa3, 0xe3, 0x82, 0xa4, 0xe3, + 0x82, 0xa4, 0xe3, 0x82, 0xa7, 0xe3, 0x82, 0xa5, 0xe3, 0x82, 0xa6, 0xe3, 0x82, + 0xa6, 0xe3, 0x82, 0xa2, 0xe3, 0x82, 0xa6, 0xe3, 0x82, 0xa3, 0xe3, 0x82, 0xa6, + 0xe3, 0x82, 0xa4, 0xe3, 0x82, 0xa6, 0xe3, 0x82, 0xa6, 0xe3, 0x82, 0xa6, 0xe3, + 0x82, 0xa7, 0xe3, 0x82, 0xa6, 0xe3, 0x82, 0xa8, 0xe3, 0x82, 0xa6, 0xe3, 0x82, + 0xaa, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xa0, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xa1, + 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xa2, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xa3, 0xe3, + 0x82, 0xa6, 0xe3, 0x83, 0xa4, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xa5, 0xe3, 0x82, + 0xa6, 0xe3, 0x83, 0xa6, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xa7, 0xe3, 0x82, 0xa6, + 0xe3, 0x83, 0xa8, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xa9, 0xe3, 0x82, 0xa6, 0xe3, + 0x83, 0xaa, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xab, 0xe3, 0x82, 0xa6, 0xe3, 0x83, + 0xac, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xad, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xae, + 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xaf, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xb0, 0xe3, + 0x82, 0xa6, 0xe3, 0x83, 0xb1, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xb2, 0xe3, 0x82, + 0xa6, 0xe3, 0x83, 0xb3, 0xe3, 0x82, 0xa6, 0xe3, 0x83, 0xbc, 0xe3, 0x82, 0xa7, + 0xe3, 0x82, 0xa8, 0xe3, 0x82, 0xa9, 0xe3, 0x82, 0xaa, 0xe3, 0x82, 0xab, 0xe3, + 0x82, 0xac, 0xe3, 0x82, 0xad, 0xe3, 0x82, 0xad, 0xe3, 0x83, 0xa3, 0xe3, 0x82, + 0xad, 0xe3, 0x83, 0xa5, 0xe3, 0x82, 0xad, 0xe3, 0x83, 0xa7, 0xe3, 0x82, 0xae, + 0xe3, 0x82, 0xae, 0xe3, 0x83, 0xa3, 0xe3, 0x82, 0xae, 0xe3, 0x83, 0xa5, 0xe3, + 0x82, 0xae, 0xe3, 0x83, 0xa7, 0xe3, 0x82, 0xaf, 0xe3, 0x82, 0xaf, 0xe3, 0x82, + 0xa1, 0xe3, 0x82, 0xb0, 0xe3, 0x82, 0xb0, 0xe3, 0x82, 0xa1, 0xe3, 0x82, 0xb1, + 0xe3, 0x82, 0xb2, 0xe3, 0x82, 0xb3, 0xe3, 0x82, 0xb4, 0xe3, 0x82, 0xb5, 0xe3, + 0x82, 0xb6, 0xe3, 0x82, 0xb7, 0xe3, 0x82, 0xb7, 0xe3, 0x82, 0xa7, 0xe3, 0x82, + 0xb7, 0xe3, 0x83, 0xa3, 0xe3, 0x82, 0xb7, 0xe3, 0x83, 0xa5, 0xe3, 0x82, 0xb7, + 0xe3, 0x83, 0xa7, 0xe3, 0x82, 0xb8, 0xe3, 0x82, 0xb8, 0xe3, 0x82, 0xa7, 0xe3, + 0x82, 0xb8, 0xe3, 0x83, 0xa3, 0xe3, 0x82, 0xb8, 0xe3, 0x83, 0xa5, 0xe3, 0x82, + 0xb8, 0xe3, 0x83, 0xa7, 0xe3, 0x82, 0xb9, 0xe3, 0x82, 0xba, 0xe3, 0x82, 0xbb, + 0xe3, 0x82, 0xbc, 0xe3, 0x82, 0xbd, 0xe3, 0x82, 0xbe, 0xe3, 0x82, 0xbf, 0xe3, + 0x83, 0x80, 0xe3, 0x83, 0x81, 0xe3, 0x83, 0x81, 0xe3, 0x82, 0xa7, 0xe3, 0x83, + 0x81, 0xe3, 0x83, 0xa3, 0xe3, 0x83, 0x81, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0x81, + 0xe3, 0x83, 0xa7, 0xe3, 0x83, 0x82, 0xe3, 0x83, 0x82, 0xe3, 0x83, 0xa3, 0xe3, + 0x83, 0x82, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0x82, 0xe3, 0x83, 0xa7, 0xe3, 0x83, + 0x83, 0xe3, 0x83, 0x84, 0xe3, 0x83, 0x84, 0xe3, 0x82, 0xa1, 0xe3, 0x83, 0x84, + 0xe3, 0x82, 0xa3, 0xe3, 0x83, 0x84, 0xe3, 0x82, 0xa7, 0xe3, 0x83, 0x84, 0xe3, + 0x82, 0xa9, 0xe3, 0x83, 0x85, 0xe3, 0x83, 0x86, 0xe3, 0x83, 0x86, 0xe3, 0x82, + 0xa3, 0xe3, 0x83, 0x86, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0x87, 0xe3, 0x83, 0x87, + 0xe3, 0x82, 0xa3, 0xe3, 0x83, 0x87, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0x88, 0xe3, + 0x83, 0x88, 0xe3, 0x82, 0xa5, 0xe3, 0x83, 0x89, 0xe3, 0x83, 0x89, 0xe3, 0x82, + 0xa5, 0xe3, 0x83, 0x8a, 0xe3, 0x83, 0x8b, 0xe3, 0x83, 0x8b, 0xe3, 0x82, 0xa3, + 0xe3, 0x83, 0x8b, 0xe3, 0x82, 0xa7, 0xe3, 0x83, 0x8b, 0xe3, 0x83, 0xa3, 0xe3, + 0x83, 0x8b, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0x8b, 0xe3, 0x83, 0xa7, 0xe3, 0x83, + 0x8c, 0xe3, 0x83, 0x8d, 0xe3, 0x83, 0x8e, 0xe3, 0x83, 0x8f, 0xe3, 0x83, 0x90, + 0xe3, 0x83, 0x91, 0xe3, 0x83, 0x92, 0xe3, 0x83, 0x92, 0xe3, 0x83, 0xa3, 0xe3, + 0x83, 0x92, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0x92, 0xe3, 0x83, 0xa7, 0xe3, 0x83, + 0x93, 0xe3, 0x83, 0x93, 0xe3, 0x83, 0xa3, 0xe3, 0x83, 0x93, 0xe3, 0x83, 0xa5, + 0xe3, 0x83, 0x93, 0xe3, 0x83, 0xa7, 0xe3, 0x83, 0x94, 0xe3, 0x83, 0x94, 0xe3, + 0x83, 0xa3, 0xe3, 0x83, 0x94, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0x94, 0xe3, 0x83, + 0xa7, 0xe3, 0x83, 0x95, 0xe3, 0x83, 0x95, 0xe3, 0x82, 0xa1, 0xe3, 0x83, 0x95, + 0xe3, 0x82, 0xa3, 0xe3, 0x83, 0x95, 0xe3, 0x82, 0xa7, 0xe3, 0x83, 0x95, 0xe3, + 0x82, 0xa9, 0xe3, 0x83, 0x95, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0x96, 0xe3, 0x83, + 0x97, 0xe3, 0x83, 0x98, 0xe3, 0x83, 0x99, 0xe3, 0x83, 0x9a, 0xe3, 0x83, 0x9b, + 0xe3, 0x83, 0x9c, 0xe3, 0x83, 0x9d, 0xe3, 0x83, 0x9e, 0xe3, 0x83, 0x9f, 0xe3, + 0x83, 0x9f, 0xe3, 0x83, 0xa3, 0xe3, 0x83, 0x9f, 0xe3, 0x83, 0xa5, 0xe3, 0x83, + 0x9f, 0xe3, 0x83, 0xa7, 0xe3, 0x83, 0xa0, 0xe3, 0x83, 0xa1, 0xe3, 0x83, 0xa2, + 0xe3, 0x83, 0xa3, 0xe3, 0x83, 0xa4, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0xa6, 0xe3, + 0x83, 0xa7, 0xe3, 0x83, 0xa8, 0xe3, 0x83, 0xa9, 0xe3, 0x83, 0xaa, 0xe3, 0x83, + 0xaa, 0xe3, 0x83, 0xa3, 0xe3, 0x83, 0xaa, 0xe3, 0x83, 0xa5, 0xe3, 0x83, 0xaa, + 0xe3, 0x83, 0xa7, 0xe3, 0x83, 0xab, 0xe3, 0x83, 0xac, 0xe3, 0x83, 0xad, 0xe3, + 0x83, 0xae, 0xe3, 0x83, 0xaf, 0xe3, 0x83, 0xb0, 0xe3, 0x83, 0xb1, 0xe3, 0x83, + 0xb2, 0xe3, 0x83, 0xb3, 0xe3, 0x83, 0xb3, 0xe3, 0x83, 0xbc, 0xe3, 0x83, 0xb4, + 0xe3, 0x83, 0xb4, 0xe3, 0x82, 0xa1, 0xe3, 0x83, 0xb4, 0xe3, 0x82, 0xa3, 0xe3, + 0x83, 0xb4, 0xe3, 0x82, 0xa7, 0xe3, 0x83, 0xb4, 0xe3, 0x82, 0xa9, 0xe3, 0x83, + 0xb5, 0xe3, 0x83, 0xb6, 0xe3, 0x83, 0xbc +}; +static uint16_t rk_tree_idx[] = { + 0x001b, 0x0022, 0x0025, 0x0028, 0x002d, 0x0030, 0x0039, 0x003b, 0x003c, 0x003f, + 0x0046, 0x0047, 0x004f, 0x0050, 0x0053, 0x005a, 0x005d, 0x0064, 0x0067, 0x006f, + 0x0070, 0x0073, 0x007d, 0x007f, 0x0081, 0x0082, 0x0083, 0x0088, 0x008f, 0x0092, + 0x00af, 0x00b5, 0x00bc, 0x00bf, 0x00c6, 0x00c9, 0x00d1, 0x00d6, 0x00da, 0x00e4, + 0x00e6, 0x00eb, 0x00ec, 0x00f0, 0x00f6, 0x00fc, 0x00fe, 0x0108, 0x010a, 0x010c, + 0x010d, 0x010e, 0x0113, 0x0118, 0x011f, 0x0123, 0x0125, 0x0164, 0x0180, 0x0183, + 0x0199, 0x01ad +}; +static rk_tree_node rk_tree[] = { + {0x2d, 0x00, 0xb2, 0x01}, {0x61, 0x00, 0x01, 0x01}, {0x62, 0x01, 0xff, 0x01}, + {0x63, 0x03, 0xff, 0x01}, {0x64, 0x06, 0xff, 0x01}, {0x65, 0x00, 0x24, 0x01}, + {0x66, 0x0a, 0xff, 0x01}, {0x67, 0x0c, 0xff, 0x01}, {0x68, 0x0f, 0xff, 0x01}, + {0x69, 0x00, 0x03, 0x01}, {0x6a, 0x11, 0xff, 0x01}, {0x6b, 0x13, 0xff, 0x01}, + {0x6c, 0x16, 0xff, 0x01}, {0x6d, 0x1c, 0xff, 0x01}, {0x6e, 0x1e, 0xff, 0x01}, + {0x6f, 0x00, 0x26, 0x01}, {0x70, 0x20, 0xff, 0x01}, {0x72, 0x22, 0xff, 0x01}, + {0x73, 0x24, 0xff, 0x01}, {0x74, 0x27, 0xff, 0x01}, {0x75, 0x00, 0x06, 0x01}, + {0x76, 0x2c, 0xff, 0x01}, {0x77, 0x2d, 0xff, 0x01}, {0x78, 0x2f, 0xff, 0x01}, + {0x79, 0x35, 0xff, 0x01}, {0x7a, 0x36, 0xff, 0x01}, {0xe3, 0x38, 0xff, 0x01}, + {0x61, 0x00, 0x72, 0x01}, {0x62, 0x01, 0x56, 0x01}, {0x65, 0x00, 0x89, 0x01}, + {0x69, 0x00, 0x78, 0x01}, {0x6f, 0x00, 0x8c, 0x01}, {0x75, 0x00, 0x86, 0x01}, + {0x79, 0x02, 0xff, 0x00}, {0x61, 0x00, 0x79, 0x01}, {0x6f, 0x00, 0x7b, 0x01}, + {0x75, 0x00, 0x7a, 0x01}, {0x63, 0x03, 0x56, 0x01}, {0x68, 0x04, 0xff, 0x01}, + {0x79, 0x05, 0xff, 0x01}, {0x61, 0x00, 0x4f, 0x00}, {0x65, 0x00, 0x4e, 0x00}, + {0x69, 0x00, 0x4d, 0x01}, {0x6f, 0x00, 0x51, 0x00}, {0x75, 0x00, 0x50, 0x00}, + {0x61, 0x00, 0x4f, 0x01}, {0x6f, 0x00, 0x51, 0x01}, {0x75, 0x00, 0x50, 0x01}, + {0x61, 0x00, 0x4c, 0x01}, {0x64, 0x06, 0x56, 0x01}, {0x65, 0x00, 0x60, 0x01}, + {0x68, 0x07, 0xff, 0x00}, {0x69, 0x00, 0x61, 0x00}, {0x6f, 0x00, 0x65, 0x01}, + {0x75, 0x00, 0x5c, 0x01}, {0x77, 0x08, 0xff, 0x00}, {0x79, 0x09, 0xff, 0x01}, + {0x69, 0x00, 0x61, 0x01}, {0x75, 0x00, 0x62, 0x01}, {0x75, 0x00, 0x66, 0x01}, + {0x61, 0x00, 0x53, 0x01}, {0x6f, 0x00, 0x55, 0x01}, {0x75, 0x00, 0x54, 0x01}, + {0x61, 0x00, 0x81, 0x00}, {0x65, 0x00, 0x83, 0x00}, {0x66, 0x0a, 0x56, 0x01}, + {0x69, 0x00, 0x82, 0x00}, {0x6f, 0x00, 0x84, 0x00}, {0x75, 0x00, 0x80, 0x01}, + {0x79, 0x0b, 0xff, 0x00}, {0x75, 0x00, 0x85, 0x01}, {0x61, 0x00, 0x28, 0x01}, + {0x65, 0x00, 0x36, 0x01}, {0x67, 0x0c, 0x56, 0x01}, {0x69, 0x00, 0x2d, 0x01}, + {0x6f, 0x00, 0x38, 0x01}, {0x75, 0x00, 0x33, 0x01}, {0x77, 0x0d, 0xff, 0x00}, + {0x79, 0x0e, 0xff, 0x00}, {0x61, 0x00, 0x34, 0x01}, {0x61, 0x00, 0x2e, 0x01}, + {0x6f, 0x00, 0x30, 0x01}, {0x75, 0x00, 0x2f, 0x01}, {0x61, 0x00, 0x71, 0x01}, + {0x65, 0x00, 0x88, 0x01}, {0x68, 0x0f, 0x56, 0x01}, {0x69, 0x00, 0x74, 0x01}, + {0x6f, 0x00, 0x8b, 0x01}, {0x75, 0x00, 0x80, 0x01}, {0x79, 0x10, 0xff, 0x00}, + {0x61, 0x00, 0x75, 0x01}, {0x6f, 0x00, 0x77, 0x01}, {0x75, 0x00, 0x76, 0x01}, + {0x61, 0x00, 0x42, 0x00}, {0x65, 0x00, 0x41, 0x00}, {0x69, 0x00, 0x40, 0x01}, + {0x6a, 0x11, 0x56, 0x01}, {0x6f, 0x00, 0x44, 0x00}, {0x75, 0x00, 0x43, 0x00}, + {0x79, 0x12, 0xff, 0x00}, {0x61, 0x00, 0x42, 0x01}, {0x6f, 0x00, 0x44, 0x01}, + {0x75, 0x00, 0x43, 0x01}, {0x61, 0x00, 0x27, 0x01}, {0x65, 0x00, 0x35, 0x01}, + {0x69, 0x00, 0x29, 0x01}, {0x6b, 0x13, 0x56, 0x01}, {0x6f, 0x00, 0x37, 0x01}, + {0x75, 0x00, 0x31, 0x01}, {0x77, 0x14, 0xff, 0x00}, {0x79, 0x15, 0xff, 0x00}, + {0x61, 0x00, 0x32, 0x01}, {0x61, 0x00, 0x2a, 0x01}, {0x6f, 0x00, 0x2c, 0x01}, + {0x75, 0x00, 0x2b, 0x01}, {0x61, 0x00, 0x00, 0x01}, {0x65, 0x00, 0x23, 0x01}, + {0x69, 0x00, 0x02, 0x01}, {0x6b, 0x17, 0xff, 0x01}, {0x6c, 0x16, 0x56, 0x01}, + {0x6f, 0x00, 0x25, 0x01}, {0x74, 0x18, 0xff, 0x01}, {0x75, 0x00, 0x05, 0x01}, + {0x77, 0x1a, 0xff, 0x01}, {0x79, 0x1b, 0xff, 0x01}, {0x61, 0x00, 0xb0, 0x01}, + {0x65, 0x00, 0xb1, 0x01}, {0x73, 0x19, 0xff, 0x00}, {0x75, 0x00, 0x56, 0x01}, + {0x75, 0x00, 0x56, 0x01}, {0x61, 0x00, 0xa4, 0x01}, {0x61, 0x00, 0x96, 0x01}, + {0x65, 0x00, 0x23, 0x01}, {0x69, 0x00, 0x02, 0x01}, {0x6f, 0x00, 0x9a, 0x01}, + {0x75, 0x00, 0x98, 0x01}, {0x61, 0x00, 0x8e, 0x01}, {0x65, 0x00, 0x94, 0x01}, + {0x69, 0x00, 0x8f, 0x01}, {0x6d, 0x1c, 0x56, 0x01}, {0x6f, 0x00, 0x95, 0x01}, + {0x75, 0x00, 0x93, 0x01}, {0x79, 0x1d, 0xff, 0x00}, {0x61, 0x00, 0x90, 0x01}, + {0x6f, 0x00, 0x92, 0x01}, {0x75, 0x00, 0x91, 0x01}, {0x00, 0x00, 0xa9, 0x01}, + {0x27, 0x00, 0xa9, 0x00}, {0x2d, 0x00, 0xaa, 0x00}, {0x61, 0x00, 0x67, 0x01}, + {0x62, 0x01, 0xa9, 0x00}, {0x63, 0x03, 0xa9, 0x00}, {0x64, 0x06, 0xa9, 0x00}, + {0x65, 0x00, 0x6f, 0x01}, {0x66, 0x0a, 0xa9, 0x00}, {0x67, 0x0c, 0xa9, 0x00}, + {0x68, 0x0f, 0xa9, 0x00}, {0x69, 0x00, 0x68, 0x01}, {0x6a, 0x11, 0xa9, 0x00}, + {0x6b, 0x13, 0xa9, 0x00}, {0x6c, 0x16, 0xa9, 0x00}, {0x6d, 0x1c, 0xa9, 0x00}, + {0x6e, 0x00, 0xa9, 0x00}, {0x6f, 0x00, 0x70, 0x01}, {0x70, 0x20, 0xa9, 0x00}, + {0x72, 0x22, 0xa9, 0x00}, {0x73, 0x24, 0xa9, 0x00}, {0x74, 0x27, 0xa9, 0x00}, + {0x75, 0x00, 0x6e, 0x01}, {0x76, 0x2c, 0xa9, 0x00}, {0x77, 0x2d, 0xa9, 0x00}, + {0x78, 0x2f, 0xa9, 0x00}, {0x79, 0x1f, 0xff, 0x00}, {0x7a, 0x36, 0xa9, 0x00}, + {0xe3, 0x38, 0xa9, 0x00}, {0x00, 0x00, 0xa9, 0x01}, {0x61, 0x00, 0x6b, 0x01}, + {0x65, 0x00, 0x6a, 0x01}, {0x69, 0x00, 0x69, 0x01}, {0x6f, 0x00, 0x6d, 0x01}, + {0x75, 0x00, 0x6c, 0x01}, {0x61, 0x00, 0x73, 0x01}, {0x65, 0x00, 0x8a, 0x01}, + {0x69, 0x00, 0x7c, 0x01}, {0x6f, 0x00, 0x8d, 0x01}, {0x70, 0x20, 0x56, 0x01}, + {0x75, 0x00, 0x87, 0x01}, {0x79, 0x21, 0xff, 0x00}, {0x61, 0x00, 0x7d, 0x01}, + {0x6f, 0x00, 0x7f, 0x01}, {0x75, 0x00, 0x7e, 0x01}, {0x61, 0x00, 0x9c, 0x01}, + {0x65, 0x00, 0xa2, 0x01}, {0x69, 0x00, 0x9d, 0x01}, {0x6f, 0x00, 0xa3, 0x01}, + {0x72, 0x22, 0x56, 0x01}, {0x75, 0x00, 0xa1, 0x01}, {0x79, 0x23, 0xff, 0x00}, + {0x61, 0x00, 0x9e, 0x01}, {0x6f, 0x00, 0xa0, 0x01}, {0x75, 0x00, 0x9f, 0x01}, + {0x61, 0x00, 0x39, 0x01}, {0x65, 0x00, 0x47, 0x01}, {0x68, 0x25, 0xff, 0x00}, + {0x69, 0x00, 0x3b, 0x01}, {0x6f, 0x00, 0x49, 0x01}, {0x73, 0x24, 0x56, 0x01}, + {0x75, 0x00, 0x45, 0x01}, {0x79, 0x26, 0xff, 0x00}, {0x61, 0x00, 0x3d, 0x00}, + {0x65, 0x00, 0x3c, 0x00}, {0x69, 0x00, 0x3b, 0x01}, {0x6f, 0x00, 0x3f, 0x00}, + {0x75, 0x00, 0x3e, 0x00}, {0x61, 0x00, 0x3d, 0x01}, {0x65, 0x00, 0x3c, 0x01}, + {0x6f, 0x00, 0x3f, 0x01}, {0x75, 0x00, 0x3e, 0x01}, {0x61, 0x00, 0x4b, 0x01}, + {0x65, 0x00, 0x5d, 0x01}, {0x68, 0x28, 0xff, 0x00}, {0x69, 0x00, 0x4d, 0x01}, + {0x6f, 0x00, 0x63, 0x01}, {0x73, 0x29, 0xff, 0x00}, {0x74, 0x27, 0x56, 0x01}, + {0x75, 0x00, 0x57, 0x01}, {0x77, 0x2a, 0xff, 0x00}, {0x79, 0x2b, 0xff, 0x00}, + {0x69, 0x00, 0x5e, 0x01}, {0x75, 0x00, 0x5f, 0x01}, {0x61, 0x00, 0x58, 0x00}, + {0x65, 0x00, 0x5a, 0x00}, {0x69, 0x00, 0x59, 0x00}, {0x6f, 0x00, 0x5b, 0x00}, + {0x75, 0x00, 0x57, 0x01}, {0x75, 0x00, 0x64, 0x01}, {0x61, 0x00, 0x4f, 0x01}, + {0x65, 0x00, 0x4e, 0x01}, {0x6f, 0x00, 0x51, 0x01}, {0x75, 0x00, 0x50, 0x01}, + {0x61, 0x00, 0xac, 0x00}, {0x65, 0x00, 0xae, 0x00}, {0x69, 0x00, 0xad, 0x00}, + {0x6f, 0x00, 0xaf, 0x00}, {0x75, 0x00, 0xab, 0x01}, {0x76, 0x2c, 0x56, 0x01}, + {0x61, 0x00, 0xa5, 0x01}, {0x65, 0x00, 0x0b, 0x01}, {0x69, 0x00, 0x08, 0x01}, + {0x6f, 0x00, 0xa8, 0x01}, {0x77, 0x2d, 0x56, 0x01}, {0x79, 0x2e, 0xff, 0x01}, + {0x65, 0x00, 0xa7, 0x01}, {0x69, 0x00, 0xa6, 0x01}, {0x61, 0x00, 0x00, 0x01}, + {0x65, 0x00, 0x23, 0x01}, {0x69, 0x00, 0x02, 0x01}, {0x6b, 0x30, 0xff, 0x01}, + {0x6f, 0x00, 0x25, 0x01}, {0x74, 0x31, 0xff, 0x01}, {0x75, 0x00, 0x05, 0x01}, + {0x77, 0x33, 0xff, 0x01}, {0x78, 0x2f, 0x56, 0x01}, {0x79, 0x34, 0xff, 0x01}, + {0x61, 0x00, 0xb0, 0x01}, {0x65, 0x00, 0xb1, 0x01}, {0x73, 0x32, 0xff, 0x00}, + {0x75, 0x00, 0x56, 0x01}, {0x75, 0x00, 0x56, 0x01}, {0x61, 0x00, 0xa4, 0x01}, + {0x61, 0x00, 0x96, 0x01}, {0x65, 0x00, 0x23, 0x01}, {0x69, 0x00, 0x02, 0x01}, + {0x6f, 0x00, 0x9a, 0x01}, {0x75, 0x00, 0x98, 0x01}, {0x61, 0x00, 0x97, 0x01}, + {0x65, 0x00, 0x04, 0x01}, {0x6f, 0x00, 0x9b, 0x01}, {0x75, 0x00, 0x99, 0x01}, + {0x79, 0x35, 0x56, 0x01}, {0x61, 0x00, 0x3a, 0x01}, {0x65, 0x00, 0x48, 0x01}, + {0x69, 0x00, 0x40, 0x01}, {0x6f, 0x00, 0x4a, 0x01}, {0x75, 0x00, 0x46, 0x01}, + {0x79, 0x37, 0xff, 0x00}, {0x7a, 0x36, 0x56, 0x01}, {0x61, 0x00, 0x42, 0x01}, + {0x65, 0x00, 0x41, 0x01}, {0x6f, 0x00, 0x44, 0x01}, {0x75, 0x00, 0x43, 0x01}, + {0x81, 0x39, 0xff, 0x01}, {0x82, 0x3d, 0xff, 0x01}, {0x81, 0x00, 0x00, 0x01}, + {0x82, 0x00, 0x01, 0x01}, {0x83, 0x00, 0x02, 0x01}, {0x84, 0x00, 0x03, 0x01}, + {0x85, 0x00, 0x05, 0x01}, {0x86, 0x3a, 0xff, 0x01}, {0x87, 0x00, 0x23, 0x01}, + {0x88, 0x00, 0x24, 0x01}, {0x89, 0x00, 0x25, 0x01}, {0x8a, 0x00, 0x26, 0x01}, + {0x8b, 0x00, 0x27, 0x01}, {0x8c, 0x00, 0x28, 0x01}, {0x8d, 0x00, 0x29, 0x01}, + {0x8e, 0x00, 0x2d, 0x01}, {0x8f, 0x00, 0x31, 0x01}, {0x90, 0x00, 0x33, 0x01}, + {0x91, 0x00, 0x35, 0x01}, {0x92, 0x00, 0x36, 0x01}, {0x93, 0x00, 0x37, 0x01}, + {0x94, 0x00, 0x38, 0x01}, {0x95, 0x00, 0x39, 0x01}, {0x96, 0x00, 0x3a, 0x01}, + {0x97, 0x00, 0x3b, 0x01}, {0x98, 0x00, 0x40, 0x01}, {0x99, 0x00, 0x45, 0x01}, + {0x9a, 0x00, 0x46, 0x01}, {0x9b, 0x00, 0x47, 0x01}, {0x9c, 0x00, 0x48, 0x01}, + {0x9d, 0x00, 0x49, 0x01}, {0x9e, 0x00, 0x4a, 0x01}, {0x9f, 0x00, 0x4b, 0x01}, + {0xa0, 0x00, 0x4c, 0x01}, {0xa1, 0x00, 0x4d, 0x01}, {0xa2, 0x00, 0x52, 0x01}, + {0xa3, 0x00, 0x56, 0x01}, {0xa4, 0x00, 0x57, 0x01}, {0xa5, 0x00, 0x5c, 0x01}, + {0xa6, 0x00, 0x5d, 0x01}, {0xa7, 0x00, 0x60, 0x01}, {0xa8, 0x00, 0x63, 0x01}, + {0xa9, 0x00, 0x65, 0x01}, {0xaa, 0x00, 0x67, 0x01}, {0xab, 0x00, 0x68, 0x01}, + {0xac, 0x00, 0x6e, 0x01}, {0xad, 0x00, 0x6f, 0x01}, {0xae, 0x00, 0x70, 0x01}, + {0xaf, 0x00, 0x71, 0x01}, {0xb0, 0x00, 0x72, 0x01}, {0xb1, 0x00, 0x73, 0x01}, + {0xb2, 0x00, 0x74, 0x01}, {0xb3, 0x00, 0x78, 0x01}, {0xb4, 0x00, 0x7c, 0x01}, + {0xb5, 0x00, 0x80, 0x01}, {0xb6, 0x00, 0x86, 0x01}, {0xb7, 0x00, 0x87, 0x01}, + {0xb8, 0x00, 0x88, 0x01}, {0xb9, 0x00, 0x89, 0x01}, {0xba, 0x00, 0x8a, 0x01}, + {0xbb, 0x00, 0x8b, 0x01}, {0xbc, 0x00, 0x8c, 0x01}, {0xbd, 0x00, 0x8d, 0x01}, + {0xbe, 0x00, 0x8e, 0x01}, {0xbf, 0x00, 0x8f, 0x01}, {0x00, 0x00, 0x06, 0x00}, + {0x2d, 0x00, 0x22, 0x00}, {0x61, 0x00, 0x07, 0x00}, {0x62, 0x01, 0x06, 0x00}, + {0x63, 0x03, 0x06, 0x00}, {0x64, 0x06, 0x06, 0x00}, {0x65, 0x00, 0x0c, 0x00}, + {0x66, 0x0a, 0x06, 0x00}, {0x67, 0x0c, 0x06, 0x00}, {0x68, 0x0f, 0x06, 0x00}, + {0x69, 0x00, 0x09, 0x00}, {0x6a, 0x11, 0x06, 0x00}, {0x6b, 0x13, 0x06, 0x00}, + {0x6c, 0x16, 0x06, 0x00}, {0x6d, 0x1c, 0x06, 0x00}, {0x6e, 0x1e, 0x06, 0x00}, + {0x6f, 0x00, 0x0d, 0x00}, {0x70, 0x20, 0x06, 0x00}, {0x72, 0x22, 0x06, 0x00}, + {0x73, 0x24, 0x06, 0x00}, {0x74, 0x27, 0x06, 0x00}, {0x75, 0x00, 0x0a, 0x00}, + {0x76, 0x2c, 0x06, 0x00}, {0x77, 0x2d, 0x06, 0x00}, {0x78, 0x2f, 0x06, 0x00}, + {0x79, 0x35, 0x06, 0x00}, {0x7a, 0x36, 0x06, 0x00}, {0xe3, 0x3b, 0xff, 0x01}, + {0x00, 0x00, 0x06, 0x00}, {0x81, 0x39, 0x06, 0x00}, {0x82, 0x3c, 0xff, 0x01}, + {0x00, 0x00, 0x06, 0x01}, {0x80, 0x00, 0x0e, 0x00}, {0x81, 0x00, 0x0f, 0x00}, + {0x82, 0x00, 0x10, 0x00}, {0x83, 0x00, 0x11, 0x00}, {0x84, 0x00, 0x12, 0x00}, + {0x85, 0x00, 0x13, 0x00}, {0x86, 0x00, 0x14, 0x00}, {0x87, 0x00, 0x15, 0x00}, + {0x88, 0x00, 0x16, 0x00}, {0x89, 0x00, 0x17, 0x00}, {0x8a, 0x00, 0x18, 0x00}, + {0x8b, 0x00, 0x19, 0x00}, {0x8c, 0x00, 0x1a, 0x00}, {0x8d, 0x00, 0x1b, 0x00}, + {0x8e, 0x00, 0x1c, 0x00}, {0x8f, 0x00, 0x1d, 0x00}, {0x90, 0x00, 0x1e, 0x00}, + {0x91, 0x00, 0x1f, 0x00}, {0x92, 0x00, 0x20, 0x00}, {0x93, 0x00, 0x21, 0x00}, + {0x9b, 0x00, 0xab, 0x01}, {0x80, 0x00, 0x93, 0x01}, {0x81, 0x00, 0x94, 0x01}, + {0x82, 0x00, 0x95, 0x01}, {0x83, 0x00, 0x96, 0x01}, {0x84, 0x00, 0x97, 0x01}, + {0x85, 0x00, 0x98, 0x01}, {0x86, 0x00, 0x99, 0x01}, {0x87, 0x00, 0x9a, 0x01}, + {0x88, 0x00, 0x9b, 0x01}, {0x89, 0x00, 0x9c, 0x01}, {0x8a, 0x00, 0x9d, 0x01}, + {0x8b, 0x00, 0xa1, 0x01}, {0x8c, 0x00, 0xa2, 0x01}, {0x8d, 0x00, 0xa3, 0x01}, + {0x8e, 0x00, 0xa4, 0x01}, {0x8f, 0x00, 0xa5, 0x01}, {0x90, 0x00, 0xa6, 0x01}, + {0x91, 0x00, 0xa7, 0x01}, {0x92, 0x00, 0xa8, 0x01}, {0x93, 0x00, 0xa9, 0x01} +}; + +static rk_tree_node * +rk_lookup(uint8_t state, uint8_t code) +{ + if (state < sizeof(rk_tree_idx)/sizeof(uint16_t)) { + uint16_t ns = state ? rk_tree_idx[state - 1] : 0; + uint16_t ne = rk_tree_idx[state]; + while (ns < ne) { + uint16_t m = (ns + ne)>>1; + rk_tree_node *rn = &rk_tree[m]; + if (rn->code == code) { return rn; } + if (rn->code < code) { + ns = m + 1; + } else { + ne = m; + } + } + } + return NULL; +} + +static uint32_t +rk_emit(rk_tree_node *rn, char **str) +{ + if (rn && rn->emit != 0xff) { + uint16_t pos = rn->emit ? rk_str_idx[rn->emit - 1] : 0; + *str = &rk_str[pos]; + return (uint32_t)(rk_str_idx[rn->emit] - pos); + } else { + *str = NULL; + return 0; + } +} + +#define RK_OUTPUT(e,l) do {\ + if (oc < oe) {\ + uint32_t l_ = (oc + (l) < oe) ? (l) : (oe - oc);\ + grn_memcpy(oc, (e), l_);\ + oc += l_;\ + ic_ = ic;\ + }\ +} while (0) + +static uint32_t +rk_conv(const char *str, uint32_t str_len, uint8_t *buf, uint32_t buf_size, uint8_t *statep) +{ + uint32_t l; + uint8_t state = 0; + rk_tree_node *rn; + char *e; + uint8_t *oc = buf, *oe = oc + buf_size; + const uint8_t *ic = (uint8_t *)str, *ic_ = ic, *ie = ic + str_len; + while (ic < ie) { + if ((rn = rk_lookup(state, *ic))) { + ic++; + if ((l = rk_emit(rn, &e))) { RK_OUTPUT(e, l); } + state = rn->next; + } else { + if (!state) { ic++; } + if (ic_ < ic) { RK_OUTPUT(ic_, ic - ic_); } + state = 0; + } + } +#ifdef FLUSH_UNRESOLVED_INPUT + if ((rn = rk_lookup(state, 0))) { + if ((l = rk_emit(rn, &e))) { RK_OUTPUT(e, l); } + state = rn->next; + } else { + if (ic_ < ic) { RK_OUTPUT(ic_, ic - ic_); } + } +#endif /* FLUSH_UNRESOLVED_INPUT */ + *statep = state; + return oc - buf; +} + +static grn_id +sub_search(grn_ctx *ctx, grn_pat *pat, grn_id id, + int *c0, uint8_t *key, uint32_t key_len) +{ + pat_node *pn; + uint32_t len = key_len * 16; + if (!key_len) { return id; } + PAT_AT(pat, id, pn); + while (pn) { + int ch; + ch = PAT_CHK(pn); + if (*c0 < ch && ch < len - 1) { + if (ch & 1) { + id = (ch + 1 < len) ? pn->lr[1] : pn->lr[0]; + } else { + id = pn->lr[nth_bit(key, ch, len)]; + } + *c0 = ch; + PAT_AT(pat, id, pn); + } else { + const uint8_t *k = pat_node_get_key(ctx, pat, pn); + return (k && key_len <= PAT_LEN(pn) && !memcmp(k, key, key_len)) ? id : GRN_ID_NIL; + } + } + return GRN_ID_NIL; +} + +static void +search_push(grn_ctx *ctx, grn_pat *pat, grn_pat_cursor *c, + uint8_t *key, uint32_t key_len, uint8_t state, grn_id id, int c0, int flags) +{ + if (state) { + int step; + uint16_t ns, ne; + if (flags & GRN_CURSOR_DESCENDING) { + ns = rk_tree_idx[state - 1]; + ne = rk_tree_idx[state]; + step = 1; + } else { + ns = rk_tree_idx[state] - 1; + ne = rk_tree_idx[state - 1] - 1; + step = -1; + } + for (; ns != ne; ns += step) { + rk_tree_node *rn = &rk_tree[ns]; + if (rn->attr) { + char *e; + uint32_t l = rk_emit(rn, &e); + if (l) { + if (l + key_len <= GRN_TABLE_MAX_KEY_SIZE) { + int ch = c0; + grn_id i; + grn_memcpy(key + key_len, e, l); + if ((i = sub_search(ctx, pat, id, &ch, key, key_len + l))) { + search_push(ctx, pat, c, key, key_len + l, rn->next, i, ch, flags); + } + } + } else { + search_push(ctx, pat, c, key, key_len, rn->next, id, c0, flags); + } + } + } + } else { + pat_node *pn; + PAT_AT(pat, id, pn); + if (pn) { + int ch = PAT_CHK(pn); + uint32_t len = key_len * 16; + if (c0 < ch) { + if (flags & GRN_CURSOR_DESCENDING) { + if ((ch > len - 1) || !(flags & GRN_CURSOR_GT)) { push(c, pn->lr[0], ch); } + push(c, pn->lr[1], ch); + } else { + push(c, pn->lr[1], ch); + if ((ch > len - 1) || !(flags & GRN_CURSOR_GT)) { push(c, pn->lr[0], ch); } + } + } else { + if (PAT_LEN(pn) * 16 > len || !(flags & GRN_CURSOR_GT)) { push(c, id, ch); } + } + } + } +} + +static grn_rc +set_cursor_rk(grn_ctx *ctx, grn_pat *pat, grn_pat_cursor *c, + const void *key, uint32_t key_len, int flags) +{ + grn_id id; + uint8_t state; + pat_node *pn; + int c0 = -1; + uint32_t len, byte_len; + uint8_t keybuf[GRN_TABLE_MAX_KEY_SIZE]; + if (flags & GRN_CURSOR_SIZE_BY_BIT) { return GRN_OPERATION_NOT_SUPPORTED; } + byte_len = rk_conv(key, key_len, keybuf, GRN_TABLE_MAX_KEY_SIZE, &state); + len = byte_len * 16; + PAT_AT(pat, 0, pn); + id = pn->lr[1]; + if ((id = sub_search(ctx, pat, id, &c0, keybuf, byte_len))) { + search_push(ctx, pat, c, keybuf, byte_len, state, id, c0, flags); + } + return ctx->rc; +} + +uint32_t +grn_pat_total_key_size(grn_ctx *ctx, grn_pat *pat) +{ + return pat->header->curr_key; +} + +grn_bool +grn_pat_is_key_encoded(grn_ctx *ctx, grn_pat *pat) +{ + grn_obj *domain; + uint32_t key_size; + + domain = grn_ctx_at(ctx, pat->obj.header.domain); + if (grn_obj_is_type(ctx, domain)) { + key_size = grn_type_size(ctx, domain); + } else { + key_size = sizeof(grn_id); + } + + return KEY_NEEDS_CONVERT(pat, key_size); +} + +grn_rc +grn_pat_dirty(grn_ctx *ctx, grn_pat *pat) +{ + grn_rc rc = GRN_SUCCESS; + + CRITICAL_SECTION_ENTER(pat->lock); + if (!pat->is_dirty) { + uint32_t n_dirty_opens; + pat->is_dirty = GRN_TRUE; + GRN_ATOMIC_ADD_EX(&(pat->header->n_dirty_opens), 1, n_dirty_opens); + rc = grn_io_flush(ctx, pat->io); + } + CRITICAL_SECTION_LEAVE(pat->lock); + + return rc; +} + +grn_bool +grn_pat_is_dirty(grn_ctx *ctx, grn_pat *pat) +{ + return pat->header->n_dirty_opens > 0; +} + +grn_rc +grn_pat_clean(grn_ctx *ctx, grn_pat *pat) +{ + grn_rc rc = GRN_SUCCESS; + + CRITICAL_SECTION_ENTER(pat->lock); + if (pat->is_dirty) { + uint32_t n_dirty_opens; + pat->is_dirty = GRN_FALSE; + GRN_ATOMIC_ADD_EX(&(pat->header->n_dirty_opens), -1, n_dirty_opens); + rc = grn_io_flush(ctx, pat->io); + } + CRITICAL_SECTION_LEAVE(pat->lock); + + return rc; +} + +grn_rc +grn_pat_clear_dirty(grn_ctx *ctx, grn_pat *pat) +{ + grn_rc rc = GRN_SUCCESS; + + CRITICAL_SECTION_ENTER(pat->lock); + pat->is_dirty = GRN_FALSE; + pat->header->n_dirty_opens = 0; + rc = grn_io_flush(ctx, pat->io); + CRITICAL_SECTION_LEAVE(pat->lock); + + return rc; +} diff --git a/storage/mroonga/vendor/groonga/lib/plugin.c b/storage/mroonga/vendor/groonga/lib/plugin.c new file mode 100644 index 00000000..ce4e3347 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/plugin.c @@ -0,0 +1,1396 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include "grn_ctx_impl_mrb.h" +#include "grn_proc.h" +#include + +#include +#include +#include + +#include +#ifdef HAVE_DIRENT_H +# include +#endif /* HAVE_DIRENT_H */ + +#ifndef S_ISREG +# ifdef _S_IFREG +# define S_ISREG(mode) (mode & _S_IFREG) +# endif /* _S_IFREG */ +#endif /* !S_ISREG */ + +#include "grn_db.h" +#include "grn_plugin.h" +#include "grn_ctx_impl.h" +#include "grn_util.h" + +#ifdef GRN_WITH_MRUBY +# include +#endif /* GRN_WITH_MRUBY */ + +static grn_hash *grn_plugins = NULL; +static grn_critical_section grn_plugins_lock; +static grn_ctx grn_plugins_ctx; + +#ifdef HAVE_DLFCN_H +# include +# define grn_dl_open(filename) dlopen(filename, RTLD_LAZY | RTLD_LOCAL) +# define grn_dl_open_error_label() dlerror() +# define grn_dl_close(dl) (dlclose(dl) == 0) +# define grn_dl_close_error_label() dlerror() +# define grn_dl_sym(dl, symbol) dlsym(dl, symbol) +# define grn_dl_sym_error_label() dlerror() +# define grn_dl_clear_error() dlerror() +#else +# define grn_dl_open(filename) LoadLibrary(filename) +# define grn_dl_open_error_label() "LoadLibrary" +# define grn_dl_close(dl) (FreeLibrary(dl) != 0) +# define grn_dl_close_error_label() "FreeLibrary" +# define grn_dl_sym(dl, symbol) ((void *)GetProcAddress(dl, symbol)) +# define grn_dl_sym_error_label() "GetProcAddress" +# define grn_dl_clear_error() +#endif + +#define GRN_PLUGIN_KEY_SIZE(filename) (strlen((filename)) + 1) + +static char grn_plugins_dir[GRN_ENV_BUFFER_SIZE]; + +void +grn_plugin_init_from_env(void) +{ + grn_getenv("GRN_PLUGINS_DIR", + grn_plugins_dir, + GRN_ENV_BUFFER_SIZE); +} + +static int +compute_name_size(const char *name, int name_size) +{ + if (name_size < 0) { + if (name) { + name_size = strlen(name); + } else { + name_size = 0; + } + } + return name_size; +} + +grn_id +grn_plugin_reference(grn_ctx *ctx, const char *filename) +{ + grn_id id; + grn_plugin **plugin = NULL; + + CRITICAL_SECTION_ENTER(grn_plugins_lock); + id = grn_hash_get(&grn_plugins_ctx, grn_plugins, + filename, GRN_PLUGIN_KEY_SIZE(filename), + (void **)&plugin); + if (plugin) { + (*plugin)->refcount++; + } + CRITICAL_SECTION_LEAVE(grn_plugins_lock); + + return id; +} + +const char * +grn_plugin_path(grn_ctx *ctx, grn_id id) +{ + const char *path; + grn_plugin *plugin; + int value_size; + const char *system_plugins_dir; + size_t system_plugins_dir_size; + + if (id == GRN_ID_NIL) { + return NULL; + } + + CRITICAL_SECTION_ENTER(grn_plugins_lock); + value_size = grn_hash_get_value(&grn_plugins_ctx, grn_plugins, id, &plugin); + CRITICAL_SECTION_LEAVE(grn_plugins_lock); + + if (!plugin) { + return NULL; + } + + path = plugin->path; + system_plugins_dir = grn_plugin_get_system_plugins_dir(); + system_plugins_dir_size = strlen(system_plugins_dir); + if (strncmp(system_plugins_dir, path, system_plugins_dir_size) == 0) { + const char *plugin_name = path + system_plugins_dir_size; + while (plugin_name[0] == '/') { + plugin_name++; + } + /* TODO: remove suffix too? */ + return plugin_name; + } else { + return path; + } +} + +#define GRN_PLUGIN_FUNC_PREFIX "grn_plugin_impl_" + +static grn_rc +grn_plugin_call_init(grn_ctx *ctx, grn_id id) +{ + grn_plugin *plugin; + int size; + + size = grn_hash_get_value(&grn_plugins_ctx, grn_plugins, id, &plugin); + if (size == 0) { + return GRN_INVALID_ARGUMENT; + } + + if (plugin->init_func) { + return plugin->init_func(ctx); + } + + return GRN_SUCCESS; +} + +#ifdef GRN_WITH_MRUBY +static grn_rc +grn_plugin_call_register_mrb(grn_ctx *ctx, grn_id id, grn_plugin *plugin) +{ + grn_mrb_data *data; + mrb_state *mrb; + struct RClass *module; + struct RClass *plugin_loader_class; + int arena_index; + + grn_ctx_impl_mrb_ensure_init(ctx); + if (ctx->rc != GRN_SUCCESS) { + return ctx->rc; + } + + data = &(ctx->impl->mrb); + mrb = data->state; + module = data->module; + + { + int added; + grn_hash_add(ctx, ctx->impl->mrb.registered_plugins, + &id, sizeof(grn_id), NULL, &added); + if (!added) { + return ctx->rc; + } + } + + arena_index = mrb_gc_arena_save(mrb); + plugin_loader_class = mrb_class_get_under(mrb, module, "PluginLoader"); + mrb_funcall(mrb, mrb_obj_value(plugin_loader_class), + "load_file", 1, mrb_str_new_cstr(mrb, ctx->impl->plugin_path)); + mrb_gc_arena_restore(mrb, arena_index); + return ctx->rc; +} +#endif /*GRN_WITH_MRUBY */ + +static grn_rc +grn_plugin_call_register(grn_ctx *ctx, grn_id id) +{ + grn_plugin *plugin; + int size; + + CRITICAL_SECTION_ENTER(grn_plugins_lock); + size = grn_hash_get_value(&grn_plugins_ctx, grn_plugins, id, &plugin); + CRITICAL_SECTION_LEAVE(grn_plugins_lock); + + if (size == 0) { + return GRN_INVALID_ARGUMENT; + } + +#ifdef GRN_WITH_MRUBY + if (!plugin->dl) { + return grn_plugin_call_register_mrb(ctx, id, plugin); + } +#endif /* GRN_WITH_MRUBY */ + + if (plugin->register_func) { + return plugin->register_func(ctx); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_plugin_call_fin(grn_ctx *ctx, grn_id id) +{ + grn_plugin *plugin; + int size; + + size = grn_hash_get_value(&grn_plugins_ctx, grn_plugins, id, &plugin); + if (size == 0) { + return GRN_INVALID_ARGUMENT; + } + + if (plugin->fin_func) { + return plugin->fin_func(ctx); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_plugin_initialize(grn_ctx *ctx, grn_plugin *plugin, + grn_dl dl, grn_id id, const char *path) +{ + plugin->dl = dl; + +#define GET_SYMBOL(type) do { \ + grn_dl_clear_error(); \ + plugin->type ## _func = grn_dl_sym(dl, GRN_PLUGIN_FUNC_PREFIX #type); \ + if (!plugin->type ## _func) { \ + const char *label; \ + label = grn_dl_sym_error_label(); \ + SERR("%s", label); \ + } \ +} while (0) + + GET_SYMBOL(init); + GET_SYMBOL(register); + GET_SYMBOL(fin); + +#undef GET_SYMBOL + + if (!plugin->init_func || !plugin->register_func || !plugin->fin_func) { + ERR(GRN_INVALID_FORMAT, + "init func (%s) %sfound, " + "register func (%s) %sfound and " + "fin func (%s) %sfound", + GRN_PLUGIN_FUNC_PREFIX "init", plugin->init_func ? "" : "not ", + GRN_PLUGIN_FUNC_PREFIX "register", plugin->register_func ? "" : "not ", + GRN_PLUGIN_FUNC_PREFIX "fin", plugin->fin_func ? "" : "not "); + } + + if (!ctx->rc) { + ctx->impl->plugin_path = path; + grn_plugin_call_init(ctx, id); + ctx->impl->plugin_path = NULL; + } + + return ctx->rc; +} + +#ifdef GRN_WITH_MRUBY +static grn_id +grn_plugin_open_mrb(grn_ctx *ctx, const char *filename, size_t filename_size) +{ + grn_ctx *plugins_ctx = &grn_plugins_ctx; + grn_id id = GRN_ID_NIL; + grn_plugin **plugin = NULL; + + grn_ctx_impl_mrb_ensure_init(ctx); + if (ctx->rc != GRN_SUCCESS) { + return GRN_ID_NIL; + } + + if (!ctx->impl->mrb.state) { + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "mruby support isn't enabled"); + return GRN_ID_NIL; + } + + id = grn_hash_add(plugins_ctx, grn_plugins, filename, filename_size, + (void **)&plugin, NULL); + if (!id) { + return id; + } + + { + grn_ctx *ctx = plugins_ctx; + *plugin = GRN_MALLOCN(grn_plugin, 1); + } + if (!*plugin) { + grn_hash_delete_by_id(plugins_ctx, grn_plugins, id, NULL); + return GRN_ID_NIL; + } + + grn_memcpy((*plugin)->path, filename, filename_size); + (*plugin)->dl = NULL; + (*plugin)->init_func = NULL; + (*plugin)->register_func = NULL; + (*plugin)->fin_func = NULL; + (*plugin)->refcount = 1; + + return id; +} +#endif /* GRN_WITH_MRUBY */ + +grn_id +grn_plugin_open(grn_ctx *ctx, const char *filename) +{ + grn_ctx *plugins_ctx = &grn_plugins_ctx; + grn_id id = GRN_ID_NIL; + grn_dl dl; + grn_plugin **plugin = NULL; + size_t filename_size; + + filename_size = GRN_PLUGIN_KEY_SIZE(filename); + + CRITICAL_SECTION_ENTER(grn_plugins_lock); + if ((id = grn_hash_get(plugins_ctx, grn_plugins, filename, filename_size, + (void **)&plugin))) { + (*plugin)->refcount++; + goto exit; + } + +#ifdef GRN_WITH_MRUBY + { + const char *mrb_suffix; + mrb_suffix = grn_plugin_get_ruby_suffix(); + if (filename_size > strlen(mrb_suffix) && + strcmp(filename + (strlen(filename) - strlen(mrb_suffix)), + mrb_suffix) == 0) { + id = grn_plugin_open_mrb(ctx, filename, filename_size); + goto exit; + } + } +#endif /* GRN_WITH_MRUBY */ + + if ((dl = grn_dl_open(filename))) { + if ((id = grn_hash_add(plugins_ctx, grn_plugins, filename, filename_size, + (void **)&plugin, NULL))) { + { + grn_ctx *ctx = plugins_ctx; + *plugin = GRN_MALLOCN(grn_plugin, 1); + } + if (*plugin) { + grn_memcpy((*plugin)->path, filename, filename_size); + if (grn_plugin_initialize(ctx, *plugin, dl, id, filename)) { + { + grn_ctx *ctx = plugins_ctx; + GRN_FREE(*plugin); + } + *plugin = NULL; + } + } + if (!*plugin) { + grn_hash_delete_by_id(plugins_ctx, grn_plugins, id, NULL); + if (grn_dl_close(dl)) { + /* Now, __FILE__ set in plugin is invalid. */ + ctx->errline = 0; + ctx->errfile = NULL; + } else { + const char *label; + label = grn_dl_close_error_label(); + SERR("%s", label); + } + id = GRN_ID_NIL; + } else { + (*plugin)->refcount = 1; + } + } else { + if (!grn_dl_close(dl)) { + const char *label; + label = grn_dl_close_error_label(); + SERR("%s", label); + } + } + } else { + const char *label; + label = grn_dl_open_error_label(); + SERR("%s", label); + } + +exit: + CRITICAL_SECTION_LEAVE(grn_plugins_lock); + + return id; +} + +grn_rc +grn_plugin_close(grn_ctx *ctx, grn_id id) +{ + grn_ctx *plugins_ctx = &grn_plugins_ctx; + grn_rc rc; + grn_plugin *plugin; + + if (id == GRN_ID_NIL) { + return GRN_INVALID_ARGUMENT; + } + + CRITICAL_SECTION_ENTER(grn_plugins_lock); + if (!grn_hash_get_value(plugins_ctx, grn_plugins, id, &plugin)) { + rc = GRN_INVALID_ARGUMENT; + goto exit; + } + if (--plugin->refcount) { + rc = GRN_SUCCESS; + goto exit; + } + if (plugin->dl) { + grn_plugin_call_fin(ctx, id); + if (!grn_dl_close(plugin->dl)) { + const char *label; + label = grn_dl_close_error_label(); + SERR("%s", label); + } + } + { + grn_ctx *ctx = plugins_ctx; + GRN_FREE(plugin); + } + rc = grn_hash_delete_by_id(plugins_ctx, grn_plugins, id, NULL); + +exit: + CRITICAL_SECTION_LEAVE(grn_plugins_lock); + + return rc; +} + +void * +grn_plugin_sym(grn_ctx *ctx, grn_id id, const char *symbol) +{ + grn_plugin *plugin; + grn_dl_symbol func; + + if (id == GRN_ID_NIL) { + return NULL; + } + + CRITICAL_SECTION_ENTER(grn_plugins_lock); + if (!grn_hash_get_value(&grn_plugins_ctx, grn_plugins, id, &plugin)) { + func = NULL; + goto exit; + } + grn_dl_clear_error(); + if (!(func = grn_dl_sym(plugin->dl, symbol))) { + const char *label; + label = grn_dl_sym_error_label(); + SERR("%s", label); + } + +exit: + CRITICAL_SECTION_LEAVE(grn_plugins_lock); + + return func; +} + +grn_rc +grn_plugins_init(void) +{ + CRITICAL_SECTION_INIT(grn_plugins_lock); + grn_ctx_init(&grn_plugins_ctx, 0); + grn_plugins = grn_hash_create(&grn_plugins_ctx, NULL, + PATH_MAX, sizeof(grn_plugin *), + GRN_OBJ_KEY_VAR_SIZE); + if (!grn_plugins) { + grn_ctx_fin(&grn_plugins_ctx); + return GRN_NO_MEMORY_AVAILABLE; + } + return GRN_SUCCESS; +} + +grn_rc +grn_plugins_fin(void) +{ + grn_rc rc; + if (!grn_plugins) { return GRN_INVALID_ARGUMENT; } + GRN_HASH_EACH(&grn_plugins_ctx, grn_plugins, id, NULL, NULL, NULL, { + grn_plugin_close(&grn_plugins_ctx, id); + }); + rc = grn_hash_close(&grn_plugins_ctx, grn_plugins); + grn_ctx_fin(&grn_plugins_ctx); + CRITICAL_SECTION_FIN(grn_plugins_lock); + return rc; +} + +const char * +grn_plugin_get_suffix(void) +{ + return GRN_PLUGIN_SUFFIX; +} + +const char * +grn_plugin_get_ruby_suffix(void) +{ + return ".rb"; +} + +grn_rc +grn_plugin_register_by_path(grn_ctx *ctx, const char *path) +{ + grn_obj *db; + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "db not initialized"); + return ctx->rc; + } + GRN_API_ENTER; + if (GRN_DB_P(db)) { + grn_id id; + id = grn_plugin_open(ctx, path); + if (id) { + ctx->impl->plugin_path = path; + ctx->rc = grn_plugin_call_register(ctx, id); + ctx->impl->plugin_path = NULL; + grn_plugin_close(ctx, id); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "invalid db assigned"); + } + GRN_API_RETURN(ctx->rc); +} + +#ifdef WIN32 +static char *windows_plugins_dir = NULL; +static char windows_plugins_dir_buffer[PATH_MAX]; +static const char * +grn_plugin_get_default_system_plugins_dir(void) +{ + if (!windows_plugins_dir) { + const char *base_dir; + const char *relative_path = GRN_RELATIVE_PLUGINS_DIR; + size_t base_dir_length; + + base_dir = grn_windows_base_dir(); + base_dir_length = strlen(base_dir); + grn_strcpy(windows_plugins_dir_buffer, PATH_MAX, base_dir); + grn_strcat(windows_plugins_dir_buffer, PATH_MAX, "/"); + grn_strcat(windows_plugins_dir_buffer, PATH_MAX, relative_path); + windows_plugins_dir = windows_plugins_dir_buffer; + } + return windows_plugins_dir; +} + +#else /* WIN32 */ +static const char * +grn_plugin_get_default_system_plugins_dir(void) +{ + return GRN_PLUGINS_DIR; +} +#endif /* WIN32 */ + +const char * +grn_plugin_get_system_plugins_dir(void) +{ + if (grn_plugins_dir[0]) { + return grn_plugins_dir; + } else { + return grn_plugin_get_default_system_plugins_dir(); + } +} + +static char * +grn_plugin_find_path_raw(grn_ctx *ctx, const char *path) +{ + struct stat path_stat; + + if (stat(path, &path_stat) != 0) { + return NULL; + } + + if (!S_ISREG(path_stat.st_mode)) { + return NULL; + } + + return GRN_STRDUP(path); +} + +#ifdef GRN_WITH_MRUBY +static char * +grn_plugin_find_path_mrb(grn_ctx *ctx, const char *path, size_t path_len) +{ + char mrb_path[PATH_MAX]; + const char *mrb_suffix; + size_t mrb_path_len; + + grn_ctx_impl_mrb_ensure_init(ctx); + if (ctx->rc != GRN_SUCCESS) { + return NULL; + } + + if (!ctx->impl->mrb.state) { + return NULL; + } + + mrb_suffix = grn_plugin_get_ruby_suffix(); + mrb_path_len = path_len + strlen(mrb_suffix); + if (mrb_path_len >= PATH_MAX) { + ERR(GRN_FILENAME_TOO_LONG, + "too long plugin path: <%s%s>", + path, mrb_suffix); + return NULL; + } + + grn_strcpy(mrb_path, PATH_MAX, path); + grn_strcat(mrb_path, PATH_MAX, mrb_suffix); + return grn_plugin_find_path_raw(ctx, mrb_path); +} +#else /* GRN_WITH_MRUBY */ +static char * +grn_plugin_find_path_mrb(grn_ctx *ctx, const char *path, size_t path_len) +{ + return NULL; +} +#endif /* GRN_WITH_MRUBY */ + +static char * +grn_plugin_find_path_so(grn_ctx *ctx, const char *path, size_t path_len) +{ + char so_path[PATH_MAX]; + const char *so_suffix; + size_t so_path_len; + + so_suffix = grn_plugin_get_suffix(); + so_path_len = path_len + strlen(so_suffix); + if (so_path_len >= PATH_MAX) { + ERR(GRN_FILENAME_TOO_LONG, + "too long plugin path: <%s%s>", + path, so_suffix); + return NULL; + } + + grn_strcpy(so_path, PATH_MAX, path); + grn_strcat(so_path, PATH_MAX, so_suffix); + return grn_plugin_find_path_raw(ctx, so_path); +} + +static char * +grn_plugin_find_path_libs_so(grn_ctx *ctx, const char *path, size_t path_len) +{ + char libs_so_path[PATH_MAX]; + const char *base_name; + const char *so_suffix; + const char *libs_path = "/.libs"; + size_t libs_so_path_len; + + base_name = strrchr(path, '/'); + if (!base_name) { + return NULL; + } + + so_suffix = grn_plugin_get_suffix(); + libs_so_path_len = + base_name - path + + strlen(libs_path) + + strlen(base_name) + + strlen(so_suffix); + if (libs_so_path_len >= PATH_MAX) { + ERR(GRN_FILENAME_TOO_LONG, + "too long plugin path: <%.*s/.libs%s%s>", + (int)(base_name - path), path, base_name, so_suffix); + return NULL; + } + + libs_so_path[0] = '\0'; + grn_strncat(libs_so_path, PATH_MAX, path, base_name - path); + grn_strcat(libs_so_path, PATH_MAX, libs_path); + grn_strcat(libs_so_path, PATH_MAX, base_name); + grn_strcat(libs_so_path, PATH_MAX, so_suffix); + return grn_plugin_find_path_raw(ctx, libs_so_path); +} + +char * +grn_plugin_find_path(grn_ctx *ctx, const char *name) +{ + const char *plugins_dir; + char dir_last_char; + char path[PATH_MAX]; + int name_length, max_name_length; + char *found_path = NULL; + size_t path_len; + + GRN_API_ENTER; + if (name[0] == '/') { + path[0] = '\0'; + } else { + plugins_dir = grn_plugin_get_system_plugins_dir(); + grn_strcpy(path, PATH_MAX, plugins_dir); + + dir_last_char = plugins_dir[strlen(path) - 1]; + if (dir_last_char != '/') { + grn_strcat(path, PATH_MAX, "/"); + } + } + + name_length = strlen(name); + max_name_length = PATH_MAX - strlen(path) - 1; + if (name_length > max_name_length) { + ERR(GRN_INVALID_ARGUMENT, + "plugin name is too long: %d (max: %d) <%s%s>", + name_length, max_name_length, + path, name); + goto exit; + } + grn_strcat(path, PATH_MAX, name); + + found_path = grn_plugin_find_path_raw(ctx, path); + if (found_path) { + goto exit; + } + + path_len = strlen(path); + + found_path = grn_plugin_find_path_so(ctx, path, path_len); + if (found_path) { + goto exit; + } + if (ctx->rc) { + goto exit; + } + + found_path = grn_plugin_find_path_libs_so(ctx, path, path_len); + if (found_path) { + goto exit; + } + if (ctx->rc) { + goto exit; + } + + found_path = grn_plugin_find_path_mrb(ctx, path, path_len); + if (found_path) { + goto exit; + } + if (ctx->rc) { + goto exit; + } + +exit : + GRN_API_RETURN(found_path); +} + +static void +grn_plugin_set_name_resolve_error(grn_ctx *ctx, const char *name, + const char *tag) +{ + const char *prefix, *prefix_separator, *suffix; + + if (name[0] == '/') { + prefix = ""; + prefix_separator = ""; + suffix = ""; + } else { + prefix = grn_plugin_get_system_plugins_dir(); + if (prefix[strlen(prefix) - 1] != '/') { + prefix_separator = "/"; + } else { + prefix_separator = ""; + } + suffix = grn_plugin_get_suffix(); + } + ERR(GRN_NO_SUCH_FILE_OR_DIRECTORY, + "%s cannot find plugin file: <%s%s%s%s>", + tag, prefix, prefix_separator, name, suffix); +} + +grn_rc +grn_plugin_register(grn_ctx *ctx, const char *name) +{ + grn_rc rc; + char *path; + + GRN_API_ENTER; + path = grn_plugin_find_path(ctx, name); + if (path) { + rc = grn_plugin_register_by_path(ctx, path); + GRN_FREE(path); + } else { + if (ctx->rc == GRN_SUCCESS) { + grn_plugin_set_name_resolve_error(ctx, name, "[plugin][register]"); + } + rc = ctx->rc; + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_plugin_unregister_by_path(grn_ctx *ctx, const char *path) +{ + grn_obj *db; + grn_id plugin_id; + + if (!ctx || !ctx->impl) { + ERR(GRN_INVALID_ARGUMENT, "[plugin][unregister] ctx isn't initialized"); + return ctx->rc; + } + + db = ctx->impl->db; + if (!db) { + ERR(GRN_INVALID_ARGUMENT, "[plugin][unregister] DB isn't initialized"); + return ctx->rc; + } + + GRN_API_ENTER; + + CRITICAL_SECTION_ENTER(grn_plugins_lock); + plugin_id = grn_hash_get(&grn_plugins_ctx, grn_plugins, + path, GRN_PLUGIN_KEY_SIZE(path), + NULL); + CRITICAL_SECTION_LEAVE(grn_plugins_lock); + + if (plugin_id == GRN_ID_NIL) { + GRN_API_RETURN(ctx->rc); + } + + { + grn_table_cursor *cursor; + grn_id id; + + cursor = grn_table_cursor_open(ctx, db, + NULL, 0, + NULL, 0, + 0, -1, GRN_CURSOR_BY_ID); + if (!cursor) { + GRN_API_RETURN(ctx->rc); + } + + while ((id = grn_table_cursor_next(ctx, cursor))) { + grn_obj *obj; + obj = grn_ctx_at(ctx, id); + if (!obj) { + continue; + } + if (obj->header.type == GRN_PROC && DB_OBJ(obj)->range == plugin_id) { + grn_obj_remove(ctx, obj); + } else { + grn_obj_unlink(ctx, obj); + } + } + grn_table_cursor_close(ctx, cursor); + } + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_plugin_unregister(grn_ctx *ctx, const char *name) +{ + grn_rc rc; + char *path; + + GRN_API_ENTER; + path = grn_plugin_find_path(ctx, name); + if (path) { + rc = grn_plugin_unregister_by_path(ctx, path); + GRN_FREE(path); + } else { + if (ctx->rc == GRN_SUCCESS) { + grn_plugin_set_name_resolve_error(ctx, name, "[plugin][unregister]"); + } + rc = ctx->rc; + } + GRN_API_RETURN(rc); +} + +void +grn_plugin_ensure_registered(grn_ctx *ctx, grn_obj *proc) +{ +#ifdef GRN_WITH_MRUBY + grn_id plugin_id; + grn_plugin *plugin = NULL; + + if (!(proc->header.flags & GRN_OBJ_CUSTOM_NAME)) { + return; + } + + plugin_id = DB_OBJ(proc)->range; + CRITICAL_SECTION_ENTER(grn_plugins_lock); + { + const char *value; + value = grn_hash_get_value_(&grn_plugins_ctx, grn_plugins, plugin_id, NULL); + if (value) { + plugin = *((grn_plugin **)value); + } + } + CRITICAL_SECTION_LEAVE(grn_plugins_lock); + + if (!plugin) { + return; + } + + if (plugin->dl) { + return; + } + + grn_ctx_impl_mrb_ensure_init(ctx); + if (ctx->rc != GRN_SUCCESS) { + return; + } + + if (!ctx->impl->mrb.state) { + return; + } + + { + grn_id id; + int added; + id = DB_OBJ(proc)->id; + grn_hash_add(ctx, ctx->impl->mrb.checked_procs, + &id, sizeof(grn_id), NULL, &added); + if (!added) { + return; + } + } + + ctx->impl->plugin_path = plugin->path; + grn_plugin_call_register_mrb(ctx, plugin_id, plugin); + ctx->impl->plugin_path = NULL; +#endif /* GRN_WITH_MRUBY */ +} + +grn_rc +grn_plugin_get_names(grn_ctx *ctx, grn_obj *names) +{ + grn_hash *processed_paths; + const char *system_plugins_dir; + const char *native_plugin_suffix; + const char *ruby_plugin_suffix; + grn_bool is_close_opened_object_mode = GRN_FALSE; + + GRN_API_ENTER; + + if (ctx->rc) { + GRN_API_RETURN(ctx->rc); + } + + if (grn_thread_get_limit() == 1) { + is_close_opened_object_mode = GRN_TRUE; + } + + processed_paths = grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, 0, + GRN_OBJ_TABLE_HASH_KEY | + GRN_OBJ_KEY_VAR_SIZE); + if (!processed_paths) { + GRN_API_RETURN(ctx->rc); + } + + system_plugins_dir = grn_plugin_get_system_plugins_dir(); + native_plugin_suffix = grn_plugin_get_suffix(); + ruby_plugin_suffix = grn_plugin_get_ruby_suffix(); + + GRN_TABLE_EACH_BEGIN_FLAGS(ctx, grn_ctx_db(ctx), cursor, id, + GRN_CURSOR_BY_ID | GRN_CURSOR_ASCENDING) { + void *name; + int name_size; + grn_obj *object; + const char *path; + grn_id processed_path_id; + + if (grn_id_is_builtin(ctx, id)) { + continue; + } + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + object = grn_ctx_at(ctx, id); + if (!object) { + ERRCLR(ctx); + goto next_loop; + } + + if (!grn_obj_is_proc(ctx, object)) { + goto next_loop; + } + + path = grn_obj_path(ctx, object); + if (!path) { + goto next_loop; + } + + processed_path_id = grn_hash_get(ctx, processed_paths, + path, strlen(path), + NULL); + if (processed_path_id != GRN_ID_NIL) { + goto next_loop; + } + + grn_hash_add(ctx, processed_paths, + path, strlen(path), + NULL, NULL); + + { + const char *relative_path; + const char *libs_path = "/.libs/"; + const char *start_libs; + char name[PATH_MAX]; + + name[0] = '\0'; + if (strncmp(path, system_plugins_dir, strlen(system_plugins_dir)) == 0) { + relative_path = path + strlen(system_plugins_dir); + } else { + relative_path = path; + } + start_libs = strstr(relative_path, libs_path); + if (start_libs) { + grn_strncat(name, PATH_MAX, relative_path, start_libs - relative_path); + grn_strcat(name, PATH_MAX, "/"); + grn_strcat(name, PATH_MAX, start_libs + strlen(libs_path)); + } else { + grn_strcat(name, PATH_MAX, relative_path); + } + if (strlen(name) > strlen(native_plugin_suffix) && + strcmp(name + strlen(name) - strlen(native_plugin_suffix), + native_plugin_suffix) == 0) { + name[strlen(name) - strlen(native_plugin_suffix)] = '\0'; + } else if (strlen(name) > strlen(ruby_plugin_suffix) && + strcmp(name + strlen(name) - strlen(ruby_plugin_suffix), + ruby_plugin_suffix) == 0) { + name[strlen(name) - strlen(ruby_plugin_suffix)] = '\0'; + } + grn_vector_add_element(ctx, names, + name, strlen(name), + 0, GRN_DB_TEXT); + } + + next_loop : + if (is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_TABLE_EACH_END(ctx, cursor); + + grn_hash_close(ctx, processed_paths); + + GRN_API_RETURN(ctx->rc); +} + +void * +grn_plugin_malloc(grn_ctx *ctx, size_t size, const char *file, int line, + const char *func) +{ + return grn_malloc(ctx, size, file, line, func); +} + +void * +grn_plugin_calloc(grn_ctx *ctx, size_t size, const char *file, int line, + const char *func) +{ + return grn_calloc(ctx, size, file, line, func); +} + +void * +grn_plugin_realloc(grn_ctx *ctx, void *ptr, size_t size, + const char *file, int line, const char *func) +{ + return grn_realloc(ctx, ptr, size, file, line, func); +} + +void +grn_plugin_free(grn_ctx *ctx, void *ptr, const char *file, int line, + const char *func) +{ + grn_free(ctx, ptr, file, line, func); +} + +void +grn_plugin_set_error(grn_ctx *ctx, grn_log_level level, grn_rc error_code, + const char *file, int line, const char *func, + const char *format, ...) +{ + char old_error_message[GRN_CTX_MSGSIZE]; + + ctx->errlvl = level; + ctx->rc = error_code; + ctx->errfile = file; + ctx->errline = line; + ctx->errfunc = func; + + grn_strcpy(old_error_message, GRN_CTX_MSGSIZE, ctx->errbuf); + + { + va_list ap; + va_start(ap, format); + grn_ctx_logv(ctx, format, ap); + va_end(ap); + } + + if (grn_ctx_impl_should_log(ctx)) { + grn_ctx_impl_set_current_error_message(ctx); + if (grn_logger_pass(ctx, level)) { + char new_error_message[GRN_CTX_MSGSIZE]; + grn_strcpy(new_error_message, GRN_CTX_MSGSIZE, ctx->errbuf); + grn_strcpy(ctx->errbuf, GRN_CTX_MSGSIZE, old_error_message); + { + va_list ap; + va_start(ap, format); + grn_logger_putv(ctx, level, file, line, func, format, ap); + va_end(ap); + } + grn_strcpy(ctx->errbuf, GRN_CTX_MSGSIZE, new_error_message); + } + if (level <= GRN_LOG_ERROR) { + grn_plugin_logtrace(ctx, level); + } + } +} + +void +grn_plugin_clear_error(grn_ctx *ctx) +{ + ERRCLR(ctx); +} + +void +grn_plugin_backtrace(grn_ctx *ctx) +{ + BACKTRACE(ctx); +} + +void +grn_plugin_logtrace(grn_ctx *ctx, grn_log_level level) +{ + if (level <= GRN_LOG_ERROR) { + grn_plugin_backtrace(ctx); + LOGTRACE(ctx, level); + } +} + +struct _grn_plugin_mutex { + grn_critical_section critical_section; +}; + +grn_plugin_mutex * +grn_plugin_mutex_open(grn_ctx *ctx) +{ + grn_plugin_mutex * const mutex = + GRN_PLUGIN_MALLOC(ctx, sizeof(grn_plugin_mutex)); + if (mutex != NULL) { + CRITICAL_SECTION_INIT(mutex->critical_section); + } + return mutex; +} + +grn_plugin_mutex * +grn_plugin_mutex_create(grn_ctx *ctx) +{ + return grn_plugin_mutex_open(ctx); +} + +void +grn_plugin_mutex_close(grn_ctx *ctx, grn_plugin_mutex *mutex) +{ + if (mutex != NULL) { + CRITICAL_SECTION_FIN(mutex->critical_section); + GRN_PLUGIN_FREE(ctx, mutex); + } +} + +void +grn_plugin_mutex_destroy(grn_ctx *ctx, grn_plugin_mutex *mutex) +{ + grn_plugin_mutex_close(ctx, mutex); +} + +void +grn_plugin_mutex_lock(grn_ctx *ctx, grn_plugin_mutex *mutex) +{ + if (mutex != NULL) { + CRITICAL_SECTION_ENTER(mutex->critical_section); + } +} + +void +grn_plugin_mutex_unlock(grn_ctx *ctx, grn_plugin_mutex *mutex) +{ + if (mutex != NULL) { + CRITICAL_SECTION_LEAVE(mutex->critical_section); + } +} + +grn_obj * +grn_plugin_proc_alloc(grn_ctx *ctx, grn_user_data *user_data, + grn_id domain, unsigned char flags) +{ + return grn_proc_alloc(ctx, user_data, domain, flags); +} + +grn_obj * +grn_plugin_proc_get_vars(grn_ctx *ctx, grn_user_data *user_data) +{ + return grn_proc_get_vars(ctx, user_data); +} + +grn_obj * +grn_plugin_proc_get_var(grn_ctx *ctx, grn_user_data *user_data, + const char *name, int name_size) +{ + name_size = compute_name_size(name, name_size); + return grn_proc_get_var(ctx, user_data, name, name_size); +} + +grn_bool +grn_plugin_proc_get_var_bool(grn_ctx *ctx, + grn_user_data *user_data, + const char *name, + int name_size, + grn_bool default_value) +{ + grn_obj *var; + + var = grn_plugin_proc_get_var(ctx, user_data, name, name_size); + return grn_proc_option_value_bool(ctx, var, default_value); +} + +int32_t +grn_plugin_proc_get_var_int32(grn_ctx *ctx, + grn_user_data *user_data, + const char *name, + int name_size, + int32_t default_value) +{ + grn_obj *var; + + var = grn_plugin_proc_get_var(ctx, user_data, name, name_size); + return grn_proc_option_value_int32(ctx, var, default_value); +} + +const char * +grn_plugin_proc_get_var_string(grn_ctx *ctx, + grn_user_data *user_data, + const char *name, + int name_size, + size_t *size) +{ + grn_obj *var; + + var = grn_plugin_proc_get_var(ctx, user_data, name, name_size); + return grn_proc_option_value_string(ctx, var, size); +} + +grn_content_type +grn_plugin_proc_get_var_content_type(grn_ctx *ctx, + grn_user_data *user_data, + const char *name, + int name_size, + grn_content_type default_value) +{ + grn_obj *var; + + var = grn_plugin_proc_get_var(ctx, user_data, name, name_size); + return grn_proc_option_value_content_type(ctx, var, default_value); +} + +grn_obj * +grn_plugin_proc_get_var_by_offset(grn_ctx *ctx, grn_user_data *user_data, + unsigned int offset) +{ + return grn_proc_get_var_by_offset(ctx, user_data, offset); +} + +grn_obj * +grn_plugin_proc_get_caller(grn_ctx *ctx, grn_user_data *user_data) +{ + grn_obj *caller = NULL; + GRN_API_ENTER; + grn_proc_get_info(ctx, user_data, NULL, NULL, &caller); + GRN_API_RETURN(caller); +} + +const char * +grn_plugin_win32_base_dir(void) +{ + return grn_plugin_windows_base_dir(); +} + +const char * +grn_plugin_windows_base_dir(void) +{ +#ifdef WIN32 + return grn_windows_base_dir(); +#else /* WIN32 */ + return NULL; +#endif /* WIN32 */ +} + +/* + grn_plugin_charlen() takes the length of a string, unlike grn_charlen_(). + */ +int +grn_plugin_charlen(grn_ctx *ctx, const char *str_ptr, + unsigned int str_length, grn_encoding encoding) +{ + return grn_charlen_(ctx, str_ptr, str_ptr + str_length, encoding); +} + +/* + grn_plugin_isspace() takes the length of a string, unlike grn_isspace(). + */ +int +grn_plugin_isspace(grn_ctx *ctx, const char *str_ptr, + unsigned int str_length, grn_encoding encoding) +{ + if ((str_ptr == NULL) || (str_length == 0)) { + return 0; + } + switch ((unsigned char)str_ptr[0]) { + case ' ' : + case '\f' : + case '\n' : + case '\r' : + case '\t' : + case '\v' : + return 1; + case 0x81 : + if ((encoding == GRN_ENC_SJIS) && (str_length >= 2) && + ((unsigned char)str_ptr[1] == 0x40)) { + return 2; + } + break; + case 0xA1 : + if ((encoding == GRN_ENC_EUC_JP) && (str_length >= 2) && + ((unsigned char)str_ptr[1] == 0xA1)) { + return 2; + } + break; + case 0xE3 : + if ((encoding == GRN_ENC_UTF8) && (str_length >= 3) && + ((unsigned char)str_ptr[1] == 0x80) && + ((unsigned char)str_ptr[2] == 0x80)) { + return 3; + } + break; + default : + break; + } + return 0; +} + +grn_rc +grn_plugin_expr_var_init(grn_ctx *ctx, + grn_expr_var *var, + const char *name, + int name_size) +{ + var->name = name; + var->name_size = compute_name_size(name, name_size); + GRN_TEXT_INIT(&var->value, 0); + return GRN_SUCCESS; +} + +grn_obj * +grn_plugin_command_create(grn_ctx *ctx, + const char *name, + int name_size, + grn_proc_func func, + unsigned int n_vars, + grn_expr_var *vars) +{ + grn_obj *proc; + name_size = compute_name_size(name, name_size); + proc = grn_proc_create(ctx, name, name_size, GRN_PROC_COMMAND, + func, NULL, NULL, n_vars, vars); + return proc; +} diff --git a/storage/mroonga/vendor/groonga/lib/proc.c b/storage/mroonga/vendor/groonga/lib/proc.c new file mode 100644 index 00000000..8ed39961 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc.c @@ -0,0 +1,4211 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_proc.h" +#include "grn_ctx.h" +#include "grn_ii.h" +#include "grn_db.h" +#include "grn_util.h" +#include "grn_output.h" +#include "grn_pat.h" +#include "grn_geo.h" +#include "grn_expr.h" +#include "grn_cache.h" +#include "grn_load.h" + +#include +#include +#include +#include + +#ifdef WIN32 +# include +# include +#endif /* WIN32 */ + +#ifndef O_NOFOLLOW +#define O_NOFOLLOW 0 +#endif + +/**** globals for procs ****/ +const char *grn_document_root = NULL; + +#define VAR GRN_PROC_GET_VAR_BY_OFFSET + +static double grn_between_too_many_index_match_ratio = 0.01; +static double grn_in_values_too_many_index_match_ratio = 0.01; + +void +grn_proc_init_from_env(void) +{ + { + char grn_between_too_many_index_match_ratio_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_BETWEEN_TOO_MANY_INDEX_MATCH_RATIO", + grn_between_too_many_index_match_ratio_env, + GRN_ENV_BUFFER_SIZE); + if (grn_between_too_many_index_match_ratio_env[0]) { + grn_between_too_many_index_match_ratio = + atof(grn_between_too_many_index_match_ratio_env); + } + } + + { + char grn_in_values_too_many_index_match_ratio_env[GRN_ENV_BUFFER_SIZE]; + grn_getenv("GRN_IN_VALUES_TOO_MANY_INDEX_MATCH_RATIO", + grn_in_values_too_many_index_match_ratio_env, + GRN_ENV_BUFFER_SIZE); + if (grn_in_values_too_many_index_match_ratio_env[0]) { + grn_in_values_too_many_index_match_ratio = + atof(grn_in_values_too_many_index_match_ratio_env); + } + } +} + +/* bulk must be initialized grn_bulk or grn_msg */ +static int +grn_bulk_put_from_file(grn_ctx *ctx, grn_obj *bulk, const char *path) +{ + /* FIXME: implement more smartly with grn_bulk */ + int fd, ret = 0; + struct stat stat; + grn_open(fd, path, O_RDONLY|O_NOFOLLOW|GRN_OPEN_FLAG_BINARY); + if (fd == -1) { + switch (errno) { + case EACCES : + ERR(GRN_OPERATION_NOT_PERMITTED, "request is not allowed: <%s>", path); + break; + case ENOENT : + ERR(GRN_NO_SUCH_FILE_OR_DIRECTORY, "no such file: <%s>", path); + break; +#ifndef WIN32 + case ELOOP : + ERR(GRN_NO_SUCH_FILE_OR_DIRECTORY, + "symbolic link is not allowed: <%s>", path); + break; +#endif /* WIN32 */ + default : + ERRNO_ERR("failed to open file: <%s>", path); + break; + } + return 0; + } + if (fstat(fd, &stat) != -1) { + char *buf, *bp; + off_t rest = stat.st_size; + if ((buf = GRN_MALLOC(rest))) { + ssize_t ss; + for (bp = buf; rest; rest -= ss, bp += ss) { + if ((ss = grn_read(fd, bp, rest)) == -1) { goto exit; } + } + GRN_TEXT_PUT(ctx, bulk, buf, stat.st_size); + ret = 1; + } + GRN_FREE(buf); + } else { + ERR(GRN_INVALID_ARGUMENT, "cannot stat file: <%s>", path); + } +exit : + grn_close(fd); + return ret; +} + +#ifdef stat +# undef stat +#endif /* stat */ + +/**** procs ****/ + +static grn_obj * +proc_load(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_load_input input; + + input.type = grn_plugin_proc_get_var_content_type(ctx, + user_data, + "input_type", + -1, + GRN_CONTENT_JSON); +#define INIT_STRING_ARGUMENT(member_name, arg_name) \ + input.member_name.value = \ + grn_plugin_proc_get_var_string(ctx, \ + user_data, \ + arg_name, \ + -1, \ + &(input.member_name.length)) + + INIT_STRING_ARGUMENT(table, "table"); + INIT_STRING_ARGUMENT(columns, "columns"); + INIT_STRING_ARGUMENT(values, "values"); + INIT_STRING_ARGUMENT(if_exists, "ifexists"); + INIT_STRING_ARGUMENT(each, "each"); + +#undef INIT_STRING_ARGUMENT + + input.output_ids = grn_plugin_proc_get_var_bool(ctx, + user_data, + "output_ids", -1, + GRN_FALSE); + input.output_errors = grn_plugin_proc_get_var_bool(ctx, + user_data, + "output_errors", -1, + GRN_FALSE); + input.emit_level = 1; + + grn_load_internal(ctx, &input); + if (ctx->rc == GRN_CANCEL) { + ctx->impl->loader.stat = GRN_LOADER_END; + ctx->impl->loader.rc = GRN_SUCCESS; + } + if (ctx->impl->loader.stat != GRN_LOADER_END && + !(ctx->impl->command.flags & GRN_CTX_TAIL)) { + grn_obj *command = grn_proc_get_info(ctx, user_data, NULL, NULL, NULL); + grn_ctx_set_keep_command(ctx, command); + } else { + if (ctx->impl->loader.rc != GRN_SUCCESS) { + ctx->rc = ctx->impl->loader.rc; + grn_strcpy(ctx->errbuf, GRN_CTX_MSGSIZE, ctx->impl->loader.errbuf); + } + if (grn_ctx_get_command_version(ctx) >= GRN_COMMAND_VERSION_3) { + int n_elements = 1; + if (ctx->impl->loader.output_ids) { + n_elements++; + } + if (ctx->impl->loader.output_errors) { + n_elements++; + } + GRN_OUTPUT_MAP_OPEN("result", n_elements); + GRN_OUTPUT_CSTR("n_loaded_records"); + GRN_OUTPUT_INT64(ctx->impl->loader.nrecords); + if (ctx->impl->loader.output_ids) { + grn_obj *ids = &(ctx->impl->loader.ids); + int i, n_ids; + + GRN_OUTPUT_CSTR("loaded_ids"); + n_ids = GRN_BULK_VSIZE(ids) / sizeof(uint32_t); + GRN_OUTPUT_ARRAY_OPEN("loaded_ids", n_ids); + for (i = 0; i < n_ids; i++) { + GRN_OUTPUT_UINT64(GRN_UINT32_VALUE_AT(ids, i)); + } + GRN_OUTPUT_ARRAY_CLOSE(); + } + if (ctx->impl->loader.output_errors) { + grn_obj *return_codes = &(ctx->impl->loader.return_codes); + grn_obj *error_messages = &(ctx->impl->loader.error_messages); + int i, n; + + GRN_OUTPUT_CSTR("errors"); + n = GRN_BULK_VSIZE(return_codes) / sizeof(int32_t); + GRN_OUTPUT_ARRAY_OPEN("errors", n); + for (i = 0; i < n; i++) { + const char *message; + unsigned int message_size; + + message_size = grn_vector_get_element(ctx, + error_messages, + i, + &message, + NULL, + NULL); + + GRN_OUTPUT_MAP_OPEN("error", 2); + GRN_OUTPUT_CSTR("return_code"); + GRN_OUTPUT_INT64(GRN_INT32_VALUE_AT(return_codes, i)); + GRN_OUTPUT_CSTR("message"); + if (message_size == 0) { + GRN_OUTPUT_NULL(); + } else { + GRN_OUTPUT_STR(message, message_size); + } + GRN_OUTPUT_MAP_CLOSE(); + } + GRN_OUTPUT_ARRAY_CLOSE(); + } + GRN_OUTPUT_MAP_CLOSE(); + } else { + GRN_OUTPUT_INT64(ctx->impl->loader.nrecords); + } + if (ctx->impl->loader.table) { + grn_db_touch(ctx, DB_OBJ(ctx->impl->loader.table)->db); + } + grn_ctx_loader_clear(ctx); + } + return NULL; +} + +static grn_obj * +proc_status(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_timeval now; + grn_cache *cache; + grn_cache_statistics statistics; + + grn_timeval_now(ctx, &now); + cache = grn_cache_current_get(ctx); + grn_cache_get_statistics(ctx, cache, &statistics); + GRN_OUTPUT_MAP_OPEN("RESULT", 10); + GRN_OUTPUT_CSTR("alloc_count"); + GRN_OUTPUT_INT32(grn_alloc_count()); + GRN_OUTPUT_CSTR("starttime"); + GRN_OUTPUT_INT32(grn_starttime.tv_sec); + GRN_OUTPUT_CSTR("start_time"); + GRN_OUTPUT_INT32(grn_starttime.tv_sec); + GRN_OUTPUT_CSTR("uptime"); + GRN_OUTPUT_INT32(now.tv_sec - grn_starttime.tv_sec); + GRN_OUTPUT_CSTR("version"); + GRN_OUTPUT_CSTR(grn_get_version()); + GRN_OUTPUT_CSTR("n_queries"); + GRN_OUTPUT_INT64(statistics.nfetches); + GRN_OUTPUT_CSTR("cache_hit_rate"); + if (statistics.nfetches == 0) { + GRN_OUTPUT_FLOAT(0.0); + } else { + double cache_hit_rate; + cache_hit_rate = (double)statistics.nhits / (double)statistics.nfetches; + GRN_OUTPUT_FLOAT(cache_hit_rate * 100.0); + } + GRN_OUTPUT_CSTR("command_version"); + GRN_OUTPUT_INT32(grn_ctx_get_command_version(ctx)); + GRN_OUTPUT_CSTR("default_command_version"); + GRN_OUTPUT_INT32(grn_get_default_command_version()); + GRN_OUTPUT_CSTR("max_command_version"); + GRN_OUTPUT_INT32(GRN_COMMAND_VERSION_MAX); + GRN_OUTPUT_MAP_CLOSE(); + +#ifdef USE_MEMORY_DEBUG + grn_alloc_info_dump(&grn_gctx); +#endif /* USE_MEMORY_DEBUG */ + + return NULL; +} + +#define GRN_STRLEN(s) ((s) ? strlen(s) : 0) + +void +grn_proc_output_object_name(grn_ctx *ctx, grn_obj *obj) +{ + grn_obj bulk; + int name_len; + char name[GRN_TABLE_MAX_KEY_SIZE]; + + if (obj) { + GRN_TEXT_INIT(&bulk, GRN_OBJ_DO_SHALLOW_COPY); + name_len = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE); + GRN_TEXT_SET(ctx, &bulk, name, name_len); + } else { + GRN_VOID_INIT(&bulk); + } + + GRN_OUTPUT_OBJ(&bulk, NULL); + GRN_OBJ_FIN(ctx, &bulk); +} + +void +grn_proc_output_object_id_name(grn_ctx *ctx, grn_id id) +{ + grn_obj *obj = NULL; + + if (id != GRN_ID_NIL) { + obj = grn_ctx_at(ctx, id); + } + + grn_proc_output_object_name(ctx, obj); +} + +static grn_obj * +proc_missing(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + uint32_t plen; + grn_obj *outbuf = ctx->impl->output.buf; + static int grn_document_root_len = -1; + if (!grn_document_root) { return NULL; } + if (grn_document_root_len < 0) { + size_t l; + if ((l = strlen(grn_document_root)) > PATH_MAX) { + return NULL; + } + grn_document_root_len = (int)l; + if (l > 0 && grn_document_root[l - 1] == '/') { grn_document_root_len--; } + } + if ((plen = GRN_TEXT_LEN(VAR(0))) + grn_document_root_len < PATH_MAX) { + char path[PATH_MAX]; + grn_memcpy(path, grn_document_root, grn_document_root_len); + path[grn_document_root_len] = '/'; + grn_str_url_path_normalize(ctx, + GRN_TEXT_VALUE(VAR(0)), + GRN_TEXT_LEN(VAR(0)), + path + grn_document_root_len + 1, + PATH_MAX - grn_document_root_len - 1); + grn_bulk_put_from_file(ctx, outbuf, path); + } else { + uint32_t abbrlen = 32; + ERR(GRN_INVALID_ARGUMENT, + "too long path name: <%s/%.*s...> %u(%u)", + grn_document_root, + abbrlen < plen ? abbrlen : plen, GRN_TEXT_VALUE(VAR(0)), + plen + grn_document_root_len, PATH_MAX); + } + return NULL; +} + +static grn_obj * +proc_quit(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + ctx->stat = GRN_CTX_QUITTING; + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static grn_obj * +proc_shutdown(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + const char *mode; + size_t mode_size; + + mode = grn_plugin_proc_get_var_string(ctx, user_data, "mode", -1, &mode_size); +#define MODE_EQUAL(name) \ + (mode_size == strlen(name) && memcmp(mode, name, mode_size) == 0) + if (mode_size == 0 || MODE_EQUAL("graceful")) { + /* Do nothing. This is the default. */ + } else if (MODE_EQUAL("immediate")) { + grn_request_canceler_cancel_all(); + if (ctx->rc == GRN_INTERRUPTED_FUNCTION_CALL) { + ctx->rc = GRN_SUCCESS; + } + } else { + ERR(GRN_INVALID_ARGUMENT, + "[shutdown] mode must be or : <%.*s>", + (int)mode_size, mode); + } +#undef MODE_EQUAL + + if (ctx->rc == GRN_SUCCESS) { + grn_gctx.stat = GRN_CTX_QUIT; + ctx->stat = GRN_CTX_QUITTING; + } + + GRN_OUTPUT_BOOL(!ctx->rc); + + return NULL; +} + +static grn_obj * +proc_defrag(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *obj; + int olen, threshold; + olen = GRN_TEXT_LEN(VAR(0)); + + if (olen) { + obj = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)), olen); + } else { + obj = ctx->impl->db; + } + + threshold = GRN_TEXT_LEN(VAR(1)) + ? grn_atoi(GRN_TEXT_VALUE(VAR(1)), GRN_BULK_CURR(VAR(1)), NULL) + : 0; + + if (obj) { + grn_obj_defrag(ctx, obj, threshold); + } else { + ERR(GRN_INVALID_ARGUMENT, "defrag object not found"); + } + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static grn_obj * +proc_log_level(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *level_name = VAR(0); + if (GRN_TEXT_LEN(level_name) > 0) { + grn_log_level max_level; + GRN_TEXT_PUTC(ctx, level_name, '\0'); + if (grn_log_level_parse(GRN_TEXT_VALUE(level_name), &max_level)) { + grn_logger_set_max_level(ctx, max_level); + } else { + ERR(GRN_INVALID_ARGUMENT, + "invalid log level: <%s>", GRN_TEXT_VALUE(level_name)); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "log level is missing"); + } + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static grn_obj * +proc_log_put(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *level_name = VAR(0); + grn_obj *message = VAR(1); + if (GRN_TEXT_LEN(level_name) > 0) { + grn_log_level level; + GRN_TEXT_PUTC(ctx, level_name, '\0'); + if (grn_log_level_parse(GRN_TEXT_VALUE(level_name), &level)) { + GRN_LOG(ctx, level, "%.*s", + (int)GRN_TEXT_LEN(message), + GRN_TEXT_VALUE(message)); + } else { + ERR(GRN_INVALID_ARGUMENT, + "invalid log level: <%s>", GRN_TEXT_VALUE(level_name)); + } + } else { + ERR(GRN_INVALID_ARGUMENT, "log level is missing"); + } + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static grn_obj * +proc_log_reopen(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_log_reopen(ctx); + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static grn_rc +proc_delete_validate_selector(grn_ctx *ctx, grn_obj *table, grn_obj *table_name, + grn_obj *key, grn_obj *id, grn_obj *filter) +{ + grn_rc rc = GRN_SUCCESS; + + if (!table) { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, + "[table][record][delete] table doesn't exist: <%.*s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name)); + return rc; + } + + if (GRN_TEXT_LEN(key) == 0 && + GRN_TEXT_LEN(id) == 0 && + GRN_TEXT_LEN(filter) == 0) { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, + "[table][record][delete] either key, id or filter must be specified: " + "table: <%.*s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name)); + return rc; + } + + if (GRN_TEXT_LEN(key) && GRN_TEXT_LEN(id) && GRN_TEXT_LEN(filter)) { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, + "[table][record][delete] " + "record selector must be one of key, id and filter: " + "table: <%.*s>, key: <%.*s>, id: <%.*s>, filter: <%.*s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name), + (int)GRN_TEXT_LEN(key), GRN_TEXT_VALUE(key), + (int)GRN_TEXT_LEN(id), GRN_TEXT_VALUE(id), + (int)GRN_TEXT_LEN(filter), GRN_TEXT_VALUE(filter)); + return rc; + } + + if (GRN_TEXT_LEN(key) && GRN_TEXT_LEN(id) && GRN_TEXT_LEN(filter) == 0) { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, + "[table][record][delete] " + "can't use both key and id: table: <%.*s>, key: <%.*s>, id: <%.*s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name), + (int)GRN_TEXT_LEN(key), GRN_TEXT_VALUE(key), + (int)GRN_TEXT_LEN(id), GRN_TEXT_VALUE(id)); + return rc; + } + + if (GRN_TEXT_LEN(key) && GRN_TEXT_LEN(id) == 0 && GRN_TEXT_LEN(filter)) { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, + "[table][record][delete] " + "can't use both key and filter: " + "table: <%.*s>, key: <%.*s>, filter: <%.*s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name), + (int)GRN_TEXT_LEN(key), GRN_TEXT_VALUE(key), + (int)GRN_TEXT_LEN(filter), GRN_TEXT_VALUE(filter)); + return rc; + } + + if (GRN_TEXT_LEN(key) == 0 && GRN_TEXT_LEN(id) && GRN_TEXT_LEN(filter)) { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, + "[table][record][delete] " + "can't use both id and filter: " + "table: <%.*s>, id: <%.*s>, filter: <%.*s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name), + (int)GRN_TEXT_LEN(id), GRN_TEXT_VALUE(id), + (int)GRN_TEXT_LEN(filter), GRN_TEXT_VALUE(filter)); + return rc; + } + + return rc; +} + +static grn_obj * +proc_delete(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_rc rc = GRN_INVALID_ARGUMENT; + grn_obj *table_name = VAR(0); + grn_obj *key = VAR(1); + grn_obj *id = VAR(2); + grn_obj *filter = VAR(3); + grn_obj *table = NULL; + + if (GRN_TEXT_LEN(table_name) == 0) { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, "[table][record][delete] table name isn't specified"); + goto exit; + } + + table = grn_ctx_get(ctx, + GRN_TEXT_VALUE(table_name), + GRN_TEXT_LEN(table_name)); + rc = proc_delete_validate_selector(ctx, table, table_name, key, id, filter); + if (rc != GRN_SUCCESS) { goto exit; } + + if (GRN_TEXT_LEN(key)) { + grn_obj casted_key; + if (key->header.domain != table->header.domain) { + GRN_OBJ_INIT(&casted_key, GRN_BULK, 0, table->header.domain); + grn_obj_cast(ctx, key, &casted_key, GRN_FALSE); + key = &casted_key; + } + if (ctx->rc) { + rc = ctx->rc; + } else { + rc = grn_table_delete(ctx, table, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key)); + if (key == &casted_key) { + GRN_OBJ_FIN(ctx, &casted_key); + } + } + } else if (GRN_TEXT_LEN(id)) { + const char *end; + grn_id parsed_id = grn_atoui(GRN_TEXT_VALUE(id), GRN_BULK_CURR(id), &end); + if (end == GRN_BULK_CURR(id)) { + rc = grn_table_delete_by_id(ctx, table, parsed_id); + } else { + rc = GRN_INVALID_ARGUMENT; + ERR(rc, + "[table][record][delete] id should be number: " + "table: <%.*s>, id: <%.*s>, detail: <%.*s|%c|%.*s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name), + (int)GRN_TEXT_LEN(id), GRN_TEXT_VALUE(id), + (int)(end - GRN_TEXT_VALUE(id)), GRN_TEXT_VALUE(id), + end[0], + (int)(GRN_TEXT_VALUE(id) - end - 1), end + 1); + } + } else if (GRN_TEXT_LEN(filter)) { + grn_obj *cond, *v; + + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, cond, v); + grn_expr_parse(ctx, cond, + GRN_TEXT_VALUE(filter), + GRN_TEXT_LEN(filter), + NULL, GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc) { + rc = ctx->rc; + ERR(rc, + "[table][record][delete] failed to parse filter: " + "table: <%.*s>, filter: <%.*s>, detail: <%s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name), + (int)GRN_TEXT_LEN(filter), GRN_TEXT_VALUE(filter), + ctx->errbuf); + } else { + grn_obj *records; + + records = grn_table_select(ctx, table, cond, NULL, GRN_OP_OR); + if (records) { + GRN_TABLE_EACH_BEGIN(ctx, records, cursor, result_id) { + void *key; + grn_id id; + grn_rc sub_rc; + + if (grn_table_cursor_get_key(ctx, cursor, &key) == 0) { + continue; + } + + id = *(grn_id *)key; + sub_rc = grn_table_delete_by_id(ctx, table, id); + if (rc == GRN_SUCCESS) { + rc = sub_rc; + } + if (ctx->rc == GRN_CANCEL) { + break; + } + if (ctx->rc != GRN_SUCCESS) { + ERRCLR(ctx); + } + } GRN_TABLE_EACH_END(ctx, cursor); + grn_obj_unlink(ctx, records); + } + } + grn_obj_unlink(ctx, cond); + } + +exit : + if (table) { + grn_obj_unlink(ctx, table); + } + GRN_OUTPUT_BOOL(rc == GRN_SUCCESS); + return NULL; +} + +grn_bool +grn_proc_option_value_bool(grn_ctx *ctx, + grn_obj *option, + grn_bool default_value) +{ + const char *value; + size_t value_length; + + if (!option) { + return default_value; + } + + value = GRN_TEXT_VALUE(option); + value_length = GRN_TEXT_LEN(option); + + if (value_length == 0) { + return default_value; + } + + if (value_length == strlen("yes") && + strncmp(value, "yes", value_length) == 0) { + return GRN_TRUE; + } else if (value_length == strlen("no") && + strncmp(value, "no", value_length) == 0) { + return GRN_FALSE; + } else { + return default_value; + } +} + +int32_t +grn_proc_option_value_int32(grn_ctx *ctx, + grn_obj *option, + int32_t default_value) +{ + const char *value; + size_t value_length; + int32_t int32_value; + const char *rest; + + if (!option) { + return default_value; + } + + value = GRN_TEXT_VALUE(option); + value_length = GRN_TEXT_LEN(option); + + if (value_length == 0) { + return default_value; + } + + int32_value = grn_atoi(value, value + value_length, &rest); + if (rest == value + value_length) { + return int32_value; + } else { + return default_value; + } +} + +const char * +grn_proc_option_value_string(grn_ctx *ctx, + grn_obj *option, + size_t *size) +{ + const char *value; + size_t value_length; + + if (!option) { + if (size) { + *size = 0; + } + return NULL; + } + + value = GRN_TEXT_VALUE(option); + value_length = GRN_TEXT_LEN(option); + + if (size) { + *size = value_length; + } + + if (value_length == 0) { + return NULL; + } else { + return value; + } +} + +grn_content_type +grn_proc_option_value_content_type(grn_ctx *ctx, + grn_obj *option, + grn_content_type default_value) +{ + if (!option) { + return default_value; + } + + return grn_content_type_parse(ctx, option, default_value); +} + +static grn_obj * +proc_cache_limit(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_cache *cache; + unsigned int current_max_n_entries; + + cache = grn_cache_current_get(ctx); + current_max_n_entries = grn_cache_get_max_n_entries(ctx, cache); + if (GRN_TEXT_LEN(VAR(0))) { + const char *rest; + uint32_t max = grn_atoui(GRN_TEXT_VALUE(VAR(0)), + GRN_BULK_CURR(VAR(0)), &rest); + if (GRN_BULK_CURR(VAR(0)) == rest) { + grn_cache_set_max_n_entries(ctx, cache, max); + } else { + ERR(GRN_INVALID_ARGUMENT, + "max value is invalid unsigned integer format: <%.*s>", + (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0))); + } + } + if (ctx->rc == GRN_SUCCESS) { + GRN_OUTPUT_INT64(current_max_n_entries); + } + return NULL; +} + +static grn_obj * +proc_register(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + if (GRN_TEXT_LEN(VAR(0))) { + const char *name; + GRN_TEXT_PUTC(ctx, VAR(0), '\0'); + name = GRN_TEXT_VALUE(VAR(0)); + grn_plugin_register(ctx, name); + } else { + ERR(GRN_INVALID_ARGUMENT, "path is required"); + } + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +void grn_ii_buffer_check(grn_ctx *ctx, grn_ii *ii, uint32_t seg); + +static grn_obj * +proc_check(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *obj = grn_ctx_get(ctx, GRN_TEXT_VALUE(VAR(0)), GRN_TEXT_LEN(VAR(0))); + if (!obj) { + ERR(GRN_INVALID_ARGUMENT, + "no such object: <%.*s>", (int)GRN_TEXT_LEN(VAR(0)), GRN_TEXT_VALUE(VAR(0))); + GRN_OUTPUT_BOOL(!ctx->rc); + } else { + switch (obj->header.type) { + case GRN_DB : + GRN_OUTPUT_BOOL(!ctx->rc); + break; + case GRN_TABLE_PAT_KEY : + grn_pat_check(ctx, (grn_pat *)obj); + break; + case GRN_TABLE_HASH_KEY : + grn_hash_check(ctx, (grn_hash *)obj); + break; + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + case GRN_COLUMN_FIX_SIZE : + GRN_OUTPUT_BOOL(!ctx->rc); + break; + case GRN_COLUMN_VAR_SIZE : + grn_ja_check(ctx, (grn_ja *)obj); + break; + case GRN_COLUMN_INDEX : + { + grn_ii *ii = (grn_ii *)obj; + struct grn_ii_header *h = ii->header; + char buf[8]; + GRN_OUTPUT_ARRAY_OPEN("RESULT", 8); + { + uint32_t i, j, g =0, a = 0, b = 0; + uint32_t max = 0; + for (i = h->bgqtail; i != h->bgqhead; i = ((i + 1) & (GRN_II_BGQSIZE - 1))) { + j = h->bgqbody[i]; + g++; + if (j > max) { max = j; } + } + for (i = 0; i < GRN_II_MAX_LSEG; i++) { + j = h->binfo[i]; + if (j != GRN_II_PSEG_NOT_ASSIGNED) { + if (j > max) { max = j; } + b++; + } + } + for (i = 0; i < GRN_II_MAX_LSEG; i++) { + j = h->ainfo[i]; + if (j != GRN_II_PSEG_NOT_ASSIGNED) { + if (j > max) { max = j; } + a++; + } + } + GRN_OUTPUT_MAP_OPEN("SUMMARY", 12); + GRN_OUTPUT_CSTR("flags"); + grn_itoh(h->flags, buf, 8); + GRN_OUTPUT_STR(buf, 8); + GRN_OUTPUT_CSTR("max sid"); + GRN_OUTPUT_INT64(h->smax); + GRN_OUTPUT_CSTR("number of garbage segments"); + GRN_OUTPUT_INT64(g); + GRN_OUTPUT_CSTR("number of array segments"); + GRN_OUTPUT_INT64(a); + GRN_OUTPUT_CSTR("max id of array segment"); + GRN_OUTPUT_INT64(h->amax); + GRN_OUTPUT_CSTR("number of buffer segments"); + GRN_OUTPUT_INT64(b); + GRN_OUTPUT_CSTR("max id of buffer segment"); + GRN_OUTPUT_INT64(h->bmax); + GRN_OUTPUT_CSTR("max id of physical segment in use"); + GRN_OUTPUT_INT64(max); + GRN_OUTPUT_CSTR("number of unmanaged segments"); + GRN_OUTPUT_INT64(h->pnext - a - b - g); + GRN_OUTPUT_CSTR("total chunk size"); + GRN_OUTPUT_INT64(h->total_chunk_size); + for (max = 0, i = 0; i < (GRN_II_MAX_CHUNK >> 3); i++) { + if ((j = h->chunks[i])) { + int k; + for (k = 0; k < 8; k++) { + if ((j & (1 << k))) { max = (i << 3) + j; } + } + } + } + GRN_OUTPUT_CSTR("max id of chunk segments in use"); + GRN_OUTPUT_INT64(max); + GRN_OUTPUT_CSTR("number of garbage chunk"); + GRN_OUTPUT_ARRAY_OPEN("NGARBAGES", GRN_II_N_CHUNK_VARIATION); + for (i = 0; i <= GRN_II_N_CHUNK_VARIATION; i++) { + GRN_OUTPUT_INT64(h->ngarbages[i]); + } + GRN_OUTPUT_ARRAY_CLOSE(); + GRN_OUTPUT_MAP_CLOSE(); + for (i = 0; i < GRN_II_MAX_LSEG; i++) { + if (h->binfo[i] < 0x20000) { grn_ii_buffer_check(ctx, ii, i); } + } + } + GRN_OUTPUT_ARRAY_CLOSE(); + } + break; + } + } + return NULL; +} + +static grn_obj * +proc_truncate(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + const char *target_name; + int target_name_len; + + target_name_len = GRN_TEXT_LEN(VAR(0)); + if (target_name_len > 0) { + target_name = GRN_TEXT_VALUE(VAR(0)); + } else { + target_name_len = GRN_TEXT_LEN(VAR(1)); + if (target_name_len == 0) { + ERR(GRN_INVALID_ARGUMENT, "[truncate] table name is missing"); + goto exit; + } + target_name = GRN_TEXT_VALUE(VAR(1)); + } + + { + grn_obj *target = grn_ctx_get(ctx, target_name, target_name_len); + if (!target) { + ERR(GRN_INVALID_ARGUMENT, + "[truncate] no such target: <%.*s>", target_name_len, target_name); + goto exit; + } + + switch (target->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + grn_table_truncate(ctx, target); + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + grn_column_truncate(ctx, target); + break; + default: + { + grn_obj buffer; + GRN_TEXT_INIT(&buffer, 0); + grn_inspect(ctx, &buffer, target); + ERR(GRN_INVALID_ARGUMENT, + "[truncate] not a table nor column object: <%.*s>", + (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); + } + break; + } + } + +exit : + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static int +parse_normalize_flags(grn_ctx *ctx, grn_obj *flag_names) +{ + int flags = 0; + const char *names, *names_end; + int length; + + names = GRN_TEXT_VALUE(flag_names); + length = GRN_TEXT_LEN(flag_names); + names_end = names + length; + while (names < names_end) { + if (*names == '|' || *names == ' ') { + names += 1; + continue; + } + +#define CHECK_FLAG(name)\ + if (((unsigned long) (names_end - names) >= (unsigned long) (sizeof(#name) - 1)) && \ + (!memcmp(names, #name, sizeof(#name) - 1))) {\ + flags |= GRN_STRING_ ## name;\ + names += sizeof(#name) - 1;\ + continue;\ + } + + CHECK_FLAG(REMOVE_BLANK); + CHECK_FLAG(WITH_TYPES); + CHECK_FLAG(WITH_CHECKS); + CHECK_FLAG(REMOVE_TOKENIZED_DELIMITER); + +#define GRN_STRING_NONE 0 + CHECK_FLAG(NONE); +#undef GRN_STRING_NONE + + ERR(GRN_INVALID_ARGUMENT, "[normalize] invalid flag: <%.*s>", + (int)(names_end - names), names); + return 0; +#undef CHECK_FLAG + } + + return flags; +} + +static grn_bool +is_normalizer(grn_ctx *ctx, grn_obj *object) +{ + if (object->header.type != GRN_PROC) { + return GRN_FALSE; + } + + if (grn_proc_get_type(ctx, object) != GRN_PROC_NORMALIZER) { + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static const char * +char_type_name(grn_char_type type) +{ + const char *name = "unknown"; + +#define CHAR_TYPE_NAME_WITH_BLANK(type_name) do { \ + if (GRN_CHAR_IS_BLANK(type)) { \ + name = type_name "|blank"; \ + } else { \ + name = type_name; \ + } \ + } while (GRN_FALSE) + + switch (GRN_CHAR_TYPE(type)) { + case GRN_CHAR_NULL : + CHAR_TYPE_NAME_WITH_BLANK("null"); + break; + case GRN_CHAR_ALPHA : + CHAR_TYPE_NAME_WITH_BLANK("alpha"); + break; + case GRN_CHAR_DIGIT : + CHAR_TYPE_NAME_WITH_BLANK("digit"); + break; + case GRN_CHAR_SYMBOL : + CHAR_TYPE_NAME_WITH_BLANK("symbol"); + break; + case GRN_CHAR_HIRAGANA : + CHAR_TYPE_NAME_WITH_BLANK("hiragana"); + break; + case GRN_CHAR_KATAKANA : + CHAR_TYPE_NAME_WITH_BLANK("katakana"); + break; + case GRN_CHAR_KANJI : + CHAR_TYPE_NAME_WITH_BLANK("kanji"); + break; + case GRN_CHAR_OTHERS : + CHAR_TYPE_NAME_WITH_BLANK("others"); + break; + default : + CHAR_TYPE_NAME_WITH_BLANK("unknown"); + break; + } + +#undef CHAR_TYPE_NAME_WITH_BLANK + + return name; +} + +static grn_obj * +proc_normalize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *normalizer_name; + grn_obj *string; + grn_obj *flag_names; + + normalizer_name = VAR(0); + string = VAR(1); + flag_names = VAR(2); + if (GRN_TEXT_LEN(normalizer_name) == 0) { + ERR(GRN_INVALID_ARGUMENT, "normalizer name is missing"); + return NULL; + } + + { + grn_obj *normalizer; + grn_obj *grn_string; + int flags; + unsigned int normalized_length_in_bytes; + unsigned int normalized_n_characters; + + flags = parse_normalize_flags(ctx, flag_names); + normalizer = grn_ctx_get(ctx, + GRN_TEXT_VALUE(normalizer_name), + GRN_TEXT_LEN(normalizer_name)); + if (!normalizer) { + ERR(GRN_INVALID_ARGUMENT, + "[normalize] nonexistent normalizer: <%.*s>", + (int)GRN_TEXT_LEN(normalizer_name), + GRN_TEXT_VALUE(normalizer_name)); + return NULL; + } + + if (!is_normalizer(ctx, normalizer)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, normalizer); + ERR(GRN_INVALID_ARGUMENT, + "[normalize] not normalizer: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + grn_obj_unlink(ctx, normalizer); + return NULL; + } + + grn_string = grn_string_open(ctx, + GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string), + normalizer, flags); + grn_obj_unlink(ctx, normalizer); + + GRN_OUTPUT_MAP_OPEN("RESULT", 3); + { + const char *normalized; + + grn_string_get_normalized(ctx, grn_string, + &normalized, + &normalized_length_in_bytes, + &normalized_n_characters); + GRN_OUTPUT_CSTR("normalized"); + GRN_OUTPUT_STR(normalized, normalized_length_in_bytes); + } + { + const unsigned char *types; + + types = grn_string_get_types(ctx, grn_string); + GRN_OUTPUT_CSTR("types"); + if (types) { + unsigned int i; + GRN_OUTPUT_ARRAY_OPEN("types", normalized_n_characters); + for (i = 0; i < normalized_n_characters; i++) { + GRN_OUTPUT_CSTR(char_type_name(types[i])); + } + GRN_OUTPUT_ARRAY_CLOSE(); + } else { + GRN_OUTPUT_ARRAY_OPEN("types", 0); + GRN_OUTPUT_ARRAY_CLOSE(); + } + } + { + const short *checks; + + checks = grn_string_get_checks(ctx, grn_string); + GRN_OUTPUT_CSTR("checks"); + if (checks) { + unsigned int i; + GRN_OUTPUT_ARRAY_OPEN("checks", normalized_length_in_bytes); + for (i = 0; i < normalized_length_in_bytes; i++) { + GRN_OUTPUT_INT32(checks[i]); + } + GRN_OUTPUT_ARRAY_CLOSE(); + } else { + GRN_OUTPUT_ARRAY_OPEN("checks", 0); + GRN_OUTPUT_ARRAY_CLOSE(); + } + } + GRN_OUTPUT_MAP_CLOSE(); + + grn_obj_unlink(ctx, grn_string); + } + + return NULL; +} + +static void +list_proc(grn_ctx *ctx, grn_proc_type target_proc_type, + const char *name, const char *plural_name) +{ + grn_obj *db; + grn_table_cursor *cursor; + grn_obj target_procs; + + db = grn_ctx_db(ctx); + cursor = grn_table_cursor_open(ctx, db, NULL, 0, NULL, 0, 0, -1, + GRN_CURSOR_BY_ID); + if (!cursor) { + return; + } + + GRN_PTR_INIT(&target_procs, GRN_OBJ_VECTOR, GRN_ID_NIL); + { + grn_id id; + + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_obj *obj; + grn_proc_type proc_type; + + obj = grn_ctx_at(ctx, id); + if (!obj) { + continue; + } + + if (obj->header.type != GRN_PROC) { + grn_obj_unlink(ctx, obj); + continue; + } + + proc_type = grn_proc_get_type(ctx, obj); + if (proc_type != target_proc_type) { + grn_obj_unlink(ctx, obj); + continue; + } + + GRN_PTR_PUT(ctx, &target_procs, obj); + } + grn_table_cursor_close(ctx, cursor); + + { + int i, n_procs; + + n_procs = GRN_BULK_VSIZE(&target_procs) / sizeof(grn_obj *); + GRN_OUTPUT_ARRAY_OPEN(plural_name, n_procs); + for (i = 0; i < n_procs; i++) { + grn_obj *proc; + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + proc = GRN_PTR_VALUE_AT(&target_procs, i); + name_size = grn_obj_name(ctx, proc, name, GRN_TABLE_MAX_KEY_SIZE); + GRN_OUTPUT_MAP_OPEN(name, 1); + GRN_OUTPUT_CSTR("name"); + GRN_OUTPUT_STR(name, name_size); + GRN_OUTPUT_MAP_CLOSE(); + + grn_obj_unlink(ctx, proc); + } + GRN_OUTPUT_ARRAY_CLOSE(); + } + + grn_obj_unlink(ctx, &target_procs); + } +} + +static grn_obj * +proc_tokenizer_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + list_proc(ctx, GRN_PROC_TOKENIZER, "tokenizer", "tokenizers"); + return NULL; +} + +static grn_obj * +proc_normalizer_list(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + list_proc(ctx, GRN_PROC_NORMALIZER, "normalizer", "normalizers"); + return NULL; +} + +static grn_obj * +func_rand(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + int val; + grn_obj *obj; + if (nargs > 0) { + int max = GRN_INT32_VALUE(args[0]); + val = (int) (1.0 * max * rand() / (RAND_MAX + 1.0)); + } else { + val = rand(); + } + if ((obj = GRN_PROC_ALLOC(GRN_DB_INT32, 0))) { + GRN_INT32_SET(ctx, obj, val); + } + return obj; +} + +static grn_obj * +func_now(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *obj; + if ((obj = GRN_PROC_ALLOC(GRN_DB_TIME, 0))) { + GRN_TIME_NOW(ctx, obj); + } + return obj; +} + +static inline grn_bool +is_comparable_number_type(grn_id type) +{ + return GRN_DB_INT8 <= type && type <= GRN_DB_TIME; +} + +static inline grn_id +larger_number_type(grn_id type1, grn_id type2) +{ + if (type1 == type2) { + return type1; + } + + switch (type1) { + case GRN_DB_FLOAT : + return type1; + case GRN_DB_TIME : + if (type2 == GRN_DB_FLOAT) { + return type2; + } else { + return type1; + } + default : + if (type2 > type1) { + return type2; + } else { + return type1; + } + } +} + +static inline grn_id +smaller_number_type(grn_id type1, grn_id type2) +{ + if (type1 == type2) { + return type1; + } + + switch (type1) { + case GRN_DB_FLOAT : + return type1; + case GRN_DB_TIME : + if (type2 == GRN_DB_FLOAT) { + return type2; + } else { + return type1; + } + default : + { + grn_id smaller_number_type; + if (type2 > type1) { + smaller_number_type = type2; + } else { + smaller_number_type = type1; + } + switch (smaller_number_type) { + case GRN_DB_UINT8 : + return GRN_DB_INT8; + case GRN_DB_UINT16 : + return GRN_DB_INT16; + case GRN_DB_UINT32 : + return GRN_DB_INT32; + case GRN_DB_UINT64 : + return GRN_DB_INT64; + default : + return smaller_number_type; + } + } + } +} + +static inline grn_bool +is_negative_value(grn_obj *number) +{ + switch (number->header.domain) { + case GRN_DB_INT8 : + return GRN_INT8_VALUE(number) < 0; + case GRN_DB_INT16 : + return GRN_INT16_VALUE(number) < 0; + case GRN_DB_INT32 : + return GRN_INT32_VALUE(number) < 0; + case GRN_DB_INT64 : + return GRN_INT64_VALUE(number) < 0; + case GRN_DB_TIME : + return GRN_TIME_VALUE(number) < 0; + case GRN_DB_FLOAT : + return GRN_FLOAT_VALUE(number) < 0; + default : + return GRN_FALSE; + } +} + +static inline grn_bool +number_safe_cast(grn_ctx *ctx, grn_obj *src, grn_obj *dest, grn_id type) +{ + grn_obj_reinit(ctx, dest, type, 0); + if (src->header.domain == type) { + GRN_TEXT_SET(ctx, dest, GRN_TEXT_VALUE(src), GRN_TEXT_LEN(src)); + return GRN_TRUE; + } + + switch (type) { + case GRN_DB_UINT8 : + if (is_negative_value(src)) { + GRN_UINT8_SET(ctx, dest, 0); + return GRN_TRUE; + } + break; + case GRN_DB_UINT16 : + if (is_negative_value(src)) { + GRN_UINT16_SET(ctx, dest, 0); + return GRN_TRUE; + } + break; + case GRN_DB_UINT32 : + if (is_negative_value(src)) { + GRN_UINT32_SET(ctx, dest, 0); + return GRN_TRUE; + } + break; + case GRN_DB_UINT64 : + if (is_negative_value(src)) { + GRN_UINT64_SET(ctx, dest, 0); + return GRN_TRUE; + } + break; + } + return grn_obj_cast(ctx, src, dest, GRN_FALSE) == GRN_SUCCESS; +} + +static inline int +compare_number(grn_ctx *ctx, grn_obj *number1, grn_obj *number2, grn_id type) +{ +#define COMPARE_AND_RETURN(type, value1, value2)\ + {\ + type computed_value1 = value1;\ + type computed_value2 = value2;\ + if (computed_value1 > computed_value2) {\ + return 1;\ + } else if (computed_value1 < computed_value2) {\ + return -1;\ + } else {\ + return 0;\ + }\ + } + + switch (type) { + case GRN_DB_INT8 : + COMPARE_AND_RETURN(int8_t, + GRN_INT8_VALUE(number1), + GRN_INT8_VALUE(number2)); + case GRN_DB_UINT8 : + COMPARE_AND_RETURN(uint8_t, + GRN_UINT8_VALUE(number1), + GRN_UINT8_VALUE(number2)); + case GRN_DB_INT16 : + COMPARE_AND_RETURN(int16_t, + GRN_INT16_VALUE(number1), + GRN_INT16_VALUE(number2)); + case GRN_DB_UINT16 : + COMPARE_AND_RETURN(uint16_t, + GRN_UINT16_VALUE(number1), + GRN_UINT16_VALUE(number2)); + case GRN_DB_INT32 : + COMPARE_AND_RETURN(int32_t, + GRN_INT32_VALUE(number1), + GRN_INT32_VALUE(number2)); + case GRN_DB_UINT32 : + COMPARE_AND_RETURN(uint32_t, + GRN_UINT32_VALUE(number1), + GRN_UINT32_VALUE(number2)); + case GRN_DB_INT64 : + COMPARE_AND_RETURN(int64_t, + GRN_INT64_VALUE(number1), + GRN_INT64_VALUE(number2)); + case GRN_DB_UINT64 : + COMPARE_AND_RETURN(uint64_t, + GRN_UINT64_VALUE(number1), + GRN_UINT64_VALUE(number2)); + case GRN_DB_FLOAT : + COMPARE_AND_RETURN(double, + GRN_FLOAT_VALUE(number1), + GRN_FLOAT_VALUE(number2)); + case GRN_DB_TIME : + COMPARE_AND_RETURN(int64_t, + GRN_TIME_VALUE(number1), + GRN_TIME_VALUE(number2)); + default : + return 0; + } + +#undef COMPARE_AND_RETURN +} + +inline static void +get_number_in_grn_uvector(grn_ctx *ctx, grn_obj *uvector, unsigned int offset, + grn_obj *buf) +{ +#define GET_UVECTOR_ELEMENT_AS(type) do { \ + GRN_ ## type ## _SET(ctx, \ + buf, \ + GRN_ ## type ## _VALUE_AT(uvector, offset)); \ + } while (GRN_FALSE) + switch (uvector->header.domain) { + case GRN_DB_BOOL : + GET_UVECTOR_ELEMENT_AS(BOOL); + break; + case GRN_DB_INT8 : + GET_UVECTOR_ELEMENT_AS(INT8); + break; + case GRN_DB_UINT8 : + GET_UVECTOR_ELEMENT_AS(UINT8); + break; + case GRN_DB_INT16 : + GET_UVECTOR_ELEMENT_AS(INT16); + break; + case GRN_DB_UINT16 : + GET_UVECTOR_ELEMENT_AS(UINT16); + break; + case GRN_DB_INT32 : + GET_UVECTOR_ELEMENT_AS(INT32); + break; + case GRN_DB_UINT32 : + GET_UVECTOR_ELEMENT_AS(UINT32); + break; + case GRN_DB_INT64 : + GET_UVECTOR_ELEMENT_AS(INT64); + break; + case GRN_DB_UINT64 : + GET_UVECTOR_ELEMENT_AS(UINT64); + break; + case GRN_DB_FLOAT : + GET_UVECTOR_ELEMENT_AS(FLOAT); + break; + case GRN_DB_TIME : + GET_UVECTOR_ELEMENT_AS(TIME); + break; + default : + GET_UVECTOR_ELEMENT_AS(RECORD); + break; + } +#undef GET_UVECTOR_ELEMENT_AS +} + +inline static void +apply_max(grn_ctx *ctx, grn_obj *number, grn_obj *max, + grn_obj *casted_number, grn_obj *casted_max, grn_id cast_type) +{ + grn_id domain = number->header.domain; + if (!is_comparable_number_type(domain)) { + return; + } + cast_type = larger_number_type(cast_type, domain); + if (!number_safe_cast(ctx, number, casted_number, cast_type)) { + return; + } + if (max->header.domain == GRN_DB_VOID) { + grn_obj_reinit(ctx, max, cast_type, 0); + GRN_TEXT_SET(ctx, max, + GRN_TEXT_VALUE(casted_number), + GRN_TEXT_LEN(casted_number)); + return; + } + + if (max->header.domain != cast_type) { + if (!number_safe_cast(ctx, max, casted_max, cast_type)) { + return; + } + grn_obj_reinit(ctx, max, cast_type, 0); + GRN_TEXT_SET(ctx, max, + GRN_TEXT_VALUE(casted_max), + GRN_TEXT_LEN(casted_max)); + } + if (compare_number(ctx, casted_number, max, cast_type) > 0) { + grn_obj_reinit(ctx, max, cast_type, 0); + GRN_TEXT_SET(ctx, max, + GRN_TEXT_VALUE(casted_number), + GRN_TEXT_LEN(casted_number)); + } +} + +static grn_obj * +func_max(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *max; + grn_id cast_type = GRN_DB_INT8; + grn_obj casted_max, casted_number; + int i; + + max = GRN_PROC_ALLOC(GRN_DB_VOID, 0); + if (!max) { + return max; + } + + GRN_VOID_INIT(&casted_max); + GRN_VOID_INIT(&casted_number); + + for (i = 0; i < nargs; i++) { + switch (args[i]->header.type) { + case GRN_BULK : + apply_max(ctx, args[i], max, &casted_number, &casted_max, cast_type); + break; + case GRN_UVECTOR : + { + unsigned int j; + unsigned int n_elements; + grn_obj number_in_uvector; + grn_obj *domain; + + domain = grn_ctx_at(ctx, args[i]->header.domain); + GRN_OBJ_INIT(&number_in_uvector, GRN_BULK, 0, args[i]->header.domain); + n_elements = grn_uvector_size(ctx, args[i]); + for (j = 0; j < n_elements; j++) { + get_number_in_grn_uvector(ctx, args[i], j, &number_in_uvector); + if (grn_obj_is_table(ctx, domain)) { + grn_obj_reinit(ctx, &number_in_uvector, domain->header.domain, 0); + grn_table_get_key2(ctx, domain, + GRN_RECORD_VALUE(&number_in_uvector), + &number_in_uvector); + } + apply_max(ctx, &number_in_uvector, max, &casted_number, &casted_max, cast_type); + } + GRN_OBJ_FIN(ctx, &number_in_uvector); + } + break; + default : + continue; + } + } + GRN_OBJ_FIN(ctx, &casted_max); + GRN_OBJ_FIN(ctx, &casted_number); + + return max; +} + +static void +apply_min(grn_ctx *ctx, grn_obj *number, grn_obj *min, + grn_obj *casted_number, grn_obj *casted_min, grn_id cast_type) +{ + grn_id domain = number->header.domain; + if (!is_comparable_number_type(domain)) { + return; + } + cast_type = smaller_number_type(cast_type, domain); + if (!number_safe_cast(ctx, number, casted_number, cast_type)) { + return; + } + if (min->header.domain == GRN_DB_VOID) { + grn_obj_reinit(ctx, min, cast_type, 0); + GRN_TEXT_SET(ctx, min, + GRN_TEXT_VALUE(casted_number), + GRN_TEXT_LEN(casted_number)); + return; + } + + if (min->header.domain != cast_type) { + if (!number_safe_cast(ctx, min, casted_min, cast_type)) { + return; + } + grn_obj_reinit(ctx, min, cast_type, 0); + GRN_TEXT_SET(ctx, min, + GRN_TEXT_VALUE(casted_min), + GRN_TEXT_LEN(casted_min)); + } + if (compare_number(ctx, casted_number, min, cast_type) < 0) { + grn_obj_reinit(ctx, min, cast_type, 0); + GRN_TEXT_SET(ctx, min, + GRN_TEXT_VALUE(casted_number), + GRN_TEXT_LEN(casted_number)); + } +} + +static grn_obj * +func_min(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *min; + grn_id cast_type = GRN_DB_INT8; + grn_obj casted_min, casted_number; + int i; + + min = GRN_PROC_ALLOC(GRN_DB_VOID, 0); + if (!min) { + return min; + } + + GRN_VOID_INIT(&casted_min); + GRN_VOID_INIT(&casted_number); + for (i = 0; i < nargs; i++) { + switch (args[i]->header.type) { + case GRN_BULK : + apply_min(ctx, args[i], min, &casted_number, &casted_min, cast_type); + break; + case GRN_UVECTOR : + { + unsigned int j; + unsigned int n_elements; + grn_obj number_in_uvector; + grn_obj *domain; + + domain = grn_ctx_at(ctx, args[i]->header.domain); + GRN_OBJ_INIT(&number_in_uvector, GRN_BULK, 0, args[i]->header.domain); + n_elements = grn_uvector_size(ctx, args[i]); + for (j = 0; j < n_elements; j++) { + get_number_in_grn_uvector(ctx, args[i], j, &number_in_uvector); + if (grn_obj_is_table(ctx, domain)) { + grn_obj_reinit(ctx, &number_in_uvector, domain->header.domain, 0); + grn_table_get_key2(ctx, domain, + GRN_RECORD_VALUE(&number_in_uvector), + &number_in_uvector); + } + apply_min(ctx, &number_in_uvector, min, &casted_number, &casted_min, cast_type); + } + GRN_OBJ_FIN(ctx, &number_in_uvector); + } + break; + default : + continue; + } + } + GRN_OBJ_FIN(ctx, &casted_min); + GRN_OBJ_FIN(ctx, &casted_number); + + return min; +} + +static grn_obj * +func_geo_in_circle(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *obj; + grn_bool r = GRN_FALSE; + grn_geo_approximate_type type = GRN_GEO_APPROXIMATE_RECTANGLE; + switch (nargs) { + case 4 : + if (grn_geo_resolve_approximate_type(ctx, args[3], &type) != GRN_SUCCESS) { + break; + } + /* fallthru */ + case 3 : + r = grn_geo_in_circle(ctx, args[0], args[1], args[2], type); + break; + default : + break; + } + if ((obj = GRN_PROC_ALLOC(GRN_DB_BOOL, 0))) { + GRN_BOOL_SET(ctx, obj, r); + } + return obj; +} + +static grn_obj * +func_geo_in_rectangle(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *obj; + grn_bool r = GRN_FALSE; + if (nargs == 3) { + r = grn_geo_in_rectangle(ctx, args[0], args[1], args[2]); + } + if ((obj = GRN_PROC_ALLOC(GRN_DB_BOOL, 0))) { + GRN_BOOL_SET(ctx, obj, r); + } + return obj; +} + +static grn_obj * +func_geo_distance(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *obj; + double d = 0.0; + grn_geo_approximate_type type = GRN_GEO_APPROXIMATE_RECTANGLE; + switch (nargs) { + case 3 : + if (grn_geo_resolve_approximate_type(ctx, args[2], &type) != GRN_SUCCESS) { + break; + } + /* fallthru */ + case 2 : + d = grn_geo_distance(ctx, args[0], args[1], type); + break; + default: + break; + } + if ((obj = GRN_PROC_ALLOC(GRN_DB_FLOAT, 0))) { + GRN_FLOAT_SET(ctx, obj, d); + } + return obj; +} + +/* deprecated. */ +static grn_obj * +func_geo_distance2(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *obj; + double d = 0; + if (nargs == 2) { + d = grn_geo_distance_sphere(ctx, args[0], args[1]); + } + if ((obj = GRN_PROC_ALLOC(GRN_DB_FLOAT, 0))) { + GRN_FLOAT_SET(ctx, obj, d); + } + return obj; +} + +/* deprecated. */ +static grn_obj * +func_geo_distance3(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *obj; + double d = 0; + if (nargs == 2) { + d = grn_geo_distance_ellipsoid(ctx, args[0], args[1]); + } + if ((obj = GRN_PROC_ALLOC(GRN_DB_FLOAT, 0))) { + GRN_FLOAT_SET(ctx, obj, d); + } + return obj; +} + +static grn_obj * +func_all_records(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *true_value; + if ((true_value = GRN_PROC_ALLOC(GRN_DB_BOOL, 0))) { + GRN_BOOL_SET(ctx, true_value, GRN_TRUE); + } + return true_value; +} + +static grn_rc +selector_all_records(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + grn_posting posting; + + memset(&posting, 0, sizeof(grn_posting)); + GRN_TABLE_EACH(ctx, table, 0, 0, id, NULL, NULL, NULL, { + posting.rid = id; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, GRN_OP_OR); + }); + + return ctx->rc; +} + +typedef struct { + grn_obj *found; + grn_obj *table; + grn_obj *records; +} selector_to_function_data; + +static grn_bool +selector_to_function_data_init(grn_ctx *ctx, + selector_to_function_data *data, + grn_user_data *user_data) +{ + grn_obj *condition = NULL; + grn_obj *variable; + + data->table = NULL; + data->records = NULL; + + data->found = GRN_PROC_ALLOC(GRN_DB_BOOL, 0); + if (!data->found) { + return GRN_FALSE; + } + GRN_BOOL_SET(ctx, data->found, GRN_FALSE); + + grn_proc_get_info(ctx, user_data, NULL, NULL, &condition); + if (!condition) { + return GRN_FALSE; + } + + variable = grn_expr_get_var_by_offset(ctx, condition, 0); + if (!variable) { + return GRN_FALSE; + } + + data->table = grn_ctx_at(ctx, variable->header.domain); + if (!data->table) { + return GRN_FALSE; + } + + data->records = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + data->table, NULL); + if (!data->records) { + return GRN_FALSE; + } + + { + grn_rset_posinfo pi; + unsigned int key_size; + memset(&pi, 0, sizeof(grn_rset_posinfo)); + pi.rid = GRN_RECORD_VALUE(variable); + key_size = ((grn_hash *)(data->records))->key_size; + if (grn_table_add(ctx, data->records, &pi, key_size, NULL) == GRN_ID_NIL) { + return GRN_FALSE; + } + } + + return GRN_TRUE; +} + +static void +selector_to_function_data_selected(grn_ctx *ctx, + selector_to_function_data *data) +{ + GRN_BOOL_SET(ctx, data->found, grn_table_size(ctx, data->records) > 0); +} + +static void +selector_to_function_data_fin(grn_ctx *ctx, + selector_to_function_data *data) +{ + if (data->records) { + grn_obj_unlink(ctx, data->records); + } +} + +grn_operator +grn_proc_option_value_mode(grn_ctx *ctx, + grn_obj *option, + grn_operator default_mode, + const char *context) +{ + if (option->header.domain != GRN_DB_TEXT) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, option); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "%s: mode must be text: <%.*s>", + context, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return GRN_OP_NOP; + } + + if (GRN_TEXT_LEN(option) == 0) { + return default_mode; + } + +#define EQUAL_MODE(name) \ + (GRN_TEXT_LEN(option) == strlen(name) && \ + memcmp(GRN_TEXT_VALUE(option), name, strlen(name)) == 0) + + if (EQUAL_MODE("==") || EQUAL_MODE("EQUAL")) { + return GRN_OP_EQUAL; + } else if (EQUAL_MODE("!=") || EQUAL_MODE("NOT_EQUAL")) { + return GRN_OP_NOT_EQUAL; + } else if (EQUAL_MODE("<") || EQUAL_MODE("LESS")) { + return GRN_OP_LESS; + } else if (EQUAL_MODE(">") || EQUAL_MODE("GREATER")) { + return GRN_OP_GREATER; + } else if (EQUAL_MODE("<=") || EQUAL_MODE("LESS_EQUAL")) { + return GRN_OP_LESS_EQUAL; + } else if (EQUAL_MODE(">=") || EQUAL_MODE("GREATER_EQUAL")) { + return GRN_OP_GREATER_EQUAL; + } else if (EQUAL_MODE("@") || EQUAL_MODE("MATCH")) { + return GRN_OP_MATCH; + } else if (EQUAL_MODE("*N") || EQUAL_MODE("NEAR")) { + return GRN_OP_NEAR; + } else if (EQUAL_MODE("*S") || EQUAL_MODE("SIMILAR")) { + return GRN_OP_SIMILAR; + } else if (EQUAL_MODE("^") || EQUAL_MODE("@^") || EQUAL_MODE("PREFIX")) { + return GRN_OP_PREFIX; + } else if (EQUAL_MODE("$") || EQUAL_MODE("@$") || EQUAL_MODE("SUFFIX")) { + return GRN_OP_SUFFIX; + } else if (EQUAL_MODE("~") || EQUAL_MODE("@~") || EQUAL_MODE("REGEXP")) { + return GRN_OP_REGEXP; + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "%s: mode must be one of them: " + "[" + "\"==\", \"EQUAL\", " + "\"!=\", \"NOT_EQUAL\", " + "\"<\", \"LESS\", " + "\">\", \"GREATER\", " + "\"<=\", \"LESS_EQUAL\", " + "\">=\", \"GREATER_EQUAL\", " + "\"@\", \"MATCH\", " + "\"*N\", \"NEAR\", " + "\"*S\", \"SIMILAR\", " + "\"^\", \"@^\", \"PREFIX\", " + "\"$\", \"@$\", \"SUFFIX\", " + "\"~\", \"@~\", \"REGEXP\"" + "]: <%.*s>", + context, + (int)GRN_TEXT_LEN(option), + GRN_TEXT_VALUE(option)); + return GRN_OP_NOP; + } + +#undef EQUAL_MODE +} + +static grn_rc +run_query(grn_ctx *ctx, grn_obj *table, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *match_columns_string; + grn_obj *query; + grn_obj *query_expander_name = NULL; + grn_operator default_mode = GRN_OP_MATCH; + grn_expr_flags flags = GRN_EXPR_SYNTAX_QUERY; + grn_bool flags_specified = GRN_FALSE; + grn_obj *match_columns = NULL; + grn_obj *condition = NULL; + grn_obj *dummy_variable; + + if (!(2 <= nargs && nargs <= 3)) { + ERR(GRN_INVALID_ARGUMENT, + "query(): wrong number of arguments (%d for 2..3)", nargs); + rc = ctx->rc; + goto exit; + } + + match_columns_string = args[0]; + query = args[1]; + if (nargs > 2) { + grn_obj *options = args[2]; + + switch (options->header.type) { + case GRN_BULK : + query_expander_name = options; + break; + case GRN_TABLE_HASH_KEY : + { + grn_hash_cursor *cursor; + void *key; + grn_obj *value; + int key_size; + cursor = grn_hash_cursor_open(ctx, (grn_hash *)options, + NULL, 0, NULL, 0, + 0, -1, 0); + if (!cursor) { + GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, + "query(): failed to open cursor for options"); + rc = ctx->rc; + goto exit; + } + while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { + grn_hash_cursor_get_key_value(ctx, cursor, &key, &key_size, + (void **)&value); + +#define KEY_EQUAL(name) \ + (key_size == strlen(name) && memcmp(key, name, strlen(name)) == 0) + if (KEY_EQUAL("expander")) { + query_expander_name = value; + } else if (KEY_EQUAL("default_mode")) { + default_mode = grn_proc_option_value_mode(ctx, + value, + GRN_OP_MATCH, + "query()"); + if (ctx->rc != GRN_SUCCESS) { + grn_hash_cursor_close(ctx, cursor); + rc = ctx->rc; + goto exit; + } + } else if (KEY_EQUAL("flags")) { + flags_specified = GRN_TRUE; + flags |= grn_proc_expr_query_flags_parse(ctx, + GRN_TEXT_VALUE(value), + GRN_TEXT_LEN(value), + "query()"); + if (ctx->rc != GRN_SUCCESS) { + grn_hash_cursor_close(ctx, cursor); + rc = ctx->rc; + goto exit; + } + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "query(): unknown option name: <%.*s>", + key_size, (char *)key); + grn_hash_cursor_close(ctx, cursor); + rc = ctx->rc; + goto exit; + } +#undef KEY_EQUAL + } + grn_hash_cursor_close(ctx, cursor); + } + break; + default : + { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, options); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "query(): " + "3rd argument must be string or object literal: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + } + rc = ctx->rc; + goto exit; + } + } + + if (!flags_specified) { + flags |= GRN_EXPR_ALLOW_PRAGMA | GRN_EXPR_ALLOW_COLUMN; + } + + if (match_columns_string->header.domain == GRN_DB_TEXT && + GRN_TEXT_LEN(match_columns_string) > 0) { + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, match_columns, dummy_variable); + if (!match_columns) { + rc = ctx->rc; + goto exit; + } + + grn_expr_parse(ctx, match_columns, + GRN_TEXT_VALUE(match_columns_string), + GRN_TEXT_LEN(match_columns_string), + NULL, GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc != GRN_SUCCESS) { + rc = ctx->rc; + goto exit; + } + } + + if (query->header.domain == GRN_DB_TEXT && GRN_TEXT_LEN(query) > 0) { + const char *query_string; + unsigned int query_string_len; + grn_obj expanded_query; + + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, condition, dummy_variable); + if (!condition) { + rc = ctx->rc; + goto exit; + } + + query_string = GRN_TEXT_VALUE(query); + query_string_len = GRN_TEXT_LEN(query); + + GRN_TEXT_INIT(&expanded_query, 0); + if (query_expander_name && + query_expander_name->header.domain == GRN_DB_TEXT && + GRN_TEXT_LEN(query_expander_name) > 0) { + rc = grn_proc_syntax_expand_query(ctx, + query_string, query_string_len, + flags, + GRN_TEXT_VALUE(query_expander_name), + GRN_TEXT_LEN(query_expander_name), + NULL, 0, + NULL, 0, + &expanded_query, + "[query]"); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FIN(ctx, &expanded_query); + goto exit; + } + query_string = GRN_TEXT_VALUE(&expanded_query); + query_string_len = GRN_TEXT_LEN(&expanded_query); + } + grn_expr_parse(ctx, condition, + query_string, + query_string_len, + match_columns, default_mode, GRN_OP_AND, flags); + rc = ctx->rc; + GRN_OBJ_FIN(ctx, &expanded_query); + if (rc != GRN_SUCCESS) { + goto exit; + } + grn_table_select(ctx, table, condition, res, op); + rc = ctx->rc; + } + +exit : + if (match_columns) { + grn_obj_unlink(ctx, match_columns); + } + if (condition) { + grn_obj_unlink(ctx, condition); + } + + return rc; +} + +static grn_obj * +func_query(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + selector_to_function_data data; + + if (selector_to_function_data_init(ctx, &data, user_data)) { + grn_rc rc; + rc = run_query(ctx, data.table, nargs, args, data.records, GRN_OP_AND); + if (rc == GRN_SUCCESS) { + selector_to_function_data_selected(ctx, &data); + } + } + selector_to_function_data_fin(ctx, &data); + + return data.found; +} + +static grn_rc +selector_query(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + return run_query(ctx, table, nargs - 1, args + 1, res, op); +} + +static grn_rc +run_sub_filter(grn_ctx *ctx, grn_obj *table, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *scope; + grn_obj *sub_filter_string; + grn_obj *scope_domain = NULL; + grn_obj *sub_filter = NULL; + grn_obj *dummy_variable = NULL; + + if (nargs != 2) { + ERR(GRN_INVALID_ARGUMENT, + "sub_filter(): wrong number of arguments (%d for 2)", nargs); + rc = ctx->rc; + goto exit; + } + + scope = args[0]; + sub_filter_string = args[1]; + + switch (scope->header.type) { + case GRN_ACCESSOR : + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + break; + default : + /* TODO: put inspected the 1st argument to message */ + ERR(GRN_INVALID_ARGUMENT, + "sub_filter(): the 1st argument must be column or accessor"); + rc = ctx->rc; + goto exit; + break; + } + + scope_domain = grn_ctx_at(ctx, grn_obj_get_range(ctx, scope)); + + if (sub_filter_string->header.domain != GRN_DB_TEXT) { + /* TODO: put inspected the 2nd argument to message */ + ERR(GRN_INVALID_ARGUMENT, + "sub_filter(): the 2nd argument must be String"); + rc = ctx->rc; + goto exit; + } + if (GRN_TEXT_LEN(sub_filter_string) == 0) { + ERR(GRN_INVALID_ARGUMENT, + "sub_filter(): the 2nd argument must not be empty String"); + rc = ctx->rc; + goto exit; + } + + GRN_EXPR_CREATE_FOR_QUERY(ctx, scope_domain, sub_filter, dummy_variable); + if (!sub_filter) { + rc = ctx->rc; + goto exit; + } + + grn_expr_parse(ctx, sub_filter, + GRN_TEXT_VALUE(sub_filter_string), + GRN_TEXT_LEN(sub_filter_string), + NULL, GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc != GRN_SUCCESS) { + rc = ctx->rc; + goto exit; + } + + { + grn_obj *base_res = NULL; + + base_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + scope_domain, NULL); + grn_table_select(ctx, scope_domain, sub_filter, base_res, GRN_OP_OR); + if (scope->header.type == GRN_ACCESSOR) { + rc = grn_accessor_resolve(ctx, scope, -1, base_res, res, op); + } else { + grn_accessor accessor; + accessor.header.type = GRN_ACCESSOR; + accessor.obj = scope; + accessor.action = GRN_ACCESSOR_GET_COLUMN_VALUE; + accessor.next = NULL; + rc = grn_accessor_resolve(ctx, (grn_obj *)&accessor, -1, base_res, + res, op); + } + grn_obj_unlink(ctx, base_res); + } + +exit : + if (scope_domain) { + grn_obj_unlink(ctx, scope_domain); + } + if (sub_filter) { + grn_obj_unlink(ctx, sub_filter); + } + + return rc; +} + +static grn_rc +selector_sub_filter(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + return run_sub_filter(ctx, table, nargs - 1, args + 1, res, op); +} + +static grn_obj * +func_html_untag(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *html_arg; + int html_arg_domain; + grn_obj html; + grn_obj *text; + const char *html_raw; + int i, length; + grn_bool in_tag = GRN_FALSE; + + if (nargs != 1) { + ERR(GRN_INVALID_ARGUMENT, "HTML is missing"); + return NULL; + } + + html_arg = args[0]; + html_arg_domain = html_arg->header.domain; + switch (html_arg_domain) { + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + GRN_VALUE_VAR_SIZE_INIT(&html, GRN_OBJ_DO_SHALLOW_COPY, html_arg_domain); + GRN_TEXT_SET(ctx, &html, GRN_TEXT_VALUE(html_arg), GRN_TEXT_LEN(html_arg)); + break; + default : + GRN_TEXT_INIT(&html, 0); + if (grn_obj_cast(ctx, html_arg, &html, GRN_FALSE)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, html_arg); + ERR(GRN_INVALID_ARGUMENT, "failed to cast to text: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + GRN_OBJ_FIN(ctx, &html); + return NULL; + } + break; + } + + text = GRN_PROC_ALLOC(html.header.domain, 0); + if (!text) { + GRN_OBJ_FIN(ctx, &html); + return NULL; + } + + html_raw = GRN_TEXT_VALUE(&html); + length = GRN_TEXT_LEN(&html); + for (i = 0; i < length; i++) { + switch (html_raw[i]) { + case '<' : + in_tag = GRN_TRUE; + break; + case '>' : + if (in_tag) { + in_tag = GRN_FALSE; + } else { + GRN_TEXT_PUTC(ctx, text, html_raw[i]); + } + break; + default : + if (!in_tag) { + GRN_TEXT_PUTC(ctx, text, html_raw[i]); + } + break; + } + } + + GRN_OBJ_FIN(ctx, &html); + + return text; +} + +static grn_bool +grn_text_equal_cstr(grn_ctx *ctx, grn_obj *text, const char *cstr) +{ + int cstr_len; + + cstr_len = strlen(cstr); + return (GRN_TEXT_LEN(text) == cstr_len && + strncmp(GRN_TEXT_VALUE(text), cstr, cstr_len) == 0); +} + +typedef enum { + BETWEEN_BORDER_INVALID, + BETWEEN_BORDER_INCLUDE, + BETWEEN_BORDER_EXCLUDE +} between_border_type; + +typedef struct { + grn_obj *value; + grn_obj *min; + grn_obj casted_min; + between_border_type min_border_type; + grn_obj *max; + grn_obj casted_max; + between_border_type max_border_type; +} between_data; + +static void +between_data_init(grn_ctx *ctx, between_data *data) +{ + GRN_VOID_INIT(&(data->casted_min)); + GRN_VOID_INIT(&(data->casted_max)); +} + +static void +between_data_fin(grn_ctx *ctx, between_data *data) +{ + GRN_OBJ_FIN(ctx, &(data->casted_min)); + GRN_OBJ_FIN(ctx, &(data->casted_max)); +} + +static between_border_type +between_parse_border(grn_ctx *ctx, grn_obj *border, + const char *argument_description) +{ + grn_obj inspected; + + /* TODO: support other text types */ + if (border->header.domain == GRN_DB_TEXT) { + if (grn_text_equal_cstr(ctx, border, "include")) { + return BETWEEN_BORDER_INCLUDE; + } else if (grn_text_equal_cstr(ctx, border, "exclude")) { + return BETWEEN_BORDER_EXCLUDE; + } + } + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, border); + ERR(GRN_INVALID_ARGUMENT, + "between(): %s must be \"include\" or \"exclude\": <%.*s>", + argument_description, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + grn_obj_unlink(ctx, &inspected); + + return BETWEEN_BORDER_INVALID; +} + +static grn_rc +between_cast(grn_ctx *ctx, grn_obj *source, grn_obj *destination, grn_id domain, + const char *target_argument_name) +{ + grn_rc rc; + + GRN_OBJ_INIT(destination, GRN_BULK, 0, domain); + rc = grn_obj_cast(ctx, source, destination, GRN_FALSE); + if (rc != GRN_SUCCESS) { + grn_obj inspected_source; + grn_obj *domain_object; + char domain_name[GRN_TABLE_MAX_KEY_SIZE]; + int domain_name_length; + + GRN_TEXT_INIT(&inspected_source, 0); + grn_inspect(ctx, &inspected_source, source); + + domain_object = grn_ctx_at(ctx, domain); + domain_name_length = + grn_obj_name(ctx, domain_object, domain_name, GRN_TABLE_MAX_KEY_SIZE); + + ERR(rc, "between(): failed to cast %s: <%.*s> -> <%.*s>", + target_argument_name, + (int)GRN_TEXT_LEN(&inspected_source), + GRN_TEXT_VALUE(&inspected_source), + domain_name_length, + domain_name); + + grn_obj_unlink(ctx, &inspected_source); + grn_obj_unlink(ctx, domain_object); + } + + return rc; +} + +static grn_rc +between_parse_args(grn_ctx *ctx, int nargs, grn_obj **args, between_data *data) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *min_border; + grn_obj *max_border; + + if (nargs != 5) { + ERR(GRN_INVALID_ARGUMENT, + "between(): wrong number of arguments (%d for 5)", nargs); + rc = ctx->rc; + goto exit; + } + + data->value = args[0]; + data->min = args[1]; + min_border = args[2]; + data->max = args[3]; + max_border = args[4]; + + data->min_border_type = + between_parse_border(ctx, min_border, "the 3rd argument (min_border)"); + if (data->min_border_type == BETWEEN_BORDER_INVALID) { + rc = ctx->rc; + goto exit; + } + + data->max_border_type = + between_parse_border(ctx, max_border, "the 5th argument (max_border)"); + if (data->max_border_type == BETWEEN_BORDER_INVALID) { + rc = ctx->rc; + goto exit; + } + + { + grn_id value_type; + switch (data->value->header.type) { + case GRN_BULK : + value_type = data->value->header.domain; + break; + case GRN_COLUMN_INDEX : + { + grn_obj *domain_object; + domain_object = grn_ctx_at(ctx, data->value->header.domain); + value_type = domain_object->header.domain; + } + break; + default : + value_type = grn_obj_get_range(ctx, data->value); + break; + } + if (value_type != data->min->header.domain) { + rc = between_cast(ctx, data->min, &data->casted_min, value_type, "min"); + if (rc != GRN_SUCCESS) { + goto exit; + } + data->min = &(data->casted_min); + } + + if (value_type != data->max->header.domain) { + rc = between_cast(ctx, data->max, &data->casted_max, value_type, "max"); + if (rc != GRN_SUCCESS) { + goto exit; + } + data->max = &(data->casted_max); + } + } + +exit : + return rc; +} + +static grn_bool +between_create_expr(grn_ctx *ctx, grn_obj *table, between_data *data, + grn_obj **expr, grn_obj **variable) +{ + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, *expr, *variable); + if (!*expr) { + return GRN_FALSE; + } + + if (data->value->header.type == GRN_BULK) { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_PUSH, 1); + } else { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_GET_VALUE, 1); + } + grn_expr_append_obj(ctx, *expr, data->min, GRN_OP_PUSH, 1); + if (data->min_border_type == BETWEEN_BORDER_INCLUDE) { + grn_expr_append_op(ctx, *expr, GRN_OP_GREATER_EQUAL, 2); + } else { + grn_expr_append_op(ctx, *expr, GRN_OP_GREATER, 2); + } + + if (data->value->header.type == GRN_BULK) { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_PUSH, 1); + } else { + grn_expr_append_obj(ctx, *expr, data->value, GRN_OP_GET_VALUE, 1); + } + grn_expr_append_obj(ctx, *expr, data->max, GRN_OP_PUSH, 1); + if (data->max_border_type == BETWEEN_BORDER_INCLUDE) { + grn_expr_append_op(ctx, *expr, GRN_OP_LESS_EQUAL, 2); + } else { + grn_expr_append_op(ctx, *expr, GRN_OP_LESS, 2); + } + + grn_expr_append_op(ctx, *expr, GRN_OP_AND, 2); + + return GRN_TRUE; +} + +static grn_obj * +func_between(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *found; + between_data data; + grn_obj *condition = NULL; + grn_obj *variable; + grn_obj *table = NULL; + grn_obj *between_expr; + grn_obj *between_variable; + grn_obj *result; + + found = GRN_PROC_ALLOC(GRN_DB_BOOL, 0); + if (!found) { + return NULL; + } + GRN_BOOL_SET(ctx, found, GRN_FALSE); + + grn_proc_get_info(ctx, user_data, NULL, NULL, &condition); + if (!condition) { + return found; + } + + variable = grn_expr_get_var_by_offset(ctx, condition, 0); + if (!variable) { + return found; + } + + between_data_init(ctx, &data); + rc = between_parse_args(ctx, nargs, args, &data); + if (rc != GRN_SUCCESS) { + goto exit; + } + + table = grn_ctx_at(ctx, variable->header.domain); + if (!table) { + goto exit; + } + if (!between_create_expr(ctx, table, &data, &between_expr, &between_variable)) { + goto exit; + } + + GRN_RECORD_SET(ctx, between_variable, GRN_RECORD_VALUE(variable)); + result = grn_expr_exec(ctx, between_expr, 0); + if (grn_obj_is_true(ctx, result)) { + GRN_BOOL_SET(ctx, found, GRN_TRUE); + } + + grn_obj_unlink(ctx, between_expr); + grn_obj_unlink(ctx, table); + +exit : + between_data_fin(ctx, &data); + if (table) { + grn_obj_unlink(ctx, table); + } + + return found; +} + +static grn_bool +selector_between_sequential_search_should_use(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + grn_obj *index_table, + between_data *data, + grn_obj *res, + grn_operator op, + double too_many_index_match_ratio) +{ + int n_index_keys; + + if (too_many_index_match_ratio < 0.0) { + return GRN_FALSE; + } + + if (op != GRN_OP_AND) { + return GRN_FALSE; + } + + if (!index) { + return GRN_FALSE; + } + + if (index->header.flags & GRN_OBJ_WITH_WEIGHT) { + return GRN_FALSE; + } + + if (data->value->header.type == GRN_COLUMN_INDEX) { + return GRN_FALSE; + } + + n_index_keys = grn_table_size(ctx, index_table); + if (n_index_keys == 0) { + return GRN_FALSE; + } + + switch (index_table->header.domain) { + /* TODO: */ + /* case GRN_DB_INT8 : */ + /* case GRN_DB_UINT8 : */ + /* case GRN_DB_INT16 : */ + /* case GRN_DB_UINT16 : */ + /* case GRN_DB_INT32 : */ + /* case GRN_DB_UINT32 : */ + /* case GRN_DB_INT64 : */ + /* case GRN_DB_UINT64 : */ + /* case GRN_DB_FLOAT : */ + case GRN_DB_TIME : + break; + default : + return GRN_FALSE; + } + + { + grn_table_cursor *cursor; + long long int all_min; + long long int all_max; + cursor = grn_table_cursor_open(ctx, index_table, + NULL, -1, + NULL, -1, + 0, 1, + GRN_CURSOR_BY_KEY | GRN_CURSOR_ASCENDING); + if (!cursor) { + return GRN_FALSE; + } + if (grn_table_cursor_next(ctx, cursor) == GRN_ID_NIL) { + grn_table_cursor_close(ctx, cursor); + return GRN_FALSE; + } + { + long long int *key; + grn_table_cursor_get_key(ctx, cursor, (void **)&key); + all_min = *key; + } + grn_table_cursor_close(ctx, cursor); + + cursor = grn_table_cursor_open(ctx, index_table, + NULL, 0, NULL, 0, + 0, 1, + GRN_CURSOR_BY_KEY | GRN_CURSOR_DESCENDING); + if (!cursor) { + return GRN_FALSE; + } + if (grn_table_cursor_next(ctx, cursor) == GRN_ID_NIL) { + grn_table_cursor_close(ctx, cursor); + return GRN_FALSE; + } + { + long long int *key; + grn_table_cursor_get_key(ctx, cursor, (void **)&key); + all_max = *key; + } + grn_table_cursor_close(ctx, cursor); + + /* + * We assume the following: + * * homogeneous index key distribution. + * * each index key matches only 1 record. + * TODO: Improve me. + */ + { + int n_existing_records; + int n_indexed_records; + long long int all_difference; + long long int argument_difference; + + n_existing_records = grn_table_size(ctx, res); + + all_difference = all_max - all_min; + if (all_difference <= 0) { + return GRN_FALSE; + } + argument_difference = + GRN_TIME_VALUE(data->max) - GRN_TIME_VALUE(data->min); + if (argument_difference <= 0) { + return GRN_FALSE; + } + n_indexed_records = + n_index_keys * ((double)argument_difference / (double)all_difference); + + /* + * Same as: + * ((n_existing_record / n_indexed_records) > too_many_index_match_ratio) + */ + if (n_existing_records > (n_indexed_records * too_many_index_match_ratio)) { + return GRN_FALSE; + } + } + } + + return GRN_TRUE; +} + +static grn_rc +selector_between_sequential_search(grn_ctx *ctx, + grn_obj *table, + between_data *data, + grn_obj *res, + grn_operator op) +{ + { + int offset = 0; + int limit = -1; + int flags = 0; + grn_obj *target_table; + grn_obj *target_column; + grn_operator_exec_func *greater; + grn_operator_exec_func *less; + grn_table_cursor *cursor; + grn_id id; + grn_obj value; + + if (op == GRN_OP_AND) { + target_table = res; + } else { + target_table = table; + } + cursor = grn_table_cursor_open(ctx, target_table, + NULL, 0, + NULL, 0, + offset, limit, flags); + if (!cursor) { + return ctx->rc; + } + + if (data->value->header.type == GRN_BULK) { + target_column = grn_obj_column(ctx, + table, + GRN_TEXT_VALUE(data->value), + GRN_TEXT_LEN(data->value)); + } else { + target_column = data->value; + } + if (data->min_border_type == BETWEEN_BORDER_INCLUDE) { + greater = grn_operator_exec_greater_equal; + } else { + greater = grn_operator_exec_greater; + } + if (data->max_border_type == BETWEEN_BORDER_INCLUDE) { + less = grn_operator_exec_less_equal; + } else { + less = grn_operator_exec_less; + } + + GRN_VOID_INIT(&value); + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_id record_id; + + if (target_table == res) { + grn_id *key; + grn_table_cursor_get_key(ctx, cursor, (void **)&key); + record_id = *key; + } else { + record_id = id; + } + + GRN_BULK_REWIND(&value); + grn_obj_get_value(ctx, target_column, record_id, &value); + if (greater(ctx, &value, data->min) && less(ctx, &value, data->max)) { + grn_posting posting; + posting.rid = record_id; + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + } + + GRN_OBJ_FIN(ctx, &value); + + if (target_column != data->value && + target_column->header.type == GRN_ACCESSOR) { + grn_obj_unlink(ctx, target_column); + } + + grn_table_cursor_close(ctx, cursor); + + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + } + + return GRN_SUCCESS; +} + +static grn_rc +selector_between(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + int nargs, + grn_obj **args, + grn_obj *res, + grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + int offset = 0; + int limit = -1; + int flags = GRN_CURSOR_ASCENDING | GRN_CURSOR_BY_KEY; + between_data data; + grn_bool use_sequential_search; + grn_obj *index_table = NULL; + grn_table_cursor *cursor; + grn_id id; + + between_data_init(ctx, &data); + rc = between_parse_args(ctx, nargs - 1, args + 1, &data); + if (rc != GRN_SUCCESS) { + goto exit; + } + + if (data.min_border_type == BETWEEN_BORDER_EXCLUDE) { + flags |= GRN_CURSOR_GT; + } + if (data.max_border_type == BETWEEN_BORDER_EXCLUDE) { + flags |= GRN_CURSOR_LT; + } + + if (data.value->header.type == GRN_COLUMN_INDEX) { + index = data.value; + } + + if (index) { + switch (index->header.type) { + case GRN_TABLE_NO_KEY : + case GRN_TABLE_HASH_KEY : + break; + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + index_table = index; + index = NULL; + break; + default : + index_table = grn_ctx_at(ctx, index->header.domain); + break; + } + } + + if (index_table) { + double ratio = grn_between_too_many_index_match_ratio; + use_sequential_search = + selector_between_sequential_search_should_use(ctx, + table, + index, + index_table, + &data, + res, + op, + ratio); + } else { + use_sequential_search = GRN_TRUE; + } + if (use_sequential_search) { + rc = selector_between_sequential_search(ctx, table, &data, res, op); + goto exit; + } + + cursor = grn_table_cursor_open(ctx, index_table, + GRN_BULK_HEAD(data.min), + GRN_BULK_VSIZE(data.min), + GRN_BULK_HEAD(data.max), + GRN_BULK_VSIZE(data.max), + offset, limit, flags); + if (!cursor) { + rc = ctx->rc; + goto exit; + } + + if (index) { + while ((id = grn_table_cursor_next(ctx, cursor))) { + grn_ii_at(ctx, (grn_ii *)index, id, (grn_hash *)res, op); + } + } else { + grn_posting posting; + memset(&posting, 0, sizeof(grn_posting)); + posting.sid = 1; + posting.pos = 0; + while ((id = grn_table_cursor_next(ctx, cursor))) { + posting.rid = id; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + } + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + grn_table_cursor_close(ctx, cursor); + +exit : + between_data_fin(ctx, &data); + + return rc; +} + +static grn_obj * +func_in_values(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *found; + grn_obj *target_value; + int i; + + found = GRN_PROC_ALLOC(GRN_DB_BOOL, 0); + if (!found) { + return NULL; + } + GRN_BOOL_SET(ctx, found, GRN_FALSE); + + if (nargs < 1) { + ERR(GRN_INVALID_ARGUMENT, + "in_values(): wrong number of arguments (%d for 1..)", nargs); + return found; + } + + target_value = args[0]; + for (i = 1; i < nargs; i++) { + grn_obj *value = args[i]; + grn_bool result; + + result = grn_operator_exec_equal(ctx, target_value, value); + if (ctx->rc) { + break; + } + + if (result) { + GRN_BOOL_SET(ctx, found, GRN_TRUE); + break; + } + } + + return found; +} + +static grn_bool +is_reference_type_column(grn_ctx *ctx, grn_obj *column) +{ + grn_bool is_reference_type; + grn_obj *range; + + range = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); + switch (range->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + is_reference_type = GRN_TRUE; + break; + default : + is_reference_type = GRN_FALSE; + break; + } + grn_obj_unlink(ctx, range); + + return is_reference_type; +} + +static grn_obj * +selector_in_values_find_source(grn_ctx *ctx, grn_obj *index, grn_obj *res) +{ + grn_id source_id = GRN_ID_NIL; + grn_obj source_ids; + unsigned int n_source_ids; + + GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); + grn_obj_get_info(ctx, index, GRN_INFO_SOURCE, &source_ids); + n_source_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); + if (n_source_ids == 1) { + source_id = GRN_UINT32_VALUE_AT(&source_ids, 0); + } + GRN_OBJ_FIN(ctx, &source_ids); + + if (source_id == GRN_ID_NIL) { + return NULL; + } else { + return grn_ctx_at(ctx, source_id); + } +} + +static grn_bool +selector_in_values_sequential_search(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + int n_values, + grn_obj **values, + grn_obj *res, + grn_operator op) +{ + grn_obj *source; + int n_existing_records; + + if (grn_in_values_too_many_index_match_ratio < 0.0) { + return GRN_FALSE; + } + + if (op != GRN_OP_AND) { + return GRN_FALSE; + } + + if (index->header.flags & GRN_OBJ_WITH_WEIGHT) { + return GRN_FALSE; + } + + n_existing_records = grn_table_size(ctx, res); + if (n_existing_records == 0) { + return GRN_TRUE; + } + + source = selector_in_values_find_source(ctx, index, res); + if (!source) { + return GRN_FALSE; + } + + if (!is_reference_type_column(ctx, source)) { + grn_obj_unlink(ctx, source); + return GRN_FALSE; + } + + { + grn_obj value_ids; + int i, n_value_ids; + int n_indexed_records = 0; + + { + grn_id range_id; + grn_obj *range; + + range_id = grn_obj_get_range(ctx, source); + range = grn_ctx_at(ctx, range_id); + if (!range) { + grn_obj_unlink(ctx, source); + return GRN_FALSE; + } + + GRN_RECORD_INIT(&value_ids, GRN_OBJ_VECTOR, range_id); + for (i = 0; i < n_values; i++) { + grn_obj *value = values[i]; + grn_id value_id; + + value_id = grn_table_get(ctx, range, + GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value)); + if (value_id == GRN_ID_NIL) { + continue; + } + GRN_RECORD_PUT(ctx, &value_ids, value_id); + } + grn_obj_unlink(ctx, range); + } + + n_value_ids = GRN_BULK_VSIZE(&value_ids) / sizeof(grn_id); + for (i = 0; i < n_value_ids; i++) { + grn_id value_id = GRN_RECORD_VALUE_AT(&value_ids, i); + n_indexed_records += grn_ii_estimate_size(ctx, (grn_ii *)index, value_id); + } + + /* + * Same as: + * ((n_existing_record / n_indexed_records) > + * grn_in_values_too_many_index_match_ratio) + */ + if (n_existing_records > + (n_indexed_records * grn_in_values_too_many_index_match_ratio)) { + grn_obj_unlink(ctx, &value_ids); + grn_obj_unlink(ctx, source); + return GRN_FALSE; + } + + { + grn_obj *accessor; + char local_source_name[GRN_TABLE_MAX_KEY_SIZE]; + int local_source_name_length; + + local_source_name_length = grn_column_name(ctx, source, + local_source_name, + GRN_TABLE_MAX_KEY_SIZE); + grn_obj_unlink(ctx, source); + accessor = grn_obj_column(ctx, res, + local_source_name, + local_source_name_length); + { + grn_table_cursor *cursor; + grn_id id; + grn_obj record_value; + + GRN_VOID_INIT(&record_value); + cursor = grn_table_cursor_open(ctx, res, + NULL, 0, NULL, 0, + 0, -1, GRN_CURSOR_ASCENDING); + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_id *record_id; + grn_table_cursor_get_key(ctx, cursor, (void **)&record_id); + GRN_BULK_REWIND(&record_value); + grn_obj_get_value(ctx, accessor, id, &record_value); + for (i = 0; i < n_value_ids; i++) { + grn_id value_id = GRN_RECORD_VALUE_AT(&value_ids, i); + switch (record_value.header.type) { + case GRN_BULK : + if (value_id == GRN_RECORD_VALUE(&record_value)) { + grn_posting posting; + posting.rid = *record_id; + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + break; + case GRN_UVECTOR : + { + int j, n_elements; + n_elements = GRN_BULK_VSIZE(&record_value) / sizeof(grn_id); + for (j = 0; j < n_elements; j++) { + if (value_id == GRN_RECORD_VALUE_AT(&record_value, j)) { + grn_posting posting; + posting.rid = *record_id; + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + } + } + break; + default : + break; + } + } + } + grn_table_cursor_close(ctx, cursor); + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + GRN_OBJ_FIN(ctx, &record_value); + } + grn_obj_unlink(ctx, accessor); + } + grn_obj_unlink(ctx, &value_ids); + } + grn_obj_unlink(ctx, source); + + return GRN_TRUE; +} + +static grn_rc +selector_in_values(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + int i, n_values; + grn_obj **values; + + if (!index) { + return GRN_INVALID_ARGUMENT; + } + + if (nargs < 2) { + ERR(GRN_INVALID_ARGUMENT, + "in_values(): wrong number of arguments (%d for 1..)", nargs); + return ctx->rc; + } + + n_values = nargs - 2; + values = args + 2; + + if (n_values == 0) { + return rc; + } + + if (selector_in_values_sequential_search(ctx, table, index, + n_values, values, + res, op)) { + return ctx->rc; + } + + ctx->flags |= GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND; + for (i = 0; i < n_values; i++) { + grn_obj *value = values[i]; + grn_search_optarg search_options; + memset(&search_options, 0, sizeof(grn_search_optarg)); + search_options.mode = GRN_OP_EXACT; + search_options.similarity_threshold = 0; + search_options.max_interval = 0; + search_options.weight_vector = NULL; + search_options.vector_size = 0; + search_options.proc = NULL; + search_options.max_size = 0; + search_options.scorer = NULL; + if (i == n_values - 1) { + ctx->flags &= ~GRN_CTX_TEMPORARY_DISABLE_II_RESOLVE_SEL_AND; + } + rc = grn_obj_search(ctx, index, value, res, op, &search_options); + if (rc != GRN_SUCCESS) { + break; + } + } + + return rc; +} + +static grn_obj * +proc_range_filter(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *table_name = VAR(0); + grn_obj *column_name = VAR(1); + grn_obj *min = VAR(2); + grn_obj *min_border = VAR(3); + grn_obj *max = VAR(4); + grn_obj *max_border = VAR(5); + grn_obj *offset = VAR(6); + grn_obj *limit = VAR(7); + grn_obj *filter = VAR(8); + grn_obj *output_columns = VAR(9); + grn_obj *table; + grn_obj *res = NULL; + grn_obj *filter_expr = NULL; + grn_obj *filter_variable = NULL; + int real_offset; + int real_limit; + + table = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_name), GRN_TEXT_LEN(table_name)); + if (!table) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] nonexistent table <%.*s>", + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name)); + return NULL; + } + + if (GRN_TEXT_LEN(filter) > 0) { + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, filter_expr, filter_variable); + if (!filter_expr) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] failed to create expression"); + goto exit; + } + + grn_expr_parse(ctx, filter_expr, + GRN_TEXT_VALUE(filter), GRN_TEXT_LEN(filter), + NULL, GRN_OP_MATCH, GRN_OP_AND, GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + } + + res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + table, NULL); + if (!res) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] failed to result table"); + goto exit; + } + + { + grn_obj int32_value; + + GRN_INT32_INIT(&int32_value, 0); + + if (GRN_TEXT_LEN(offset) > 0) { + if (grn_obj_cast(ctx, offset, &int32_value, GRN_FALSE) != GRN_SUCCESS) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] invalid offset format: <%.*s>", + (int)GRN_TEXT_LEN(offset), GRN_TEXT_VALUE(offset)); + GRN_OBJ_FIN(ctx, &int32_value); + goto exit; + } + real_offset = GRN_INT32_VALUE(&int32_value); + } else { + real_offset = 0; + } + + GRN_BULK_REWIND(&int32_value); + + if (GRN_TEXT_LEN(limit) > 0) { + if (grn_obj_cast(ctx, limit, &int32_value, GRN_FALSE) != GRN_SUCCESS) { + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] invalid limit format: <%.*s>", + (int)GRN_TEXT_LEN(limit), GRN_TEXT_VALUE(limit)); + GRN_OBJ_FIN(ctx, &int32_value); + goto exit; + } + real_limit = GRN_INT32_VALUE(&int32_value); + } else { + real_limit = GRN_SELECT_DEFAULT_LIMIT; + } + + GRN_OBJ_FIN(ctx, &int32_value); + } + { + grn_rc rc; + int original_offset = real_offset; + int original_limit = real_limit; + rc = grn_normalize_offset_and_limit(ctx, grn_table_size(ctx, table), + &real_offset, &real_limit); + switch (rc) { + case GRN_TOO_SMALL_OFFSET : + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] too small offset: <%d>", original_offset); + goto exit; + case GRN_TOO_LARGE_OFFSET : + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] too large offset: <%d>", original_offset); + goto exit; + case GRN_TOO_SMALL_LIMIT : + ERR(GRN_INVALID_ARGUMENT, + "[range_filter] too small limit: <%d>", original_limit); + goto exit; + default : + break; + } + } + + if (real_limit != 0) { + grn_table_sort_key *sort_keys; + unsigned int n_sort_keys; + sort_keys = grn_table_sort_key_from_str(ctx, + GRN_TEXT_VALUE(column_name), + GRN_TEXT_LEN(column_name), + table, + &n_sort_keys); + if (n_sort_keys == 1) { + grn_table_sort_key *sort_key; + grn_obj *index; + int n_indexes; + grn_operator op = GRN_OP_OR; + + sort_key = &(sort_keys[0]); + n_indexes = grn_column_index(ctx, sort_key->key, GRN_OP_LESS, + &index, 1, NULL); + if (n_indexes > 0) { + grn_obj *lexicon; + grn_table_cursor *table_cursor; + int table_cursor_flags = 0; + between_border_type min_border_type; + between_border_type max_border_type; + grn_obj real_min; + grn_obj real_max; + int n_records = 0; + grn_obj *index_cursor; + int index_cursor_flags = 0; + grn_posting *posting; + + lexicon = grn_ctx_at(ctx, index->header.domain); + if (sort_key->flags & GRN_TABLE_SORT_DESC) { + table_cursor_flags |= GRN_CURSOR_DESCENDING; + } else { + table_cursor_flags |= GRN_CURSOR_ASCENDING; + } + if (GRN_TEXT_LEN(min_border) > 0) { + min_border_type = between_parse_border(ctx, min_border, "min_border"); + } else { + min_border_type = BETWEEN_BORDER_INCLUDE; + } + if (GRN_TEXT_LEN(max_border) > 0) { + max_border_type = between_parse_border(ctx, max_border, "max_border"); + } else { + max_border_type = BETWEEN_BORDER_INCLUDE; + } + if (min_border_type == BETWEEN_BORDER_EXCLUDE) { + table_cursor_flags |= GRN_CURSOR_GT; + } + if (max_border_type == BETWEEN_BORDER_EXCLUDE) { + table_cursor_flags |= GRN_CURSOR_LT; + } + GRN_OBJ_INIT(&real_min, GRN_BULK, 0, lexicon->header.domain); + GRN_OBJ_INIT(&real_max, GRN_BULK, 0, lexicon->header.domain); + if (GRN_TEXT_LEN(min) > 0) { + grn_obj_cast(ctx, min, &real_min, GRN_FALSE); + } + if (GRN_TEXT_LEN(max) > 0) { + grn_obj_cast(ctx, max, &real_max, GRN_FALSE); + } + table_cursor = grn_table_cursor_open(ctx, lexicon, + GRN_BULK_HEAD(&real_min), + GRN_BULK_VSIZE(&real_min), + GRN_BULK_HEAD(&real_max), + GRN_BULK_VSIZE(&real_max), + 0, -1, table_cursor_flags); + index_cursor = grn_index_cursor_open(ctx, table_cursor, + index, GRN_ID_NIL, GRN_ID_NIL, + index_cursor_flags); + while ((posting = grn_index_cursor_next(ctx, index_cursor, NULL))) { + grn_bool result_boolean = GRN_FALSE; + + if (filter_expr) { + grn_obj *result; + GRN_RECORD_SET(ctx, filter_variable, posting->rid); + result = grn_expr_exec(ctx, filter_expr, 0); + if (ctx->rc) { + break; + } + result_boolean = grn_obj_is_true(ctx, result); + } else { + result_boolean = GRN_TRUE; + } + + if (result_boolean) { + if (n_records >= real_offset) { + grn_ii_posting_add(ctx, posting, (grn_hash *)res, op); + } + n_records++; + if (n_records == real_limit) { + break; + } + } + } + grn_obj_unlink(ctx, index_cursor); + grn_table_cursor_close(ctx, table_cursor); + + GRN_OBJ_FIN(ctx, &real_min); + GRN_OBJ_FIN(ctx, &real_max); + } + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + } + grn_table_sort_key_close(ctx, sort_keys, n_sort_keys); + } + + if (ctx->rc == GRN_SUCCESS) { + const char *raw_output_columns; + int raw_output_columns_len; + + raw_output_columns = GRN_TEXT_VALUE(output_columns); + raw_output_columns_len = GRN_TEXT_LEN(output_columns); + if (raw_output_columns_len == 0) { + raw_output_columns = GRN_SELECT_DEFAULT_OUTPUT_COLUMNS; + raw_output_columns_len = strlen(raw_output_columns); + } + grn_proc_select_output_columns(ctx, res, -1, real_offset, real_limit, + raw_output_columns, + raw_output_columns_len, + filter_expr); + } + +exit : + if (filter_expr) { + grn_obj_unlink(ctx, filter_expr); + } + if (res) { + grn_obj_unlink(ctx, res); + } + + return NULL; +} + +static grn_obj * +proc_request_cancel(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *id = VAR(0); + grn_bool canceled; + + if (GRN_TEXT_LEN(id) == 0) { + ERR(GRN_INVALID_ARGUMENT, "[request_cancel] ID is missing"); + return NULL; + } + + canceled = grn_request_canceler_cancel(GRN_TEXT_VALUE(id), GRN_TEXT_LEN(id)); + + GRN_OUTPUT_MAP_OPEN("result", 2); + GRN_OUTPUT_CSTR("id"); + GRN_OUTPUT_STR(GRN_TEXT_VALUE(id), GRN_TEXT_LEN(id)); + GRN_OUTPUT_CSTR("canceled"); + GRN_OUTPUT_BOOL(canceled); + GRN_OUTPUT_MAP_CLOSE(); + + return NULL; +} + +static grn_obj * +proc_plugin_register(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + if (GRN_TEXT_LEN(VAR(0))) { + const char *name; + GRN_TEXT_PUTC(ctx, VAR(0), '\0'); + name = GRN_TEXT_VALUE(VAR(0)); + grn_plugin_register(ctx, name); + } else { + ERR(GRN_INVALID_ARGUMENT, "[plugin_register] name is missing"); + } + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static grn_obj * +proc_plugin_unregister(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + if (GRN_TEXT_LEN(VAR(0))) { + const char *name; + GRN_TEXT_PUTC(ctx, VAR(0), '\0'); + name = GRN_TEXT_VALUE(VAR(0)); + grn_plugin_unregister(ctx, name); + } else { + ERR(GRN_INVALID_ARGUMENT, "[plugin_unregister] name is missing"); + } + GRN_OUTPUT_BOOL(!ctx->rc); + return NULL; +} + +static grn_obj * +proc_io_flush(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *target_name; + grn_obj *recursive; + grn_obj *only_opened; + grn_obj *target; + grn_bool is_recursive; + grn_bool is_only_opened; + + target_name = VAR(0); + recursive = VAR(1); + only_opened = VAR(2); + + if (GRN_TEXT_LEN(target_name) > 0) { + target = grn_ctx_get(ctx, + GRN_TEXT_VALUE(target_name), + GRN_TEXT_LEN(target_name)); + if (!target) { + ERR(GRN_INVALID_ARGUMENT, "[io_flush] unknown target: <%.*s>", + (int)GRN_TEXT_LEN(target_name), + GRN_TEXT_VALUE(target_name)); + GRN_OUTPUT_BOOL(GRN_FALSE); + return NULL; + } + } else { + target = grn_ctx_db(ctx); + } + + is_recursive = grn_proc_option_value_bool(ctx, recursive, GRN_TRUE); + is_only_opened = grn_proc_option_value_bool(ctx, only_opened, GRN_FALSE); + { + grn_rc rc; + if (target->header.type == GRN_DB && is_only_opened) { + rc = grn_obj_flush(ctx, target); + if (rc == GRN_SUCCESS) { + GRN_TABLE_EACH_BEGIN_FLAGS(ctx, target, cursor, id, GRN_CURSOR_BY_ID) { + grn_obj *sub_target; + + if (id < GRN_N_RESERVED_TYPES) { + continue; + } + + if (!grn_ctx_is_opened(ctx, id)) { + continue; + } + + sub_target = grn_ctx_at(ctx, id); + rc = grn_obj_flush(ctx, sub_target); + if (rc != GRN_SUCCESS) { + break; + } + } GRN_TABLE_EACH_END(ctx, cursor); + } + } else { + if (is_recursive) { + rc = grn_obj_flush_recursive(ctx, target); + } else { + rc = grn_obj_flush(ctx, target); + } + } + GRN_OUTPUT_BOOL(rc == GRN_SUCCESS); + } + + + return NULL; +} + +static grn_obj * +proc_thread_limit(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *max_bulk; + uint32_t current_limit; + + current_limit = grn_thread_get_limit(); + GRN_OUTPUT_INT64(current_limit); + + max_bulk = VAR(0); + if (GRN_TEXT_LEN(max_bulk) > 0) { + uint32_t max; + const char *max_text = GRN_TEXT_VALUE(max_bulk); + const char *max_text_end; + const char *max_text_rest; + + max_text_end = max_text + GRN_TEXT_LEN(max_bulk); + max = grn_atoui(max_text, max_text_end, &max_text_rest); + if (max_text_rest != max_text_end) { + ERR(GRN_INVALID_ARGUMENT, + "[thread_limit] max must be unsigned integer value: <%.*s>", + (int)GRN_TEXT_LEN(max_bulk), + max_text); + return NULL; + } + if (max == 0) { + ERR(GRN_INVALID_ARGUMENT, + "[thread_limit] max must be 1 or larger: <%.*s>", + (int)GRN_TEXT_LEN(max_bulk), + max_text); + return NULL; + } + grn_thread_set_limit(max); + } + + return NULL; +} + +static grn_obj * +proc_database_unmap(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_rc rc; + uint32_t current_limit; + + current_limit = grn_thread_get_limit(); + if (current_limit != 1) { + ERR(GRN_OPERATION_NOT_PERMITTED, + "[database_unmap] the max number of threads must be 1: <%u>", + current_limit); + GRN_OUTPUT_BOOL(GRN_FALSE); + return NULL; + } + + rc = grn_db_unmap(ctx, grn_ctx_db(ctx)); + GRN_OUTPUT_BOOL(rc == GRN_SUCCESS); + + return NULL; +} + +static grn_obj * +proc_reindex(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *target_name; + grn_obj *target; + + target_name = VAR(0); + if (GRN_TEXT_LEN(target_name) == 0) { + target = grn_ctx_db(ctx); + } else { + target = grn_ctx_get(ctx, + GRN_TEXT_VALUE(target_name), + GRN_TEXT_LEN(target_name)); + if (!target) { + ERR(GRN_INVALID_ARGUMENT, + "[reindex] nonexistent target: <%.*s>", + (int)GRN_TEXT_LEN(target_name), + GRN_TEXT_VALUE(target_name)); + GRN_OUTPUT_BOOL(GRN_FALSE); + return NULL; + } + } + + grn_obj_reindex(ctx, target); + + GRN_OUTPUT_BOOL(ctx->rc == GRN_SUCCESS); + + return NULL; +} + +static grn_rc +selector_prefix_rk_search_key(grn_ctx *ctx, + grn_obj *table, + grn_obj *column, + grn_obj *query, + grn_obj *res, + grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + + if (!grn_obj_is_key_accessor(ctx, column)) { + grn_obj inspected_column; + GRN_TEXT_INIT(&inspected_column, 0); + grn_inspect(ctx, &inspected_column, column); + ERR(GRN_INVALID_ARGUMENT, + "prefix_rk_serach(): column must be _key: %.*s", + (int)GRN_TEXT_LEN(&inspected_column), + GRN_TEXT_VALUE(&inspected_column)); + rc = ctx->rc; + GRN_OBJ_FIN(ctx, &inspected_column); + goto exit; + } + + if (table->header.type != GRN_TABLE_PAT_KEY) { + grn_obj inspected_table; + GRN_TEXT_INIT(&inspected_table, 0); + grn_inspect(ctx, &inspected_table, table); + ERR(GRN_INVALID_ARGUMENT, + "prefix_rk_serach(): table of _key must TABLE_PAT_KEY: %.*s", + (int)GRN_TEXT_LEN(&inspected_table), + GRN_TEXT_VALUE(&inspected_table)); + rc = ctx->rc; + GRN_OBJ_FIN(ctx, &inspected_table); + goto exit; + } + + GRN_TABLE_EACH_BEGIN_MIN(ctx, + table, + cursor, + id, + GRN_TEXT_VALUE(query), + GRN_TEXT_LEN(query), + GRN_CURSOR_PREFIX | GRN_CURSOR_RK) { + grn_posting posting; + posting.rid = id; + posting.sid = 1; + posting.pos = 0; + posting.weight = 0; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } GRN_TABLE_EACH_END(ctx, cursor); + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + +exit : + return rc; +} + +static grn_rc +selector_prefix_rk_search_index(grn_ctx *ctx, + grn_obj *index, + grn_obj *query, + grn_obj *res, + grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *table; + + table = grn_column_table(ctx, index); + + GRN_TABLE_EACH_BEGIN_MIN(ctx, + table, + cursor, + id, + GRN_TEXT_VALUE(query), + GRN_TEXT_LEN(query), + GRN_CURSOR_PREFIX | GRN_CURSOR_RK) { + grn_ii_at(ctx, (grn_ii *)index, id, (grn_hash *)res, op); + } GRN_TABLE_EACH_END(ctx, cursor); + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + + return rc; +} + +static grn_rc +selector_prefix_rk_search(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + int nargs, + grn_obj **args, + grn_obj *res, + grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *column; + grn_obj *query; + + if ((nargs - 1) != 2) { + ERR(GRN_INVALID_ARGUMENT, + "prefix_rk_serach(): wrong number of arguments (%d for 2)", nargs - 1); + return ctx->rc; + } + + column = args[1]; + query = args[2]; + + if (index) { + rc = selector_prefix_rk_search_index(ctx, index, query, res, op); + } else if (grn_obj_is_accessor(ctx, column) && + ((grn_accessor *)column)->next) { + grn_obj *accessor = column; + unsigned int accessor_deep = 0; + grn_obj *base_table = NULL; + grn_obj *base_column = NULL; + grn_obj *base_index = NULL; + grn_obj *base_res = NULL; + grn_accessor *a; + + for (a = (grn_accessor *)accessor; a; a = a->next) { + if (a->next) { + accessor_deep++; + } else { + if (grn_obj_is_data_column(ctx, a->obj)) { + grn_operator selector_op; + grn_index_datum index_data; + unsigned int n_index_datum; + + selector_op = grn_proc_get_selector_operator(ctx, args[0]); + base_column = a->obj; + base_table = grn_column_table(ctx, a->obj); + n_index_datum = grn_column_find_index_data(ctx, + base_column, + selector_op, + &index_data, + 1); + if (n_index_datum > 0) { + base_index = index_data.index; + } + } else { + base_column = (grn_obj *)a; + base_table = a->obj; + } + base_res = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + base_table, NULL); + } + } + if (base_index) { + rc = selector_prefix_rk_search_index(ctx, + base_index, + query, + base_res, + GRN_OP_OR); + } else { + rc = selector_prefix_rk_search_key(ctx, + base_table, + base_column, + query, + base_res, + GRN_OP_OR); + } + if (rc == GRN_SUCCESS) { + grn_accessor_resolve(ctx, + accessor, + accessor_deep, + base_res, + res, + op); + } + grn_obj_close(ctx, base_res); + } else { + rc = selector_prefix_rk_search_key(ctx, + table, + column, + query, + res, + op); + } + return rc; +} + +#define DEF_VAR(v,name_str) do {\ + (v).name = (name_str);\ + (v).name_size = GRN_STRLEN(name_str);\ + GRN_TEXT_INIT(&(v).value, 0);\ +} while (0) + +#define DEF_COMMAND(name, func, nvars, vars)\ + (grn_proc_create(ctx, (name), (sizeof(name) - 1),\ + GRN_PROC_COMMAND, (func), NULL, NULL, (nvars), (vars))) + +void +grn_db_init_builtin_commands(grn_ctx *ctx) +{ + grn_expr_var vars[10]; + + grn_proc_init_define_selector(ctx); + grn_proc_init_select(ctx); + + DEF_VAR(vars[0], "values"); + DEF_VAR(vars[1], "table"); + DEF_VAR(vars[2], "columns"); + DEF_VAR(vars[3], "ifexists"); + DEF_VAR(vars[4], "input_type"); + DEF_VAR(vars[5], "each"); + DEF_VAR(vars[6], "output_ids"); + DEF_VAR(vars[7], "output_errors"); + DEF_COMMAND("load", proc_load, 8, vars); + + DEF_COMMAND("status", proc_status, 0, vars); + + grn_proc_init_table_list(ctx); + + grn_proc_init_column_list(ctx); + + grn_proc_init_table_create(ctx); + + grn_proc_init_table_remove(ctx); + + grn_proc_init_table_rename(ctx); + + grn_proc_init_column_create(ctx); + + grn_proc_init_column_remove(ctx); + + grn_proc_init_column_rename(ctx); + + DEF_VAR(vars[0], "path"); + DEF_COMMAND(GRN_EXPR_MISSING_NAME, proc_missing, 1, vars); + + DEF_COMMAND("quit", proc_quit, 0, vars); + + DEF_VAR(vars[0], "mode"); + DEF_COMMAND("shutdown", proc_shutdown, 1, vars); + + grn_proc_init_clearlock(ctx); + grn_proc_init_lock_clear(ctx); + + DEF_VAR(vars[0], "target_name"); + DEF_VAR(vars[1], "threshold"); + DEF_COMMAND("defrag", proc_defrag, 2, vars); + + DEF_VAR(vars[0], "level"); + DEF_COMMAND("log_level", proc_log_level, 1, vars); + + DEF_VAR(vars[0], "level"); + DEF_VAR(vars[1], "message"); + DEF_COMMAND("log_put", proc_log_put, 2, vars); + + DEF_COMMAND("log_reopen", proc_log_reopen, 0, vars); + + DEF_VAR(vars[0], "table"); + DEF_VAR(vars[1], "key"); + DEF_VAR(vars[2], "id"); + DEF_VAR(vars[3], "filter"); + DEF_COMMAND("delete", proc_delete, 4, vars); + + DEF_VAR(vars[0], "max"); + DEF_COMMAND("cache_limit", proc_cache_limit, 1, vars); + + grn_proc_init_dump(ctx); + + /* Deprecated. Use "plugin_register" instead. */ + DEF_VAR(vars[0], "path"); + DEF_COMMAND("register", proc_register, 1, vars); + + DEF_VAR(vars[0], "obj"); + DEF_COMMAND("check", proc_check, 1, vars); + + DEF_VAR(vars[0], "target_name"); + DEF_VAR(vars[1], "table"); + DEF_COMMAND("truncate", proc_truncate, 2, vars); + + DEF_VAR(vars[0], "normalizer"); + DEF_VAR(vars[1], "string"); + DEF_VAR(vars[2], "flags"); + DEF_COMMAND("normalize", proc_normalize, 3, vars); + + grn_proc_init_tokenize(ctx); + grn_proc_init_table_tokenize(ctx); + + DEF_COMMAND("tokenizer_list", proc_tokenizer_list, 0, vars); + + DEF_COMMAND("normalizer_list", proc_normalizer_list, 0, vars); + + { + grn_obj *proc; + proc = grn_proc_create(ctx, "rand", -1, GRN_PROC_FUNCTION, func_rand, + NULL, NULL, 0, NULL); + grn_proc_set_is_stable(ctx, proc, GRN_FALSE); + } + + { + grn_obj *proc; + proc = grn_proc_create(ctx, "now", -1, GRN_PROC_FUNCTION, func_now, + NULL, NULL, 0, NULL); + grn_proc_set_is_stable(ctx, proc, GRN_FALSE); + } + + grn_proc_create(ctx, "max", -1, GRN_PROC_FUNCTION, func_max, + NULL, NULL, 0, NULL); + grn_proc_create(ctx, "min", -1, GRN_PROC_FUNCTION, func_min, + NULL, NULL, 0, NULL); + + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "geo_in_circle", -1, GRN_PROC_FUNCTION, + func_geo_in_circle, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, grn_selector_geo_in_circle); + /* We may need GRN_OP_GEO_IN_CIRCLE. */ + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_MATCH); + + selector_proc = grn_proc_create(ctx, "geo_in_rectangle", -1, + GRN_PROC_FUNCTION, + func_geo_in_rectangle, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, grn_selector_geo_in_rectangle); + /* We may need GRN_OP_GEO_IN_RECTANGLE. */ + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_MATCH); + } + + grn_proc_create(ctx, "geo_distance", -1, GRN_PROC_FUNCTION, + func_geo_distance, NULL, NULL, 0, NULL); + + /* deprecated. */ + grn_proc_create(ctx, "geo_distance2", -1, GRN_PROC_FUNCTION, + func_geo_distance2, NULL, NULL, 0, NULL); + + /* deprecated. */ + grn_proc_create(ctx, "geo_distance3", -1, GRN_PROC_FUNCTION, + func_geo_distance3, NULL, NULL, 0, NULL); + + grn_proc_init_edit_distance(ctx); + + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "all_records", -1, GRN_PROC_FUNCTION, + func_all_records, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, selector_all_records); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_NOP); + } + + /* experimental */ + grn_proc_init_snippet_html(ctx); + + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "query", -1, GRN_PROC_FUNCTION, + func_query, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, selector_query); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_NOP); + } + + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "sub_filter", -1, GRN_PROC_FUNCTION, + NULL, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, selector_sub_filter); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_NOP); + } + + grn_proc_create(ctx, "html_untag", -1, GRN_PROC_FUNCTION, + func_html_untag, NULL, NULL, 0, NULL); + + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "between", -1, GRN_PROC_FUNCTION, + func_between, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, selector_between); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_LESS); + } + + grn_proc_init_highlight_html(ctx); + grn_proc_init_highlight_full(ctx); + + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "in_values", -1, GRN_PROC_FUNCTION, + func_in_values, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, selector_in_values); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_EQUAL); + } + + DEF_VAR(vars[0], "table"); + DEF_VAR(vars[1], "column"); + DEF_VAR(vars[2], "min"); + DEF_VAR(vars[3], "min_border"); + DEF_VAR(vars[4], "max"); + DEF_VAR(vars[5], "max_border"); + DEF_VAR(vars[6], "offset"); + DEF_VAR(vars[7], "limit"); + DEF_VAR(vars[8], "filter"); + DEF_VAR(vars[9], "output_columns"); + DEF_COMMAND("range_filter", proc_range_filter, 10, vars); + + DEF_VAR(vars[0], "id"); + DEF_COMMAND("request_cancel", proc_request_cancel, 1, vars); + + DEF_VAR(vars[0], "name"); + DEF_COMMAND("plugin_register", proc_plugin_register, 1, vars); + + DEF_VAR(vars[0], "name"); + DEF_COMMAND("plugin_unregister", proc_plugin_unregister, 1, vars); + + DEF_VAR(vars[0], "target_name"); + DEF_VAR(vars[1], "recursive"); + DEF_VAR(vars[2], "only_opened"); + DEF_COMMAND("io_flush", proc_io_flush, 3, vars); + + grn_proc_init_object_exist(ctx); + + DEF_VAR(vars[0], "max"); + DEF_COMMAND("thread_limit", proc_thread_limit, 1, vars); + + DEF_COMMAND("database_unmap", proc_database_unmap, 0, vars); + + grn_proc_init_column_copy(ctx); + + grn_proc_init_schema(ctx); + + DEF_VAR(vars[0], "target_name"); + DEF_COMMAND("reindex", proc_reindex, 1, vars); + + { + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "prefix_rk_search", -1, + GRN_PROC_FUNCTION, + NULL, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, selector_prefix_rk_search); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_PREFIX); + } + + grn_proc_init_config_get(ctx); + grn_proc_init_config_set(ctx); + grn_proc_init_config_delete(ctx); + + grn_proc_init_lock_acquire(ctx); + grn_proc_init_lock_release(ctx); + + grn_proc_init_object_inspect(ctx); + + grn_proc_init_fuzzy_search(ctx); + + grn_proc_init_object_remove(ctx); + + grn_proc_init_snippet(ctx); + grn_proc_init_highlight(ctx); + + grn_proc_init_query_expand(ctx); + + grn_proc_init_object_list(ctx); + + grn_proc_init_table_copy(ctx); + + grn_proc_init_in_records(ctx); + + grn_proc_init_query_log_flags_get(ctx); + grn_proc_init_query_log_flags_set(ctx); + grn_proc_init_query_log_flags_add(ctx); + grn_proc_init_query_log_flags_remove(ctx); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/Makefile.am b/storage/mroonga/vendor/groonga/lib/proc/Makefile.am new file mode 100644 index 00000000..e4284dc2 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/Makefile.am @@ -0,0 +1,17 @@ +AM_CPPFLAGS = \ + -I$(top_builddir) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib + +AM_CFLAGS = \ + $(NO_STRICT_ALIASING_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(GRN_CFLAGS) \ + $(MESSAGE_PACK_CFLAGS) \ + $(MRUBY_CFLAGS) + +noinst_LTLIBRARIES = libgrnproc.la + +include sources.am + +CLEANFILES = *.gcno *.gcda diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_column.c b/storage/mroonga/vendor/groonga/lib/proc/proc_column.c new file mode 100644 index 00000000..74d0d7a9 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_column.c @@ -0,0 +1,1019 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" + +#include "../grn_ctx.h" +#include "../grn_db.h" +#include "../grn_str.h" + +#include + +grn_column_flags +grn_proc_column_parse_flags(grn_ctx *ctx, + const char *error_message_tag, + const char *text, + const char *end) +{ + grn_column_flags flags = 0; + while (text < end) { + size_t name_size; + + if (*text == '|' || *text == ' ') { + text += 1; + continue; + } + +#define CHECK_FLAG(name) \ + name_size = strlen(#name); \ + if ((unsigned long) (end - text) >= (unsigned long) name_size && \ + memcmp(text, #name, name_size) == 0) { \ + flags |= GRN_OBJ_ ## name; \ + text += name_size; \ + continue; \ + } + + CHECK_FLAG(COLUMN_SCALAR); + CHECK_FLAG(COLUMN_VECTOR); + CHECK_FLAG(COLUMN_INDEX); + CHECK_FLAG(COMPRESS_ZLIB); + CHECK_FLAG(COMPRESS_LZ4); + CHECK_FLAG(COMPRESS_ZSTD); + CHECK_FLAG(WITH_SECTION); + CHECK_FLAG(WITH_WEIGHT); + CHECK_FLAG(WITH_POSITION); + CHECK_FLAG(RING_BUFFER); + CHECK_FLAG(INDEX_SMALL); + CHECK_FLAG(INDEX_MEDIUM); + +#undef CHECK_FLAG + + ERR(GRN_INVALID_ARGUMENT, + "%s unknown flag: <%.*s>", + error_message_tag, + (int)(end - text), text); + return 0; + } + return flags; +} + +static grn_rc +command_column_create_resolve_source_name(grn_ctx *ctx, + grn_obj *table, + const char *source_name, + int source_name_length, + grn_obj *source_ids) +{ + grn_obj *column; + + column = grn_obj_column(ctx, table, source_name, source_name_length); + if (!column) { + ERR(GRN_INVALID_ARGUMENT, + "[column][create] nonexistent source: <%.*s>", + source_name_length, source_name); + return ctx->rc; + } + + if (column->header.type == GRN_ACCESSOR) { + if (strncmp(source_name, "_key", source_name_length) == 0) { + grn_id source_id = grn_obj_id(ctx, table); + GRN_UINT32_PUT(ctx, source_ids, source_id); + } else { + ERR(GRN_INVALID_ARGUMENT, + "[column][create] pseudo column except <_key> is invalid: <%.*s>", + source_name_length, source_name); + } + } else { + grn_id source_id = grn_obj_id(ctx, column); + GRN_UINT32_PUT(ctx, source_ids, source_id); + } + grn_obj_unlink(ctx, column); + + return ctx->rc; +} + +static grn_rc +command_column_create_resolve_source_names(grn_ctx *ctx, + grn_obj *table, + grn_obj *source_names, + grn_obj *source_ids) +{ + int i, names_length; + int start, source_name_length; + const char *names; + + names = GRN_TEXT_VALUE(source_names); + start = 0; + source_name_length = 0; + names_length = GRN_TEXT_LEN(source_names); + for (i = 0; i < names_length; i++) { + switch (names[i]) { + case ' ' : + if (source_name_length == 0) { + start++; + } + break; + case ',' : + { + grn_rc rc; + const char *source_name = names + start; + rc = command_column_create_resolve_source_name(ctx, + table, + source_name, + source_name_length, + source_ids); + if (rc) { + return rc; + } + start = i + 1; + source_name_length = 0; + } + break; + default : + source_name_length++; + break; + } + } + + if (source_name_length > 0) { + grn_rc rc; + const char *source_name = names + start; + rc = command_column_create_resolve_source_name(ctx, + table, + source_name, + source_name_length, + source_ids); + if (rc) { + return rc; + } + } + + return GRN_SUCCESS; +} + +static grn_obj * +command_column_create(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_bool succeeded = GRN_TRUE; + grn_obj *table; + grn_obj *column; + grn_obj *table_raw; + grn_obj *name; + grn_obj *flags_raw; + grn_obj *type_raw; + grn_obj *source_raw; + grn_column_flags flags; + grn_obj *type = NULL; + + table_raw = grn_plugin_proc_get_var(ctx, user_data, "table", -1); + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + flags_raw = grn_plugin_proc_get_var(ctx, user_data, "flags", -1); + type_raw = grn_plugin_proc_get_var(ctx, user_data, "type", -1); + source_raw = grn_plugin_proc_get_var(ctx, user_data, "source", -1); + + table = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_raw), GRN_TEXT_LEN(table_raw)); + if (!table) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[column][create] table doesn't exist: <%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw)); + succeeded = GRN_FALSE; + goto exit; + } + + { + const char *rest; + flags = grn_atoi(GRN_TEXT_VALUE(flags_raw), + GRN_BULK_CURR(flags_raw), + &rest); + if (GRN_TEXT_VALUE(flags_raw) == rest) { + flags = grn_proc_column_parse_flags(ctx, + "[column][create][flags]", + GRN_TEXT_VALUE(flags_raw), + GRN_BULK_CURR(flags_raw)); + if (ctx->rc) { + succeeded = GRN_FALSE; + goto exit; + } + } + } + + type = grn_ctx_get(ctx, + GRN_TEXT_VALUE(type_raw), + GRN_TEXT_LEN(type_raw)); + if (!type) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[column][create] type doesn't exist: <%.*s>", + (int)GRN_TEXT_LEN(type_raw), + GRN_TEXT_VALUE(type_raw)); + succeeded = GRN_FALSE; + goto exit; + } + + if (GRN_TEXT_LEN(name) == 0) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[column][create] name is missing"); + succeeded = GRN_FALSE; + goto exit; + } + flags |= GRN_OBJ_PERSISTENT; + + column = grn_column_create(ctx, table, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name), + NULL, flags, type); + if (!column) { + succeeded = GRN_FALSE; + goto exit; + } + + if (GRN_TEXT_LEN(source_raw) > 0) { + grn_rc rc; + grn_obj source_ids; + GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); + rc = command_column_create_resolve_source_names(ctx, + type, + source_raw, + &source_ids); + if (rc == GRN_SUCCESS && GRN_BULK_VSIZE(&source_ids) > 0) { + grn_obj_set_info(ctx, column, GRN_INFO_SOURCE, &source_ids); + rc = ctx->rc; + } + GRN_OBJ_FIN(ctx, &source_ids); + if (rc != GRN_SUCCESS) { + grn_obj_remove(ctx, column); + succeeded = GRN_FALSE; + goto exit; + } + } + + grn_obj_unlink(ctx, column); + +exit : + grn_ctx_output_bool(ctx, succeeded); + if (table) { grn_obj_unlink(ctx, table); } + if (type) { grn_obj_unlink(ctx, type); } + + return NULL; +} + +void +grn_proc_init_column_create(grn_ctx *ctx) +{ + grn_expr_var vars[5]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "table", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "name", -1); + grn_plugin_expr_var_init(ctx, &(vars[2]), "flags", -1); + grn_plugin_expr_var_init(ctx, &(vars[3]), "type", -1); + grn_plugin_expr_var_init(ctx, &(vars[4]), "source", -1); + grn_plugin_command_create(ctx, + "column_create", -1, + command_column_create, + 5, + vars); +} + +static grn_obj * +command_column_remove(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *table_raw; + grn_obj *name; + grn_obj *table; + grn_obj *column; + char fullname[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int fullname_len; + + table_raw = grn_plugin_proc_get_var(ctx, user_data, "table", -1); + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + + table = grn_ctx_get(ctx, + GRN_TEXT_VALUE(table_raw), + GRN_TEXT_LEN(table_raw)); + + fullname_len = grn_obj_name(ctx, table, fullname, GRN_TABLE_MAX_KEY_SIZE); + if (fullname_len == 0) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[column][remove] table isn't found: <%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw)); + grn_ctx_output_bool(ctx, GRN_FALSE); + return NULL; + } + + fullname[fullname_len] = GRN_DB_DELIMITER; + fullname_len++; + if (fullname_len + GRN_TEXT_LEN(name) > GRN_TABLE_MAX_KEY_SIZE) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[column][remove] column name is too long: <%d> > <%u>: " + "<%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TABLE_MAX_KEY_SIZE - fullname_len, + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + grn_ctx_output_bool(ctx, GRN_FALSE); + return NULL; + } + grn_memcpy(fullname + fullname_len, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name)); + fullname_len += GRN_TEXT_LEN(name); + column = grn_ctx_get(ctx, fullname, fullname_len); + if (!column) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[column][remove] column isn't found: <%.*s%c%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw), + GRN_DB_DELIMITER, + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + grn_ctx_output_bool(ctx, GRN_FALSE); + return NULL; + } + + grn_obj_remove(ctx, column); + grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS); + return NULL; +} + +void +grn_proc_init_column_remove(grn_ctx *ctx) +{ + grn_expr_var vars[2]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "table", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "name", -1); + grn_plugin_command_create(ctx, + "column_remove", -1, + command_column_remove, + 2, + vars); +} + +static grn_obj * +command_column_rename(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *table_raw; + grn_obj *name; + grn_obj *new_name; + grn_obj *table = NULL; + grn_obj *column = NULL; + + table_raw = grn_plugin_proc_get_var(ctx, user_data, "table", -1); + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + new_name = grn_plugin_proc_get_var(ctx, user_data, "new_name", -1); + + if (GRN_TEXT_LEN(table_raw) == 0) { + rc = GRN_INVALID_ARGUMENT; + GRN_PLUGIN_ERROR(ctx, + rc, + "[column][rename] table name isn't specified"); + goto exit; + } + + table = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_raw), GRN_TEXT_LEN(table_raw)); + if (!table) { + rc = GRN_INVALID_ARGUMENT; + GRN_PLUGIN_ERROR(ctx, + rc, + "[column][rename] table isn't found: <%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw)); + goto exit; + } + + if (GRN_TEXT_LEN(name) == 0) { + rc = GRN_INVALID_ARGUMENT; + GRN_PLUGIN_ERROR(ctx, + rc, + "[column][rename] column name isn't specified: <%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw)); + goto exit; + } + + column = grn_obj_column(ctx, table, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name)); + if (!column) { + rc = GRN_INVALID_ARGUMENT; + GRN_PLUGIN_ERROR(ctx, + rc, + "[column][rename] column isn't found: <%.*s%c%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw), + GRN_DB_DELIMITER, + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + goto exit; + } + + if (GRN_TEXT_LEN(new_name) == 0) { + rc = GRN_INVALID_ARGUMENT; + GRN_PLUGIN_ERROR(ctx, + rc, + "[column][rename] new column name isn't specified: " + "<%.*s%c%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw), + GRN_DB_DELIMITER, + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + goto exit; + } + + rc = grn_column_rename(ctx, column, + GRN_TEXT_VALUE(new_name), + GRN_TEXT_LEN(new_name)); + if (rc != GRN_SUCCESS && ctx->rc == GRN_SUCCESS) { + GRN_PLUGIN_ERROR(ctx, + rc, + "[column][rename] failed to rename: " + "<%.*s%c%.*s> -> <%.*s%c%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw), + GRN_DB_DELIMITER, + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name), + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw), + GRN_DB_DELIMITER, + (int)GRN_TEXT_LEN(new_name), + GRN_TEXT_VALUE(new_name)); + goto exit; + } + +exit : + grn_ctx_output_bool(ctx, rc == GRN_SUCCESS); + if (column) { grn_obj_unlink(ctx, column); } + if (table) { grn_obj_unlink(ctx, table); } + return NULL; +} + +void +grn_proc_init_column_rename(grn_ctx *ctx) +{ + grn_expr_var vars[3]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "table", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "name", -1); + grn_plugin_expr_var_init(ctx, &(vars[2]), "new_name", -1); + grn_plugin_command_create(ctx, + "column_rename", -1, + command_column_rename, + 3, + vars); +} + +static void +output_column_name(grn_ctx *ctx, grn_obj *column) +{ + grn_obj bulk; + int name_len; + char name[GRN_TABLE_MAX_KEY_SIZE]; + + GRN_TEXT_INIT(&bulk, GRN_OBJ_DO_SHALLOW_COPY); + name_len = grn_column_name(ctx, column, name, GRN_TABLE_MAX_KEY_SIZE); + GRN_TEXT_SET(ctx, &bulk, name, name_len); + + grn_ctx_output_obj(ctx, &bulk, NULL); + GRN_OBJ_FIN(ctx, &bulk); +} + +static int +output_column_info(grn_ctx *ctx, grn_obj *column) +{ + grn_obj o; + grn_id id; + const char *type; + const char *path; + + switch (column->header.type) { + case GRN_COLUMN_FIX_SIZE: + type = "fix"; + break; + case GRN_COLUMN_VAR_SIZE: + type = "var"; + break; + case GRN_COLUMN_INDEX: + type = "index"; + break; + default: + GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid header type %d\n", column->header.type); + return 0; + } + id = grn_obj_id(ctx, column); + path = grn_obj_path(ctx, column); + GRN_TEXT_INIT(&o, 0); + grn_ctx_output_array_open(ctx, "COLUMN", 8); + grn_ctx_output_int64(ctx, id); + output_column_name(ctx, column); + grn_ctx_output_cstr(ctx, path); + grn_ctx_output_cstr(ctx, type); + grn_dump_column_create_flags(ctx, grn_column_get_flags(ctx, column), &o); + grn_ctx_output_obj(ctx, &o, NULL); + grn_proc_output_object_id_name(ctx, column->header.domain); + grn_proc_output_object_id_name(ctx, grn_obj_get_range(ctx, column)); + { + grn_db_obj *obj = (grn_db_obj *)column; + grn_id *s = obj->source; + int i = 0, n = obj->source_size / sizeof(grn_id); + grn_ctx_output_array_open(ctx, "SOURCES", n); + for (i = 0; i < n; i++, s++) { + grn_proc_output_object_id_name(ctx, *s); + } + grn_ctx_output_array_close(ctx); + + } + /* output_obj_source(ctx, (grn_db_obj *)column); */ + grn_ctx_output_array_close(ctx); + GRN_OBJ_FIN(ctx, &o); + return 1; +} + +static grn_obj * +command_column_list(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *table_raw; + grn_obj *table; + grn_hash *cols; + grn_obj *col; + int column_list_size = -1; + + table_raw = grn_plugin_proc_get_var(ctx, user_data, "table", -1); + + table = grn_ctx_get(ctx, + GRN_TEXT_VALUE(table_raw), + GRN_TEXT_LEN(table_raw)); + if (!table) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[column][list] table doesn't exist: <%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw)); + return NULL; + } + + if (!grn_obj_is_table(ctx, table)) { + const char *type_name; + type_name = grn_obj_type_to_string(table->header.type); + grn_obj_unlink(ctx, table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[column][list] not table: <%.*s>: <%s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw), + type_name); + return NULL; + } + + column_list_size = 1; /* [header, (key), (COLUMNS)] */ + if (table->header.type != GRN_TABLE_NO_KEY) { + column_list_size++; + } + cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); + if (!cols) { + grn_obj_unlink(ctx, table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[column][list] " + "failed to create temporary table to list columns: <%.*s>", + (int)GRN_TEXT_LEN(table_raw), + GRN_TEXT_VALUE(table_raw)); + return NULL; + } + + column_list_size += grn_table_columns(ctx, table, NULL, 0, (grn_obj *)cols); + + grn_ctx_output_array_open(ctx, "COLUMN_LIST", column_list_size); + grn_ctx_output_array_open(ctx, "HEADER", 8); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_cstr(ctx, "UInt32"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "path"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "type"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "flags"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "domain"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "range"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "source"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_close(ctx); + + if ((col = grn_obj_column(ctx, table, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN))) { + int name_len; + char name_buf[GRN_TABLE_MAX_KEY_SIZE]; + grn_id id; + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + grn_ctx_output_array_open(ctx, "COLUMN", 8); + id = grn_obj_id(ctx, table); + grn_ctx_output_int64(ctx, id); + grn_ctx_output_cstr(ctx, GRN_COLUMN_NAME_KEY); + grn_ctx_output_cstr(ctx, ""); + grn_ctx_output_cstr(ctx, ""); + grn_dump_column_create_flags(ctx, 0, &buf); + grn_ctx_output_obj(ctx, &buf, NULL); + name_len = grn_obj_name(ctx, table, name_buf, GRN_TABLE_MAX_KEY_SIZE); + grn_ctx_output_str(ctx, name_buf, name_len); + grn_proc_output_object_id_name(ctx, table->header.domain); + grn_ctx_output_array_open(ctx, "SOURCES", 0); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_close(ctx); + GRN_OBJ_FIN(ctx, &buf); + grn_obj_unlink(ctx, col); + } + { + grn_id *key; + GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { + if ((col = grn_ctx_at(ctx, *key))) { + output_column_info(ctx, col); + grn_obj_unlink(ctx, col); + } + }); + } + grn_ctx_output_array_close(ctx); + grn_hash_close(ctx, cols); + grn_obj_unlink(ctx, table); + + return NULL; +} + +void +grn_proc_init_column_list(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "table", -1); + grn_plugin_command_create(ctx, + "column_list", -1, + command_column_list, + 1, + vars); +} + +static grn_rc +command_column_copy_resolve_target(grn_ctx *ctx, + const char *label, + grn_obj *table_name, + grn_obj *column_name, + grn_obj **table, + grn_obj **column) +{ + if (GRN_TEXT_LEN(table_name) == 0) { + ERR(GRN_INVALID_ARGUMENT, + "[column][copy] %s table name isn't specified", + label); + return ctx->rc; + } + *table = grn_ctx_get(ctx, + GRN_TEXT_VALUE(table_name), + GRN_TEXT_LEN(table_name)); + if (!*table) { + ERR(GRN_INVALID_ARGUMENT, + "[column][copy] %s table isn't found: <%.*s>", + label, + (int)GRN_TEXT_LEN(table_name), + GRN_TEXT_VALUE(table_name)); + return ctx->rc; + } + + if (GRN_TEXT_LEN(column_name) == 0) { + ERR(GRN_INVALID_ARGUMENT, + "[column][copy] %s column name isn't specified: <%.*s>", + label, + (int)GRN_TEXT_LEN(table_name), + GRN_TEXT_VALUE(table_name)); + return ctx->rc; + } + *column = grn_obj_column(ctx, *table, + GRN_TEXT_VALUE(column_name), + GRN_TEXT_LEN(column_name)); + if (!*column) { + ERR(GRN_INVALID_ARGUMENT, + "[column][copy] %s column isn't found: <%.*s.%.*s>", + label, + (int)GRN_TEXT_LEN(table_name), GRN_TEXT_VALUE(table_name), + (int)GRN_TEXT_LEN(column_name), GRN_TEXT_VALUE(column_name)); + return ctx->rc; + } + + return ctx->rc; +} + +static void +command_column_copy_same_table(grn_ctx *ctx, grn_obj *table, + grn_obj *from_column, grn_obj *to_column) +{ + grn_table_cursor *cursor; + grn_id id; + grn_obj value; + + cursor = grn_table_cursor_open(ctx, table, + NULL, 0, + NULL, 0, + 0, -1, 0); + if (!cursor) { + return; + } + + GRN_VOID_INIT(&value); + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + GRN_BULK_REWIND(&value); + grn_obj_get_value(ctx, from_column, id, &value); + grn_obj_set_value(ctx, to_column, id, &value, GRN_OBJ_SET); + } + GRN_OBJ_FIN(ctx, &value); + grn_table_cursor_close(ctx, cursor); +} + +static void +command_column_copy_same_key_type(grn_ctx *ctx, + grn_obj *from_table, + grn_obj *from_column, + grn_obj *to_table, + grn_obj *to_column) +{ + grn_table_cursor *cursor; + grn_id from_id; + grn_obj value; + + cursor = grn_table_cursor_open(ctx, from_table, + NULL, 0, + NULL, 0, + 0, -1, 0); + if (!cursor) { + return; + } + + GRN_VOID_INIT(&value); + while ((from_id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + void *key; + int key_size; + grn_id to_id; + + key_size = grn_table_cursor_get_key(ctx, cursor, &key); + to_id = grn_table_add(ctx, to_table, key, key_size, NULL); + if (to_id == GRN_ID_NIL) { + continue; + } + + GRN_BULK_REWIND(&value); + grn_obj_get_value(ctx, from_column, from_id, &value); + grn_obj_set_value(ctx, to_column, to_id, &value, GRN_OBJ_SET); + } + GRN_OBJ_FIN(ctx, &value); + grn_table_cursor_close(ctx, cursor); +} + +static void +command_column_copy_different(grn_ctx *ctx, + grn_obj *from_table, + grn_obj *from_column, + grn_obj *to_table, + grn_obj *to_column, + grn_obj *from_table_name, + grn_obj *from_column_name, + grn_obj *to_table_name, + grn_obj *to_column_name) +{ + grn_table_cursor *cursor; + grn_id from_id; + grn_obj from_key_buffer; + grn_obj to_key_buffer; + grn_obj value; + + cursor = grn_table_cursor_open(ctx, from_table, + NULL, 0, + NULL, 0, + 0, -1, 0); + if (!cursor) { + return; + } + + if (from_table->header.domain == GRN_DB_SHORT_TEXT) { + GRN_SHORT_TEXT_INIT(&from_key_buffer, 0); + } else { + GRN_VALUE_FIX_SIZE_INIT(&from_key_buffer, 0, from_table->header.domain); + } + if (to_table->header.domain == GRN_DB_SHORT_TEXT) { + GRN_SHORT_TEXT_INIT(&to_key_buffer, 0); + } else { + GRN_VALUE_FIX_SIZE_INIT(&to_key_buffer, 0, to_table->header.domain); + } + GRN_VOID_INIT(&value); + while ((from_id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + void *key; + int key_size; + grn_rc cast_rc; + grn_id to_id; + + GRN_BULK_REWIND(&from_key_buffer); + GRN_BULK_REWIND(&to_key_buffer); + + key_size = grn_table_cursor_get_key(ctx, cursor, &key); + grn_bulk_write(ctx, &from_key_buffer, key, key_size); + cast_rc = grn_obj_cast(ctx, &from_key_buffer, &to_key_buffer, GRN_FALSE); + if (cast_rc != GRN_SUCCESS) { + grn_obj *to_key_type; + grn_obj inspected_key; + grn_obj inspected_to_key_type; + + to_key_type = grn_ctx_at(ctx, to_table->header.domain); + GRN_TEXT_INIT(&inspected_key, 0); + GRN_TEXT_INIT(&inspected_to_key_type, 0); + grn_inspect(ctx, &inspected_key, &from_key_buffer); + grn_inspect(ctx, &inspected_to_key_type, to_key_type); + ERR(cast_rc, + "[column][copy] failed to cast key: <%.*s> -> %.*s: " + "<%.*s.%.*s> -> <%.*s.%.*s>", + (int)GRN_TEXT_LEN(&inspected_key), + GRN_TEXT_VALUE(&inspected_key), + (int)GRN_TEXT_LEN(&inspected_to_key_type), + GRN_TEXT_VALUE(&inspected_to_key_type), + (int)GRN_TEXT_LEN(from_table_name), + GRN_TEXT_VALUE(from_table_name), + (int)GRN_TEXT_LEN(from_column_name), + GRN_TEXT_VALUE(from_column_name), + (int)GRN_TEXT_LEN(to_table_name), + GRN_TEXT_VALUE(to_table_name), + (int)GRN_TEXT_LEN(to_column_name), + GRN_TEXT_VALUE(to_column_name)); + GRN_OBJ_FIN(ctx, &inspected_key); + GRN_OBJ_FIN(ctx, &inspected_to_key_type); + break; + } + to_id = grn_table_add(ctx, to_table, + GRN_BULK_HEAD(&to_key_buffer), + GRN_BULK_VSIZE(&to_key_buffer), + NULL); + if (to_id == GRN_ID_NIL) { + continue; + } + + GRN_BULK_REWIND(&value); + grn_obj_get_value(ctx, from_column, from_id, &value); + grn_obj_set_value(ctx, to_column, to_id, &value, GRN_OBJ_SET); + } + GRN_OBJ_FIN(ctx, &from_key_buffer); + GRN_OBJ_FIN(ctx, &to_key_buffer); + GRN_OBJ_FIN(ctx, &value); + + grn_table_cursor_close(ctx, cursor); +} + +static grn_obj * +command_column_copy(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *from_table = NULL; + grn_obj *from_column = NULL; + grn_obj *to_table = NULL; + grn_obj *to_column = NULL; + grn_obj *from_table_name; + grn_obj *from_column_name; + grn_obj *to_table_name; + grn_obj *to_column_name; + + from_table_name = grn_plugin_proc_get_var(ctx, user_data, "from_table", -1); + from_column_name = grn_plugin_proc_get_var(ctx, user_data, "from_name", -1); + to_table_name = grn_plugin_proc_get_var(ctx, user_data, "to_table", -1); + to_column_name = grn_plugin_proc_get_var(ctx, user_data, "to_name", -1); + + rc = command_column_copy_resolve_target(ctx, "from", + from_table_name, from_column_name, + &from_table, &from_column); + if (rc != GRN_SUCCESS) { + goto exit; + } + rc = command_column_copy_resolve_target(ctx, "to", + to_table_name, to_column_name, + &to_table, &to_column); + if (rc != GRN_SUCCESS) { + goto exit; + } + + if ((from_table->header.type == GRN_TABLE_NO_KEY || + to_table->header.type == GRN_TABLE_NO_KEY) && + from_table != to_table) { + rc = GRN_OPERATION_NOT_SUPPORTED; + GRN_PLUGIN_ERROR(ctx, + rc, + "[column][copy] copy from/to TABLE_NO_KEY isn't supported: " + "<%.*s%c%.*s> -> <%.*s%c%.*s>", + (int)GRN_TEXT_LEN(from_table_name), + GRN_TEXT_VALUE(from_table_name), + GRN_DB_DELIMITER, + (int)GRN_TEXT_LEN(from_column_name), + GRN_TEXT_VALUE(from_column_name), + (int)GRN_TEXT_LEN(to_table_name), + GRN_TEXT_VALUE(to_table_name), + GRN_DB_DELIMITER, + (int)GRN_TEXT_LEN(to_column_name), + GRN_TEXT_VALUE(to_column_name)); + goto exit; + } + + if (from_table == to_table) { + command_column_copy_same_table(ctx, from_table, from_column, to_column); + } else if (from_table->header.domain == to_table->header.domain) { + command_column_copy_same_key_type(ctx, + from_table, from_column, + to_table, to_column); + } else { + command_column_copy_different(ctx, + from_table, + from_column, + to_table, + to_column, + from_table_name, + from_column_name, + to_table_name, + to_column_name); + } + +exit : + grn_ctx_output_bool(ctx, rc == GRN_SUCCESS); + + if (to_column) { + grn_obj_unlink(ctx, to_column); + } + if (to_table) { + grn_obj_unlink(ctx, to_table); + } + if (from_column) { + grn_obj_unlink(ctx, from_column); + } + if (from_table) { + grn_obj_unlink(ctx, from_table); + } + + return NULL; +} + +void +grn_proc_init_column_copy(grn_ctx *ctx) +{ + grn_expr_var vars[4]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "from_table", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "from_name", -1); + grn_plugin_expr_var_init(ctx, &(vars[2]), "to_table", -1); + grn_plugin_expr_var_init(ctx, &(vars[3]), "to_name", -1); + grn_plugin_command_create(ctx, + "column_copy", -1, + command_column_copy, + 4, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_config.c b/storage/mroonga/vendor/groonga/lib/proc/proc_config.c new file mode 100644 index 00000000..61a1c5a8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_config.c @@ -0,0 +1,139 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" + +#include + +static grn_obj * +command_config_get(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *key; + const char *value; + uint32_t value_size; + + key = grn_plugin_proc_get_var(ctx, user_data, "key", -1); + if (GRN_TEXT_LEN(key) == 0) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[config][get] key is missing"); + return NULL; + } + + grn_config_get(ctx, + GRN_TEXT_VALUE(key), GRN_TEXT_LEN(key), + &value, &value_size); + if (ctx->rc) { + return NULL; + } + + grn_ctx_output_str(ctx, value, value_size); + + return NULL; +} + +static grn_obj * +command_config_set(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *key; + grn_obj *value; + + key = grn_plugin_proc_get_var(ctx, user_data, "key", -1); + if (GRN_TEXT_LEN(key) == 0) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[config][set] key is missing"); + return NULL; + } + + value = grn_plugin_proc_get_var(ctx, user_data, "value", -1); + grn_config_set(ctx, + GRN_TEXT_VALUE(key), GRN_TEXT_LEN(key), + GRN_TEXT_VALUE(value), GRN_TEXT_LEN(value)); + + grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS); + + return NULL; +} + +static grn_obj * +command_config_delete(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *key; + + key = grn_plugin_proc_get_var(ctx, user_data, "key", -1); + if (GRN_TEXT_LEN(key) == 0) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[config][delete] key is missing"); + return NULL; + } + + grn_config_delete(ctx, + GRN_TEXT_VALUE(key), GRN_TEXT_LEN(key)); + + grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS); + + return NULL; +} + +void +grn_proc_init_config_get(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "key", -1); + grn_plugin_command_create(ctx, + "config_get", -1, + command_config_get, + 1, + vars); +} + +void +grn_proc_init_config_set(grn_ctx *ctx) +{ + grn_expr_var vars[2]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "key", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "value", -1); + grn_plugin_command_create(ctx, + "config_set", -1, + command_config_set, + 2, + vars); +} + +void +grn_proc_init_config_delete(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "key", -1); + grn_plugin_command_create(ctx, + "config_delete", -1, + command_config_delete, + 1, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_dump.c b/storage/mroonga/vendor/groonga/lib/proc/proc_dump.c new file mode 100644 index 00000000..391925d8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_dump.c @@ -0,0 +1,1138 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" +#include "../grn_ctx_impl.h" +#include "../grn_db.h" +#include "../grn_str.h" + +#include + +static const size_t DUMP_FLUSH_THRESHOLD_SIZE = 256 * 1024; + +typedef struct { + grn_obj *output; + grn_bool is_close_opened_object_mode; + grn_bool have_reference_column; + grn_bool have_index_column; + grn_bool is_sort_hash_table; + grn_obj column_name_buffer; +} grn_dumper; + +static void +dumper_collect_statistics_table(grn_ctx *ctx, + grn_dumper *dumper, + grn_obj *table) +{ + grn_hash *columns; + + columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); + if (!columns) { + return; + } + + grn_table_columns(ctx, table, NULL, 0, (grn_obj *)columns); + GRN_HASH_EACH_BEGIN(ctx, columns, cursor, id) { + void *key; + grn_id column_id; + grn_obj *column; + + grn_hash_cursor_get_key(ctx, cursor, &key); + column_id = *((grn_id *)key); + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + column = grn_ctx_at(ctx, column_id); + if (!column) { + GRN_PLUGIN_CLEAR_ERROR(ctx); + goto next_loop; + } + + if (grn_obj_is_index_column(ctx, column)) { + dumper->have_index_column = GRN_TRUE; + } else if (grn_obj_is_reference_column(ctx, column)) { + dumper->have_reference_column = GRN_TRUE; + } + + next_loop : + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_HASH_EACH_END(ctx, cursor); + grn_hash_close(ctx, columns); +} + +static void +dumper_collect_statistics(grn_ctx *ctx, grn_dumper *dumper) +{ + GRN_DB_EACH_BEGIN_BY_ID(ctx, cursor, id) { + void *name; + int name_size; + grn_obj *object; + + if (grn_id_is_builtin(ctx, id)) { + continue; + } + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + object = grn_ctx_at(ctx, id); + if (!object) { + /* XXX: this clause is executed when MeCab tokenizer is enabled in + database but the groonga isn't supported MeCab. + We should return error mesage about it and error exit status + but it's too difficult for this architecture. :< */ + GRN_PLUGIN_CLEAR_ERROR(ctx); + goto next_loop; + } + + if (!grn_obj_is_table(ctx, object)) { + goto next_loop; + } + + dumper_collect_statistics_table(ctx, dumper, object); + +next_loop : + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_DB_EACH_END(ctx, cursor); +} + +static void +dump_value_raw(grn_ctx *ctx, grn_obj *output, const char *value, int value_len) +{ + grn_obj escaped_value; + GRN_TEXT_INIT(&escaped_value, 0); + grn_text_esc(ctx, &escaped_value, value, value_len); + /* is no character escaped? */ + /* TODO false positive with spaces inside values */ + if (GRN_TEXT_LEN(&escaped_value) == value_len + 2) { + GRN_TEXT_PUT(ctx, output, value, value_len); + } else { + GRN_TEXT_PUT(ctx, output, + GRN_TEXT_VALUE(&escaped_value), GRN_TEXT_LEN(&escaped_value)); + } + grn_obj_close(ctx, &escaped_value); +} + +static void +dump_value(grn_ctx *ctx, grn_dumper *dumper, const char *value, int value_len) +{ + dump_value_raw(ctx, dumper->output, value, value_len); +} + +static void +dump_configs(grn_ctx *ctx, grn_dumper *dumper) +{ + grn_obj *config_cursor; + + config_cursor = grn_config_cursor_open(ctx); + if (!config_cursor) + return; + + while (grn_config_cursor_next(ctx, config_cursor)) { + const char *key; + uint32_t key_size; + const char *value; + uint32_t value_size; + + key_size = grn_config_cursor_get_key(ctx, config_cursor, &key); + value_size = grn_config_cursor_get_value(ctx, config_cursor, &value); + + GRN_TEXT_PUTS(ctx, dumper->output, "config_set "); + dump_value(ctx, dumper, key, key_size); + GRN_TEXT_PUTS(ctx, dumper->output, " "); + dump_value(ctx, dumper, value, value_size); + GRN_TEXT_PUTC(ctx, dumper->output, '\n'); + } + grn_obj_close(ctx, config_cursor); +} + +static void +dump_plugins(grn_ctx *ctx, grn_dumper *dumper) +{ + grn_obj plugin_names; + unsigned int i, n; + + GRN_TEXT_INIT(&plugin_names, GRN_OBJ_VECTOR); + + grn_plugin_get_names(ctx, &plugin_names); + + n = grn_vector_size(ctx, &plugin_names); + if (n == 0) { + GRN_OBJ_FIN(ctx, &plugin_names); + return; + } + + if (GRN_TEXT_LEN(dumper->output) > 0) { + GRN_TEXT_PUTC(ctx, dumper->output, '\n'); + grn_ctx_output_flush(ctx, 0); + } + for (i = 0; i < n; i++) { + const char *name; + unsigned int name_size; + + name_size = grn_vector_get_element(ctx, &plugin_names, i, &name, NULL, NULL); + grn_text_printf(ctx, dumper->output, "plugin_register %.*s\n", + (int)name_size, name); + } + + GRN_OBJ_FIN(ctx, &plugin_names); +} + +static void +dump_obj_name_raw(grn_ctx *ctx, grn_obj *output, grn_obj *obj) +{ + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_len; + name_len = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE); + dump_value_raw(ctx, output, name, name_len); +} + +static void +dump_obj_name(grn_ctx *ctx, grn_dumper *dumper, grn_obj *obj) +{ + dump_obj_name_raw(ctx, dumper->output, obj); +} + +static void +dump_column_name(grn_ctx *ctx, grn_dumper *dumper, grn_obj *column) +{ + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_len; + name_len = grn_column_name(ctx, column, name, GRN_TABLE_MAX_KEY_SIZE); + dump_value(ctx, dumper, name, name_len); +} + +static void +dump_index_column_sources(grn_ctx *ctx, grn_dumper *dumper, grn_obj *column) +{ + grn_obj sources; + grn_id *source_ids; + int i, n; + + GRN_OBJ_INIT(&sources, GRN_BULK, 0, GRN_ID_NIL); + grn_obj_get_info(ctx, column, GRN_INFO_SOURCE, &sources); + + n = GRN_BULK_VSIZE(&sources) / sizeof(grn_id); + source_ids = (grn_id *)GRN_BULK_HEAD(&sources); + if (n > 0) { + GRN_TEXT_PUTC(ctx, dumper->output, ' '); + } + for (i = 0; i < n; i++) { + grn_id source_id; + grn_obj *source; + + source_id = *source_ids; + source_ids++; + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + source = grn_ctx_at(ctx, source_id); + if (!source) { + goto next_loop; + } + + if (i) { GRN_TEXT_PUTC(ctx, dumper->output, ','); } + switch (source->header.type) { + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: + case GRN_TABLE_HASH_KEY: + GRN_TEXT_PUT(ctx, + dumper->output, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + break; + default: + dump_column_name(ctx, dumper, source); + break; + } + + next_loop : + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } + grn_obj_close(ctx, &sources); +} + +static void +dump_column(grn_ctx *ctx, grn_dumper *dumper, grn_obj *table, grn_obj *column) +{ + grn_id type_id; + grn_obj *type; + grn_column_flags flags; + grn_column_flags default_flags = GRN_OBJ_PERSISTENT; + + type_id = grn_obj_get_range(ctx, column); + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + type = grn_ctx_at(ctx, type_id); + if (!type) { + /* ERR(GRN_RANGE_ERROR, "couldn't get column's type object"); */ + goto exit; + } + + GRN_TEXT_PUTS(ctx, dumper->output, "column_create "); + dump_obj_name(ctx, dumper, table); + GRN_TEXT_PUTC(ctx, dumper->output, ' '); + dump_column_name(ctx, dumper, column); + GRN_TEXT_PUTC(ctx, dumper->output, ' '); + if (type->header.type == GRN_TYPE) { + default_flags |= type->header.flags; + } + flags = grn_column_get_flags(ctx, column); + grn_dump_column_create_flags(ctx, + flags & ~default_flags, + dumper->output); + GRN_TEXT_PUTC(ctx, dumper->output, ' '); + dump_obj_name(ctx, dumper, type); + if (column->header.flags & GRN_OBJ_COLUMN_INDEX) { + dump_index_column_sources(ctx, dumper, column); + } + GRN_TEXT_PUTC(ctx, dumper->output, '\n'); + +exit : + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } +} + +static void +dump_columns(grn_ctx *ctx, grn_dumper *dumper, grn_obj *table, + grn_bool dump_data_column, + grn_bool dump_reference_column, + grn_bool dump_index_column) +{ + grn_hash *columns; + columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); + if (!columns) { + GRN_PLUGIN_ERROR(ctx, + GRN_NO_MEMORY_AVAILABLE, + "couldn't create a hash to hold columns"); + return; + } + + if (grn_table_columns(ctx, table, NULL, 0, (grn_obj *)columns) >= 0) { + GRN_HASH_EACH_BEGIN(ctx, columns, cursor, id) { + void *key; + grn_id column_id; + grn_obj *column; + + grn_hash_cursor_get_key(ctx, cursor, &key); + column_id = *((grn_id *)key); + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + column = grn_ctx_at(ctx, column_id); + if (!column) { + GRN_PLUGIN_CLEAR_ERROR(ctx); + goto next_loop; + } + + if (grn_obj_is_index_column(ctx, column)) { + if (dump_index_column) { + dump_column(ctx, dumper, table, column); + GRN_PLUGIN_CLEAR_ERROR(ctx); + } + } else if (grn_obj_is_reference_column(ctx, column)) { + if (dump_reference_column) { + dump_column(ctx, dumper, table, column); + GRN_PLUGIN_CLEAR_ERROR(ctx); + } + } else { + if (dump_data_column) { + dump_column(ctx, dumper, table, column); + GRN_PLUGIN_CLEAR_ERROR(ctx); + } + } + + next_loop : + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_HASH_EACH_END(ctx, cursor); + } + grn_hash_close(ctx, columns); +} + +static void +dump_record_column_vector(grn_ctx *ctx, grn_dumper *dumper, grn_id id, + grn_obj *column, grn_id range_id, grn_obj *buf) +{ + grn_obj *range; + grn_obj_format *format_argument = NULL; + grn_obj_format format; + + range = grn_ctx_at(ctx, range_id); + if (column->header.flags & GRN_OBJ_WITH_WEIGHT) { + format.flags = GRN_OBJ_FORMAT_WITH_WEIGHT; + format_argument = &format; + } + + if (grn_obj_is_table(ctx, range) || + (range->header.flags & GRN_OBJ_KEY_VAR_SIZE) == 0) { + GRN_OBJ_INIT(buf, GRN_UVECTOR, 0, range_id); + grn_obj_get_value(ctx, column, id, buf); + grn_text_otoj(ctx, dumper->output, buf, format_argument); + } else { + GRN_OBJ_INIT(buf, GRN_VECTOR, 0, range_id); + grn_obj_get_value(ctx, column, id, buf); + grn_text_otoj(ctx, dumper->output, buf, format_argument); + } + + grn_obj_unlink(ctx, range); + grn_obj_unlink(ctx, buf); +} + +static void +dump_record(grn_ctx *ctx, grn_dumper *dumper, + grn_obj *table, + grn_id id, + grn_obj *columns, int n_columns) +{ + int j; + grn_obj buf; + grn_obj *column_name = &(dumper->column_name_buffer); + + GRN_TEXT_PUTC(ctx, dumper->output, '['); + for (j = 0; j < n_columns; j++) { + grn_bool is_value_column; + grn_id range; + grn_obj *column; + column = GRN_PTR_VALUE_AT(columns, j); + /* TODO: use grn_obj_is_value_accessor() */ + GRN_BULK_REWIND(column_name); + grn_column_name_(ctx, column, column_name); + if (GRN_TEXT_LEN(column_name) == GRN_COLUMN_NAME_VALUE_LEN && + !memcmp(GRN_TEXT_VALUE(column_name), + GRN_COLUMN_NAME_VALUE, + GRN_COLUMN_NAME_VALUE_LEN)) { + is_value_column = GRN_TRUE; + } else { + is_value_column = GRN_FALSE; + } + range = grn_obj_get_range(ctx, column); + + if (j) { GRN_TEXT_PUTC(ctx, dumper->output, ','); } + switch (column->header.type) { + case GRN_COLUMN_VAR_SIZE: + case GRN_COLUMN_FIX_SIZE: + switch (column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { + case GRN_OBJ_COLUMN_VECTOR: + dump_record_column_vector(ctx, dumper, id, column, range, &buf); + break; + case GRN_OBJ_COLUMN_SCALAR: + { + GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); + grn_obj_get_value(ctx, column, id, &buf); + grn_text_otoj(ctx, dumper->output, &buf, NULL); + grn_obj_unlink(ctx, &buf); + } + break; + default: + GRN_PLUGIN_ERROR(ctx, + GRN_OPERATION_NOT_SUPPORTED, + "unsupported column type: %#x", + column->header.type); + break; + } + break; + case GRN_COLUMN_INDEX: + break; + case GRN_ACCESSOR: + { + GRN_OBJ_INIT(&buf, GRN_BULK, 0, range); + grn_obj_get_value(ctx, column, id, &buf); + /* XXX maybe, grn_obj_get_range() should not unconditionally return + GRN_DB_INT32 when column is GRN_ACCESSOR and + GRN_ACCESSOR_GET_VALUE */ + if (is_value_column) { + buf.header.domain = grn_obj_get_range(ctx, table); + } + grn_text_otoj(ctx, dumper->output, &buf, NULL); + grn_obj_unlink(ctx, &buf); + } + break; + default: + GRN_PLUGIN_ERROR(ctx, + GRN_OPERATION_NOT_SUPPORTED, + "unsupported header type %#x", + column->header.type); + break; + } + } + GRN_TEXT_PUTC(ctx, dumper->output, ']'); + if ((size_t) GRN_TEXT_LEN(dumper->output) >= DUMP_FLUSH_THRESHOLD_SIZE) { + grn_ctx_output_flush(ctx, 0); + } +} + +static void +dump_records(grn_ctx *ctx, grn_dumper *dumper, grn_obj *table) +{ + grn_table_cursor *cursor; + int i, n_columns; + grn_obj columns; + grn_bool have_index_column = GRN_FALSE; + grn_bool have_data_column = GRN_FALSE; + + if (grn_table_size(ctx, table) == 0) { + return; + } + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + GRN_PTR_INIT(&columns, GRN_OBJ_VECTOR, GRN_ID_NIL); + + if (table->header.type == GRN_TABLE_NO_KEY) { + grn_obj *id_accessor; + id_accessor = grn_obj_column(ctx, + table, + GRN_COLUMN_NAME_ID, + GRN_COLUMN_NAME_ID_LEN); + GRN_PTR_PUT(ctx, &columns, id_accessor); + } else if (table->header.domain != GRN_ID_NIL) { + grn_obj *key_accessor; + key_accessor = grn_obj_column(ctx, + table, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + GRN_PTR_PUT(ctx, &columns, key_accessor); + } + + if (grn_obj_get_range(ctx, table) != GRN_ID_NIL) { + grn_obj *value_accessor; + value_accessor = grn_obj_column(ctx, + table, + GRN_COLUMN_NAME_VALUE, + GRN_COLUMN_NAME_VALUE_LEN); + GRN_PTR_PUT(ctx, &columns, value_accessor); + } + + { + grn_hash *real_columns; + + real_columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY); + grn_table_columns(ctx, table, NULL, 0, (grn_obj *)real_columns); + GRN_HASH_EACH_BEGIN(ctx, real_columns, cursor, id) { + void *key; + grn_id column_id; + grn_obj *column; + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + grn_hash_cursor_get_key(ctx, cursor, &key); + column_id = *((grn_id *)key); + + column = grn_ctx_at(ctx, column_id); + if (column) { + if (grn_obj_is_index_column(ctx, column)) { + have_index_column = GRN_TRUE; + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } else { + have_data_column = GRN_TRUE; + GRN_PTR_PUT(ctx, &columns, column); + if (dumper->is_close_opened_object_mode) { + grn_ctx_merge_temporary_open_space(ctx); + } + } + } else { + GRN_PLUGIN_CLEAR_ERROR(ctx); + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } + } GRN_HASH_EACH_END(ctx, cursor); + grn_hash_close(ctx, real_columns); + } + + n_columns = GRN_BULK_VSIZE(&columns) / sizeof(grn_obj *); + + if (have_index_column && !have_data_column) { + goto exit; + } + + if (GRN_TEXT_LEN(dumper->output) > 0) { + GRN_TEXT_PUTC(ctx, dumper->output, '\n'); + } + + GRN_TEXT_PUTS(ctx, dumper->output, "load --table "); + dump_obj_name(ctx, dumper, table); + GRN_TEXT_PUTS(ctx, dumper->output, "\n[\n"); + + GRN_TEXT_PUTC(ctx, dumper->output, '['); + for (i = 0; i < n_columns; i++) { + grn_obj *column; + grn_obj *column_name = &(dumper->column_name_buffer); + + column = GRN_PTR_VALUE_AT(&columns, i); + if (i) { GRN_TEXT_PUTC(ctx, dumper->output, ','); } + GRN_BULK_REWIND(column_name); + grn_column_name_(ctx, column, column_name); + grn_text_otoj(ctx, dumper->output, column_name, NULL); + } + GRN_TEXT_PUTS(ctx, dumper->output, "],\n"); + + if (table->header.type == GRN_TABLE_HASH_KEY && dumper->is_sort_hash_table) { + grn_obj *sorted; + grn_table_sort_key sort_keys[1]; + uint32_t n_sort_keys = 1; + grn_bool is_first_record = GRN_TRUE; + + sort_keys[0].key = grn_obj_column(ctx, table, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + sort_keys[0].flags = GRN_TABLE_SORT_ASC; + sort_keys[0].offset = 0; + sorted = grn_table_create(ctx, + NULL, 0, NULL, + GRN_TABLE_NO_KEY, + NULL, + table); + grn_table_sort(ctx, + table, 0, -1, + sorted, + sort_keys, n_sort_keys); + cursor = grn_table_cursor_open(ctx, + sorted, + NULL, 0, NULL, 0, + 0, -1, + 0); + while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) { + void *value_raw; + grn_id id; + + grn_table_cursor_get_value(ctx, cursor, &value_raw); + id = *((grn_id *)value_raw); + + if (is_first_record) { + is_first_record = GRN_FALSE; + } else { + GRN_TEXT_PUTS(ctx, dumper->output, ",\n"); + } + dump_record(ctx, dumper, table, id, &columns, n_columns); + } + GRN_TEXT_PUTS(ctx, dumper->output, "\n]\n"); + grn_obj_close(ctx, sorted); + grn_obj_unlink(ctx, sort_keys[0].key); + } else { + grn_obj delete_commands; + grn_id old_id = GRN_ID_NIL; + grn_id id; + + GRN_TEXT_INIT(&delete_commands, 0); + cursor = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, + GRN_CURSOR_BY_KEY); + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + if (old_id != GRN_ID_NIL) { GRN_TEXT_PUTS(ctx, dumper->output, ",\n"); } + if (table->header.type == GRN_TABLE_NO_KEY && old_id + 1 < id) { + grn_id current_id; + for (current_id = old_id + 1; current_id < id; current_id++) { + GRN_TEXT_PUTS(ctx, dumper->output, "[],\n"); + GRN_TEXT_PUTS(ctx, &delete_commands, "delete --table "); + dump_obj_name_raw(ctx, &delete_commands, table); + GRN_TEXT_PUTS(ctx, &delete_commands, " --id "); + grn_text_lltoa(ctx, &delete_commands, current_id); + GRN_TEXT_PUTC(ctx, &delete_commands, '\n'); + } + } + dump_record(ctx, dumper, table, id, &columns, n_columns); + + old_id = id; + } + grn_table_cursor_close(ctx, cursor); + GRN_TEXT_PUTS(ctx, dumper->output, "\n]\n"); + GRN_TEXT_PUT(ctx, dumper->output, + GRN_TEXT_VALUE(&delete_commands), + GRN_TEXT_LEN(&delete_commands)); + GRN_OBJ_FIN(ctx, &delete_commands); + } +exit : + for (i = 0; i < n_columns; i++) { + grn_obj *column; + + column = GRN_PTR_VALUE_AT(&columns, i); + if (column->header.type == GRN_ACCESSOR) { + grn_obj_close(ctx, column); + } + } + GRN_OBJ_FIN(ctx, &columns); + + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } +} + +static void +dump_table(grn_ctx *ctx, grn_dumper *dumper, grn_obj *table) +{ + grn_obj *domain = NULL; + grn_id range_id; + grn_obj *range = NULL; + grn_table_flags flags; + grn_table_flags default_flags = GRN_OBJ_PERSISTENT; + grn_obj *default_tokenizer; + grn_obj *normalizer; + grn_obj *token_filters; + + switch (table->header.type) { + case GRN_TABLE_HASH_KEY: + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: + domain = grn_ctx_at(ctx, table->header.domain); + break; + default: + break; + } + + if (GRN_TEXT_LEN(dumper->output) > 0) { + GRN_TEXT_PUTC(ctx, dumper->output, '\n'); + grn_ctx_output_flush(ctx, 0); + } + + grn_table_get_info(ctx, table, + &flags, + NULL, + &default_tokenizer, + &normalizer, + &token_filters); + + GRN_TEXT_PUTS(ctx, dumper->output, "table_create "); + dump_obj_name(ctx, dumper, table); + GRN_TEXT_PUTC(ctx, dumper->output, ' '); + grn_dump_table_create_flags(ctx, + flags & ~default_flags, + dumper->output); + if (domain) { + GRN_TEXT_PUTC(ctx, dumper->output, ' '); + dump_obj_name(ctx, dumper, domain); + } + range_id = grn_obj_get_range(ctx, table); + if (range_id != GRN_ID_NIL) { + range = grn_ctx_at(ctx, range_id); + if (!range) { + // ERR(GRN_RANGE_ERROR, "couldn't get table's value_type object"); + return; + } + if (table->header.type != GRN_TABLE_NO_KEY) { + GRN_TEXT_PUTC(ctx, dumper->output, ' '); + } else { + GRN_TEXT_PUTS(ctx, dumper->output, " --value_type "); + } + dump_obj_name(ctx, dumper, range); + grn_obj_unlink(ctx, range); + } + if (default_tokenizer) { + GRN_TEXT_PUTS(ctx, dumper->output, " --default_tokenizer "); + dump_obj_name(ctx, dumper, default_tokenizer); + } + if (normalizer) { + GRN_TEXT_PUTS(ctx, dumper->output, " --normalizer "); + dump_obj_name(ctx, dumper, normalizer); + } + if (table->header.type != GRN_TABLE_NO_KEY) { + int n_token_filters; + + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + if (n_token_filters > 0) { + int i; + GRN_TEXT_PUTS(ctx, dumper->output, " --token_filters "); + for (i = 0; i < n_token_filters; i++) { + grn_obj *token_filter = GRN_PTR_VALUE_AT(token_filters, i); + if (i > 0) { + GRN_TEXT_PUTC(ctx, dumper->output, ','); + } + dump_obj_name(ctx, dumper, token_filter); + } + } + } + + GRN_TEXT_PUTC(ctx, dumper->output, '\n'); + + dump_columns(ctx, dumper, table, GRN_TRUE, GRN_FALSE, GRN_FALSE); +} + +static void +dump_schema(grn_ctx *ctx, grn_dumper *dumper) +{ + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + void *name; + int name_size; + grn_obj *object; + + if (grn_id_is_builtin(ctx, id)) { + continue; + } + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + if ((object = grn_ctx_at(ctx, id))) { + switch (object->header.type) { + case GRN_TABLE_HASH_KEY: + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: + case GRN_TABLE_NO_KEY: + dump_table(ctx, dumper, object); + break; + default: + break; + } + } else { + /* XXX: this clause is executed when MeCab tokenizer is enabled in + database but the groonga isn't supported MeCab. + We should return error mesage about it and error exit status + but it's too difficult for this architecture. :< */ + GRN_PLUGIN_CLEAR_ERROR(ctx); + } + + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_DB_EACH_END(ctx, cursor); + + if (!dumper->have_reference_column) { + return; + } + + GRN_TEXT_PUTC(ctx, dumper->output, '\n'); + grn_ctx_output_flush(ctx, 0); + + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + void *name; + int name_size; + grn_obj *object; + + if (grn_id_is_builtin(ctx, id)) { + continue; + } + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + if ((object = grn_ctx_at(ctx, id))) { + switch (object->header.type) { + case GRN_TABLE_HASH_KEY: + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: + case GRN_TABLE_NO_KEY: + dump_columns(ctx, dumper, object, GRN_FALSE, GRN_TRUE, GRN_FALSE); + break; + default: + break; + } + } else { + /* XXX: this clause is executed when MeCab tokenizer is enabled in + database but the groonga isn't supported MeCab. + We should return error mesage about it and error exit status + but it's too difficult for this architecture. :< */ + GRN_PLUGIN_CLEAR_ERROR(ctx); + } + + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_DB_EACH_END(ctx, cursor); +} + +static void +dump_selected_tables_records(grn_ctx *ctx, grn_dumper *dumper, grn_obj *tables) +{ + const char *p, *e; + + p = GRN_TEXT_VALUE(tables); + e = p + GRN_TEXT_LEN(tables); + while (p < e) { + int len; + grn_obj *table; + const char *token, *token_e; + + if ((len = grn_isspace(p, ctx->encoding))) { + p += len; + continue; + } + + token = p; + if (!(('a' <= *p && *p <= 'z') || + ('A' <= *p && *p <= 'Z') || + (*p == '_'))) { + while (p < e && !grn_isspace(p, ctx->encoding)) { + p++; + } + GRN_LOG(ctx, GRN_LOG_WARNING, "invalid table name is ignored: <%.*s>\n", + (int)(p - token), token); + continue; + } + while (p < e && + (('a' <= *p && *p <= 'z') || + ('A' <= *p && *p <= 'Z') || + ('0' <= *p && *p <= '9') || + (*p == '_'))) { + p++; + } + token_e = p; + while (p < e && (len = grn_isspace(p, ctx->encoding))) { + p += len; + continue; + } + if (p < e && *p == ',') { + p++; + } + + table = grn_ctx_get(ctx, token, token_e - token); + if (!table) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "nonexistent table name is ignored: <%.*s>\n", + (int)(token_e - token), token); + continue; + } + + if (grn_obj_is_table(ctx, table)) { + dump_records(ctx, dumper, table); + } + grn_obj_unlink(ctx, table); + } +} + +static void +dump_all_records(grn_ctx *ctx, grn_dumper *dumper) +{ + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + void *name; + int name_size; + grn_obj *table; + + if (grn_id_is_builtin(ctx, id)) { + continue; + } + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + table = grn_ctx_at(ctx, id); + if (!table) { + /* XXX: this clause is executed when MeCab tokenizer is enabled in + database but the groonga isn't supported MeCab. + We should return error mesage about it and error exit status + but it's too difficult for this architecture. :< */ + GRN_PLUGIN_CLEAR_ERROR(ctx); + goto next_loop; + } + + if (grn_obj_is_table(ctx, table)) { + dump_records(ctx, dumper, table); + } + + next_loop : + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_DB_EACH_END(ctx, cursor); +} + +static void +dump_indexes(grn_ctx *ctx, grn_dumper *dumper) +{ + if (!dumper->have_index_column) { + return; + } + + if (GRN_TEXT_LEN(dumper->output) > 0) { + GRN_TEXT_PUTC(ctx, dumper->output, '\n'); + } + + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + void *name; + int name_size; + grn_obj *object; + + if (grn_id_is_builtin(ctx, id)) { + continue; + } + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (dumper->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + object = grn_ctx_at(ctx, id); + if (!object) { + /* XXX: this clause is executed when MeCab tokenizer is enabled in + database but the groonga isn't supported MeCab. + We should return error mesage about it and error exit status + but it's too difficult for this architecture. :< */ + GRN_PLUGIN_CLEAR_ERROR(ctx); + goto next_loop; + } + + if (grn_obj_is_table(ctx, object)) { + dump_columns(ctx, dumper, object, GRN_FALSE, GRN_FALSE, GRN_TRUE); + } + + next_loop : + if (dumper->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_DB_EACH_END(ctx, cursor); +} + +static grn_obj * +command_dump(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_dumper dumper; + grn_obj *tables; + grn_bool is_dump_plugins; + grn_bool is_dump_schema; + grn_bool is_dump_records; + grn_bool is_dump_indexes; + grn_bool is_dump_configs; + + dumper.output = ctx->impl->output.buf; + if (grn_thread_get_limit() == 1) { + dumper.is_close_opened_object_mode = GRN_TRUE; + } else { + dumper.is_close_opened_object_mode = GRN_FALSE; + } + dumper.have_reference_column = GRN_FALSE; + dumper.have_index_column = GRN_FALSE; + + tables = grn_plugin_proc_get_var(ctx, user_data, "tables", -1); + is_dump_plugins = grn_plugin_proc_get_var_bool(ctx, user_data, + "dump_plugins", -1, + GRN_TRUE); + is_dump_schema = grn_plugin_proc_get_var_bool(ctx, user_data, + "dump_schema", -1, + GRN_TRUE); + is_dump_records = grn_plugin_proc_get_var_bool(ctx, user_data, + "dump_records", -1, + GRN_TRUE); + is_dump_indexes = grn_plugin_proc_get_var_bool(ctx, user_data, + "dump_indexes", -1, + GRN_TRUE); + is_dump_configs = grn_plugin_proc_get_var_bool(ctx, user_data, + "dump_configs", -1, + GRN_TRUE); + dumper.is_sort_hash_table = + grn_plugin_proc_get_var_bool(ctx, user_data, + "sort_hash_table", -1, + GRN_FALSE); + GRN_TEXT_INIT(&(dumper.column_name_buffer), 0); + + grn_ctx_set_output_type(ctx, GRN_CONTENT_GROONGA_COMMAND_LIST); + + dumper_collect_statistics(ctx, &dumper); + + if (is_dump_configs) { + dump_configs(ctx, &dumper); + } + if (is_dump_plugins) { + dump_plugins(ctx, &dumper); + } + if (is_dump_schema) { + dump_schema(ctx, &dumper); + } + if (is_dump_records) { + /* To update index columns correctly, we first create the whole schema, then + load non-derivative records, while skipping records of index columns. That + way, Groonga will silently do the job of updating index columns for us. */ + if (GRN_TEXT_LEN(tables) > 0) { + dump_selected_tables_records(ctx, &dumper, tables); + } else { + dump_all_records(ctx, &dumper); + } + } + if (is_dump_indexes) { + dump_indexes(ctx, &dumper); + } + /* remove the last newline because another one will be added by the caller. + maybe, the caller of proc functions currently doesn't consider the + possibility of multiple-line output from proc functions. */ + if (GRN_BULK_VSIZE(dumper.output) > 0) { + grn_bulk_truncate(ctx, dumper.output, GRN_BULK_VSIZE(dumper.output) - 1); + } + + GRN_OBJ_FIN(ctx, &(dumper.column_name_buffer)); + + return NULL; +} + +void +grn_proc_init_dump(grn_ctx *ctx) +{ + grn_expr_var vars[7]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "tables", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "dump_plugins", -1); + grn_plugin_expr_var_init(ctx, &(vars[2]), "dump_schema", -1); + grn_plugin_expr_var_init(ctx, &(vars[3]), "dump_records", -1); + grn_plugin_expr_var_init(ctx, &(vars[4]), "dump_indexes", -1); + grn_plugin_expr_var_init(ctx, &(vars[5]), "dump_configs", -1); + grn_plugin_expr_var_init(ctx, &(vars[6]), "sort_hash_table", -1); + grn_plugin_command_create(ctx, + "dump", -1, + command_dump, + sizeof(vars) / sizeof(vars[0]), + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_fuzzy_search.c b/storage/mroonga/vendor/groonga/lib/proc/proc_fuzzy_search.c new file mode 100644 index 00000000..952fdbb1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_fuzzy_search.c @@ -0,0 +1,467 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" +#include "../grn_rset.h" +#include "../grn_ii.h" + +#include + +#include + +#define DIST(ox,oy) (dists[((lx + 1) * (oy)) + (ox)]) + +static uint32_t +calc_edit_distance(grn_ctx *ctx, char *sx, char *ex, char *sy, char *ey, int flags) +{ + int d = 0; + uint32_t cx, lx, cy, ly, *dists; + char *px, *py; + for (px = sx, lx = 0; px < ex && (cx = grn_charlen(ctx, px, ex)); px += cx, lx++); + for (py = sy, ly = 0; py < ey && (cy = grn_charlen(ctx, py, ey)); py += cy, ly++); + if ((dists = GRN_PLUGIN_MALLOC(ctx, (lx + 1) * (ly + 1) * sizeof(uint32_t)))) { + uint32_t x, y; + for (x = 0; x <= lx; x++) { DIST(x, 0) = x; } + for (y = 0; y <= ly; y++) { DIST(0, y) = y; } + for (x = 1, px = sx; x <= lx; x++, px += cx) { + cx = grn_charlen(ctx, px, ex); + for (y = 1, py = sy; y <= ly; y++, py += cy) { + cy = grn_charlen(ctx, py, ey); + if (cx == cy && !memcmp(px, py, cx)) { + DIST(x, y) = DIST(x - 1, y - 1); + } else { + uint32_t a = DIST(x - 1, y) + 1; + uint32_t b = DIST(x, y - 1) + 1; + uint32_t c = DIST(x - 1, y - 1) + 1; + DIST(x, y) = ((a < b) ? ((a < c) ? a : c) : ((b < c) ? b : c)); + if (flags & GRN_TABLE_FUZZY_SEARCH_WITH_TRANSPOSITION && + x > 1 && y > 1 && cx == cy && + memcmp(px, py - cy, cx) == 0 && + memcmp(px - cx, py, cx) == 0) { + uint32_t t = DIST(x - 2, y - 2) + 1; + DIST(x, y) = ((DIST(x, y) < t) ? DIST(x, y) : t); + } + } + } + } + d = DIST(lx, ly); + GRN_PLUGIN_FREE(ctx, dists); + } + return d; +} + +static grn_obj * +func_edit_distance(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ +#define N_REQUIRED_ARGS 2 +#define MAX_ARGS 3 + int d = 0; + int flags = 0; + grn_obj *obj; + if (nargs >= N_REQUIRED_ARGS && nargs <= MAX_ARGS) { + if (nargs == MAX_ARGS && GRN_BOOL_VALUE(args[2])) { + flags |= GRN_TABLE_FUZZY_SEARCH_WITH_TRANSPOSITION; + } + d = calc_edit_distance(ctx, GRN_TEXT_VALUE(args[0]), GRN_BULK_CURR(args[0]), + GRN_TEXT_VALUE(args[1]), GRN_BULK_CURR(args[1]), flags); + } + if ((obj = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_UINT32, 0))) { + GRN_UINT32_SET(ctx, obj, d); + } + return obj; +#undef N_REQUIRED_ARGS +#undef MAX_ARGS +} + +void +grn_proc_init_edit_distance(grn_ctx *ctx) +{ + grn_proc_create(ctx, "edit_distance", -1, GRN_PROC_FUNCTION, + func_edit_distance, NULL, NULL, 0, NULL); +} + +#define SCORE_HEAP_SIZE 256 + +typedef struct { + grn_id id; + uint32_t score; +} score_heap_node; + +typedef struct { + int n_entries; + int limit; + score_heap_node *nodes; +} score_heap; + +static inline score_heap * +score_heap_open(grn_ctx *ctx, int max) +{ + score_heap *h = GRN_PLUGIN_MALLOC(ctx, sizeof(score_heap)); + if (!h) { return NULL; } + h->nodes = GRN_PLUGIN_MALLOC(ctx, sizeof(score_heap_node) * max); + if (!h->nodes) { + GRN_PLUGIN_FREE(ctx, h); + return NULL; + } + h->n_entries = 0; + h->limit = max; + return h; +} + +static inline grn_bool +score_heap_push(grn_ctx *ctx, score_heap *h, grn_id id, uint32_t score) +{ + int n, n2; + score_heap_node node = {id, score}; + score_heap_node node2; + if (h->n_entries >= h->limit) { + int max = h->limit * 2; + score_heap_node *nodes; + nodes = GRN_PLUGIN_REALLOC(ctx, h->nodes, sizeof(score_heap) * max); + if (!nodes) { + return GRN_FALSE; + } + h->limit = max; + h->nodes = nodes; + } + h->nodes[h->n_entries] = node; + n = h->n_entries++; + while (n) { + n2 = (n - 1) >> 1; + if (h->nodes[n2].score <= h->nodes[n].score) { break; } + node2 = h->nodes[n]; + h->nodes[n] = h->nodes[n2]; + h->nodes[n2] = node2; + n = n2; + } + return GRN_TRUE; +} + +static inline void +score_heap_close(grn_ctx *ctx, score_heap *h) +{ + GRN_PLUGIN_FREE(ctx, h->nodes); + GRN_PLUGIN_FREE(ctx, h); +} + +static grn_rc +sequential_fuzzy_search(grn_ctx *ctx, grn_obj *table, grn_obj *column, grn_obj *query, + uint32_t max_distance, uint32_t prefix_match_size, + uint32_t max_expansion, int flags, grn_obj *res, grn_operator op) +{ + grn_table_cursor *tc; + char *sx = GRN_TEXT_VALUE(query); + char *ex = GRN_BULK_CURR(query); + + if (op == GRN_OP_AND) { + tc = grn_table_cursor_open(ctx, res, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_BY_ID); + } else { + tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_BY_ID); + } + if (tc) { + grn_id id; + grn_obj value; + score_heap *heap; + int i, n; + GRN_TEXT_INIT(&value, 0); + + heap = score_heap_open(ctx, SCORE_HEAP_SIZE); + if (!heap) { + grn_table_cursor_close(ctx, tc); + grn_obj_unlink(ctx, &value); + return GRN_NO_MEMORY_AVAILABLE; + } + + while ((id = grn_table_cursor_next(ctx, tc))) { + unsigned int distance = 0; + grn_obj *domain; + grn_id record_id; + + if (op == GRN_OP_AND) { + grn_id *key; + grn_table_cursor_get_key(ctx, tc, (void **)&key); + record_id = *key; + } else { + record_id = id; + } + GRN_BULK_REWIND(&value); + grn_obj_get_value(ctx, column, record_id, &value); + domain = grn_ctx_at(ctx, ((&value))->header.domain); + if ((&(value))->header.type == GRN_VECTOR) { + n = grn_vector_size(ctx, &value); + for (i = 0; i < n; i++) { + unsigned int length; + const char *vector_value = NULL; + length = grn_vector_get_element(ctx, &value, i, &vector_value, NULL, NULL); + + if (!prefix_match_size || + (prefix_match_size > 0 && length >= prefix_match_size && + !memcmp(sx, vector_value, prefix_match_size))) { + distance = calc_edit_distance(ctx, sx, ex, + (char *)vector_value, + (char *)vector_value + length, flags); + if (distance <= max_distance) { + score_heap_push(ctx, heap, record_id, distance); + break; + } + } + } + } else if ((&(value))->header.type == GRN_UVECTOR && + grn_obj_is_table(ctx, domain)) { + n = grn_vector_size(ctx, &value); + for (i = 0; i < n; i++) { + grn_id rid; + char key_name[GRN_TABLE_MAX_KEY_SIZE]; + int key_length; + rid = grn_uvector_get_element(ctx, &value, i, NULL); + key_length = grn_table_get_key(ctx, domain, rid, key_name, GRN_TABLE_MAX_KEY_SIZE); + + if (!prefix_match_size || + (prefix_match_size > 0 && key_length >= (int) prefix_match_size && + !memcmp(sx, key_name, prefix_match_size))) { + distance = calc_edit_distance(ctx, sx, ex, + key_name, key_name + key_length, flags); + if (distance <= max_distance) { + score_heap_push(ctx, heap, record_id, distance); + break; + } + } + } + } else { + if (grn_obj_is_reference_column(ctx, column)) { + grn_id rid; + char key_name[GRN_TABLE_MAX_KEY_SIZE]; + int key_length; + rid = GRN_RECORD_VALUE(&value); + key_length = grn_table_get_key(ctx, domain, rid, key_name, GRN_TABLE_MAX_KEY_SIZE); + if (!prefix_match_size || + (prefix_match_size > 0 && key_length >= (int) prefix_match_size && + !memcmp(sx, key_name, prefix_match_size))) { + distance = calc_edit_distance(ctx, sx, ex, + key_name, key_name + key_length, flags); + if (distance <= max_distance) { + score_heap_push(ctx, heap, record_id, distance); + } + } + } else { + if (!prefix_match_size || + (prefix_match_size > 0 && GRN_TEXT_LEN(&value) >= prefix_match_size && + !memcmp(sx, GRN_TEXT_VALUE(&value), prefix_match_size))) { + distance = calc_edit_distance(ctx, sx, ex, + GRN_TEXT_VALUE(&value), + GRN_BULK_CURR(&value), flags); + if (distance <= max_distance) { + score_heap_push(ctx, heap, record_id, distance); + } + } + } + } + grn_obj_unlink(ctx, domain); + } + grn_table_cursor_close(ctx, tc); + grn_obj_unlink(ctx, &value); + + for (i = 0; i < heap->n_entries; i++) { + if (max_expansion > 0 && (uint32_t) i >= max_expansion) { + break; + } + { + grn_posting posting; + posting.rid = heap->nodes[i].id; + posting.sid = 1; + posting.pos = 0; + posting.weight = max_distance - heap->nodes[i].score; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + } + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + score_heap_close(ctx, heap); + } + + return GRN_SUCCESS; +} + +static grn_rc +selector_fuzzy_search(grn_ctx *ctx, grn_obj *table, grn_obj *index, + int nargs, grn_obj **args, + grn_obj *res, grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *target = NULL; + grn_obj *obj; + grn_obj *query; + uint32_t max_distance = 1; + uint32_t prefix_length = 0; + uint32_t prefix_match_size = 0; + uint32_t max_expansion = 0; + int flags = 0; + grn_bool use_sequential_search = GRN_FALSE; + + if ((nargs - 1) < 2) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "fuzzy_search(): wrong number of arguments (%d ...)", + nargs - 1); + rc = ctx->rc; + goto exit; + } + obj = args[1]; + query = args[2]; + + if (nargs == 4) { + grn_obj *options = args[3]; + + switch (options->header.type) { + case GRN_BULK : + max_distance = GRN_UINT32_VALUE(options); + break; + case GRN_TABLE_HASH_KEY : + { + grn_hash_cursor *cursor; + void *key; + grn_obj *value; + int key_size; + cursor = grn_hash_cursor_open(ctx, (grn_hash *)options, + NULL, 0, NULL, 0, + 0, -1, 0); + if (!cursor) { + GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, + "fuzzy_search(): couldn't open cursor"); + goto exit; + } + while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { + grn_hash_cursor_get_key_value(ctx, cursor, &key, &key_size, + (void **)&value); + + if (key_size == 12 && !memcmp(key, "max_distance", 12)) { + max_distance = GRN_UINT32_VALUE(value); + } else if (key_size == 13 && !memcmp(key, "prefix_length", 13)) { + prefix_length = GRN_UINT32_VALUE(value); + } else if (key_size == 13 && !memcmp(key, "max_expansion", 13)) { + max_expansion = GRN_UINT32_VALUE(value); + } else if (key_size == 18 && !memcmp(key, "with_transposition", 18)) { + if (GRN_BOOL_VALUE(value)) { + flags |= GRN_TABLE_FUZZY_SEARCH_WITH_TRANSPOSITION; + } + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "invalid option name: <%.*s>", + key_size, (char *)key); + grn_hash_cursor_close(ctx, cursor); + goto exit; + } + } + grn_hash_cursor_close(ctx, cursor); + } + break; + default : + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "fuzzy_search(): " + "3rd argument must be integer or object literal: <%.*s>", + (int)GRN_TEXT_LEN(options), + GRN_TEXT_VALUE(options)); + goto exit; + } + } + + if (index) { + target = index; + } else { + if (obj->header.type == GRN_COLUMN_INDEX) { + target = obj; + } else { + grn_column_index(ctx, obj, GRN_OP_FUZZY, &target, 1, NULL); + } + } + + if (target) { + grn_obj *lexicon; + use_sequential_search = GRN_TRUE; + lexicon = grn_ctx_at(ctx, target->header.domain); + if (lexicon) { + if (lexicon->header.type == GRN_TABLE_PAT_KEY) { + use_sequential_search = GRN_FALSE; + } + grn_obj_unlink(ctx, lexicon); + } + } else { + if (grn_obj_is_key_accessor(ctx, obj) && + table->header.type == GRN_TABLE_PAT_KEY) { + target = table; + } else { + use_sequential_search = GRN_TRUE; + } + } + + if (prefix_length) { + const char *s = GRN_TEXT_VALUE(query); + const char *e = GRN_BULK_CURR(query); + const char *p; + unsigned int cl = 0; + unsigned int length = 0; + for (p = s; p < e && (cl = grn_charlen(ctx, p, e)); p += cl) { + length++; + if (length > prefix_length) { + break; + } + } + prefix_match_size = p - s; + } + + if (use_sequential_search) { + rc = sequential_fuzzy_search(ctx, table, obj, query, + max_distance, prefix_match_size, + max_expansion, flags, res, op); + goto exit; + } + + if (!target) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, target); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "fuzzy_search(): " + "column must be COLUMN_INDEX or TABLE_PAT_KEY: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + rc = ctx->rc; + GRN_OBJ_FIN(ctx, &inspected); + } else { + grn_search_optarg options = {0}; + options.mode = GRN_OP_FUZZY; + options.fuzzy.prefix_match_size = prefix_match_size; + options.fuzzy.max_distance = max_distance; + options.fuzzy.max_expansion = max_expansion; + options.fuzzy.flags = flags; + grn_obj_search(ctx, target, query, res, op, &options); + } + +exit : + return rc; +} + +void +grn_proc_init_fuzzy_search(grn_ctx *ctx) +{ + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "fuzzy_search", -1, + GRN_PROC_FUNCTION, + NULL, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, selector_fuzzy_search); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_FUZZY); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_highlight.c b/storage/mroonga/vendor/groonga/lib/proc/proc_highlight.c new file mode 100644 index 00000000..80551a10 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_highlight.c @@ -0,0 +1,503 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" +#include "../grn_expr.h" + +#include +#include + +#define GRN_FUNC_HIGHLIGHT_HTML_CACHE_NAME "$highlight_html" + +static void +grn_pat_tag_keys_put_original_text(grn_ctx *ctx, grn_obj *output, + const char *text, unsigned int length, + grn_bool use_html_escape) +{ + if (use_html_escape) { + grn_text_escape_xml(ctx, output, text, length); + } else { + GRN_TEXT_PUT(ctx, output, text, length); + } +} + +static grn_rc +grn_pat_tag_keys(grn_ctx *ctx, grn_obj *keywords, + const char *string, unsigned int string_length, + const char **open_tags, unsigned int *open_tag_lengths, + const char **close_tags, unsigned int *close_tag_lengths, + unsigned int n_tags, + grn_obj *highlighted, + grn_bool use_html_escape) +{ + while (string_length > 0) { +#define MAX_N_HITS 16 + grn_pat_scan_hit hits[MAX_N_HITS]; + const char *rest; + unsigned int i, n_hits; + unsigned int previous = 0; + size_t chunk_length; + + n_hits = grn_pat_scan(ctx, (grn_pat *)keywords, + string, string_length, + hits, MAX_N_HITS, &rest); + for (i = 0; i < n_hits; i++) { + unsigned int nth_tag; + if (hits[i].offset - previous > 0) { + grn_pat_tag_keys_put_original_text(ctx, + highlighted, + string + previous, + hits[i].offset - previous, + use_html_escape); + } + nth_tag = ((hits[i].id - 1) % n_tags); + GRN_TEXT_PUT(ctx, highlighted, + open_tags[nth_tag], open_tag_lengths[nth_tag]); + grn_pat_tag_keys_put_original_text(ctx, + highlighted, + string + hits[i].offset, + hits[i].length, + use_html_escape); + GRN_TEXT_PUT(ctx, highlighted, + close_tags[nth_tag], close_tag_lengths[nth_tag]); + previous = hits[i].offset + hits[i].length; + } + + chunk_length = rest - string; + if (chunk_length - previous > 0) { + grn_pat_tag_keys_put_original_text(ctx, + highlighted, + string + previous, + string_length - previous, + use_html_escape); + } + string_length -= chunk_length; + string = rest; +#undef MAX_N_HITS + } + + return GRN_SUCCESS; +} + +static grn_obj * +func_highlight_create_keywords_table(grn_ctx *ctx, + grn_user_data *user_data, + const char *normalizer_name, + unsigned int normalizer_name_length) +{ + grn_obj *keywords; + + keywords = grn_table_create(ctx, NULL, 0, NULL, + GRN_OBJ_TABLE_PAT_KEY, + grn_ctx_at(ctx, GRN_DB_SHORT_TEXT), + NULL); + + if (normalizer_name_length > 0) { + grn_obj *normalizer; + normalizer = grn_ctx_get(ctx, + normalizer_name, + normalizer_name_length); + if (!grn_obj_is_normalizer_proc(ctx, normalizer)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, normalizer); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "highlight_full() not normalizer: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + grn_obj_unlink(ctx, normalizer); + grn_obj_unlink(ctx, keywords); + return NULL; + } + grn_obj_set_info(ctx, keywords, GRN_INFO_NORMALIZER, normalizer); + grn_obj_unlink(ctx, normalizer); + } + + return keywords; +} + +static grn_obj * +highlight_keyword_sets(grn_ctx *ctx, grn_user_data *user_data, + grn_obj **keyword_set_args, unsigned int n_keyword_args, + grn_obj *string, grn_obj *keywords, + grn_bool use_html_escape) +{ + grn_obj *highlighted = NULL; +#define KEYWORD_SET_SIZE 3 + { + unsigned int i; + unsigned int n_keyword_sets; + grn_obj open_tags; + grn_obj open_tag_lengths; + grn_obj close_tags; + grn_obj close_tag_lengths; + + n_keyword_sets = n_keyword_args / KEYWORD_SET_SIZE; + + GRN_OBJ_INIT(&open_tags, GRN_BULK, 0, GRN_DB_VOID); + GRN_OBJ_INIT(&open_tag_lengths, GRN_BULK, 0, GRN_DB_VOID); + GRN_OBJ_INIT(&close_tags, GRN_BULK, 0, GRN_DB_VOID); + GRN_OBJ_INIT(&close_tag_lengths, GRN_BULK, 0, GRN_DB_VOID); + + for (i = 0; i < n_keyword_sets; i++) { + grn_obj *keyword = keyword_set_args[i * KEYWORD_SET_SIZE + 0]; + grn_obj *open_tag = keyword_set_args[i * KEYWORD_SET_SIZE + 1]; + grn_obj *close_tag = keyword_set_args[i * KEYWORD_SET_SIZE + 2]; + + grn_table_add(ctx, keywords, + GRN_TEXT_VALUE(keyword), + GRN_TEXT_LEN(keyword), + NULL); + { + const char *open_tag_content = GRN_TEXT_VALUE(open_tag); + grn_bulk_write(ctx, &open_tags, + (const char *)(&open_tag_content), + sizeof(char *)); + } + { + unsigned int open_tag_length = GRN_TEXT_LEN(open_tag); + grn_bulk_write(ctx, &open_tag_lengths, + (const char *)(&open_tag_length), + sizeof(unsigned int)); + } + { + const char *close_tag_content = GRN_TEXT_VALUE(close_tag); + grn_bulk_write(ctx, &close_tags, + (const char *)(&close_tag_content), + sizeof(char *)); + } + { + unsigned int close_tag_length = GRN_TEXT_LEN(close_tag); + grn_bulk_write(ctx, &close_tag_lengths, + (const char *)(&close_tag_length), + sizeof(unsigned int)); + } + } + + highlighted = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_TEXT, 0); + grn_pat_tag_keys(ctx, keywords, + GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string), + (const char **)GRN_BULK_HEAD(&open_tags), + (unsigned int *)GRN_BULK_HEAD(&open_tag_lengths), + (const char **)GRN_BULK_HEAD(&close_tags), + (unsigned int *)GRN_BULK_HEAD(&close_tag_lengths), + n_keyword_sets, + highlighted, + use_html_escape); + grn_obj_unlink(ctx, &open_tags); + grn_obj_unlink(ctx, &open_tag_lengths); + grn_obj_unlink(ctx, &close_tags); + grn_obj_unlink(ctx, &close_tag_lengths); + } +#undef KEYWORD_SET_SIZE + return highlighted; +} + +static grn_obj * +highlight_keywords(grn_ctx *ctx, grn_user_data *user_data, + grn_obj *string, grn_obj *keywords, grn_bool use_html_escape, + const char *default_open_tag, unsigned int default_open_tag_length, + const char *default_close_tag, unsigned int default_close_tag_length) +{ + grn_obj *highlighted = NULL; + const char *open_tags[1]; + unsigned int open_tag_lengths[1]; + const char *close_tags[1]; + unsigned int close_tag_lengths[1]; + unsigned int n_keyword_sets = 1; + + open_tags[0] = default_open_tag; + open_tag_lengths[0] = default_open_tag_length; + close_tags[0] = default_close_tag; + close_tag_lengths[0] = default_close_tag_length; + + highlighted = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_TEXT, 0); + grn_pat_tag_keys(ctx, keywords, + GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string), + open_tags, + open_tag_lengths, + close_tags, + close_tag_lengths, + n_keyword_sets, + highlighted, + use_html_escape); + + return highlighted; +} + +static grn_obj * +func_highlight(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *highlighted = NULL; + +#define N_REQUIRED_ARGS 1 + if (nargs > N_REQUIRED_ARGS) { + grn_obj *string = args[0]; + grn_bool use_html_escape = GRN_FALSE; + grn_obj *keywords; + const char *normalizer_name = "NormalizerAuto"; + unsigned int normalizer_name_length = 14; + const char *default_open_tag = NULL; + unsigned int default_open_tag_length = 0; + const char *default_close_tag = NULL; + unsigned int default_close_tag_length = 0; + grn_obj *end_arg = args[nargs - 1]; + int n_args_without_option = nargs; + + if (end_arg->header.type == GRN_TABLE_HASH_KEY) { + grn_obj *options = end_arg; + grn_hash_cursor *cursor; + void *key; + grn_obj *value; + int key_size; + + n_args_without_option--; + cursor = grn_hash_cursor_open(ctx, (grn_hash *)options, + NULL, 0, NULL, 0, + 0, -1, 0); + if (!cursor) { + GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, + "highlight(): couldn't open cursor"); + goto exit; + } + while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { + grn_hash_cursor_get_key_value(ctx, cursor, &key, &key_size, + (void **)&value); + if (key_size == 10 && !memcmp(key, "normalizer", 10)) { + normalizer_name = GRN_TEXT_VALUE(value); + normalizer_name_length = GRN_TEXT_LEN(value); + } else if (key_size == 11 && !memcmp(key, "html_escape", 11)) { + if (GRN_BOOL_VALUE(value)) { + use_html_escape = GRN_TRUE; + } + } else if (key_size == 16 && !memcmp(key, "default_open_tag", 16)) { + default_open_tag = GRN_TEXT_VALUE(value); + default_open_tag_length = GRN_TEXT_LEN(value); + } else if (key_size == 17 && !memcmp(key, "default_close_tag", 17)) { + default_close_tag = GRN_TEXT_VALUE(value); + default_close_tag_length = GRN_TEXT_LEN(value); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "invalid option name: <%.*s>", + key_size, (char *)key); + grn_hash_cursor_close(ctx, cursor); + goto exit; + } + } + grn_hash_cursor_close(ctx, cursor); + } + + keywords = + func_highlight_create_keywords_table(ctx, user_data, + normalizer_name, + normalizer_name_length); + + if (keywords) { + grn_obj **keyword_args = args + N_REQUIRED_ARGS; + unsigned int n_keyword_args = n_args_without_option - N_REQUIRED_ARGS; + if (default_open_tag_length == 0 && default_close_tag_length == 0) { + highlighted = highlight_keyword_sets(ctx, user_data, + keyword_args, n_keyword_args, + string, keywords, use_html_escape); + } else { + unsigned int i; + for (i = 0; i < n_keyword_args; i++) { + grn_table_add(ctx, keywords, + GRN_TEXT_VALUE(keyword_args[i]), + GRN_TEXT_LEN(keyword_args[i]), + NULL); + } + highlighted = highlight_keywords(ctx, user_data, + string, keywords, use_html_escape, + default_open_tag, default_open_tag_length, + default_close_tag, default_close_tag_length); + } + } + } +#undef N_REQUIRED_ARGS + +exit : + if (!highlighted) { + highlighted = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_VOID, 0); + } + + return highlighted; +} + +void +grn_proc_init_highlight(grn_ctx *ctx) +{ + grn_proc_create(ctx, "highlight", -1, GRN_PROC_FUNCTION, + func_highlight, NULL, NULL, 0, NULL); +} + +static grn_obj * +func_highlight_full(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *highlighted = NULL; + +#define N_REQUIRED_ARGS 3 +#define KEYWORD_SET_SIZE 3 + if ((nargs >= (N_REQUIRED_ARGS + KEYWORD_SET_SIZE) && + (nargs - N_REQUIRED_ARGS) % KEYWORD_SET_SIZE == 0)) { + grn_obj *string = args[0]; + grn_obj *keywords; + const char *normalizer_name = GRN_TEXT_VALUE(args[1]); + unsigned int normalizer_name_length = GRN_TEXT_LEN(args[1]); + grn_bool use_html_escape = GRN_BOOL_VALUE(args[2]); + + keywords = + func_highlight_create_keywords_table(ctx, user_data, + normalizer_name, + normalizer_name_length); + if (keywords) { + highlighted = highlight_keyword_sets(ctx, user_data, + args + N_REQUIRED_ARGS, + nargs - N_REQUIRED_ARGS, + string, keywords, + use_html_escape); + } + } + + if (!highlighted) { + highlighted = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_VOID, 0); + } +#undef KEYWORD_SET_SIZE +#undef N_REQUIRED_ARGS + + return highlighted; +} + +void +grn_proc_init_highlight_full(grn_ctx *ctx) +{ + grn_proc_create(ctx, "highlight_full", -1, GRN_PROC_FUNCTION, + func_highlight_full, NULL, NULL, 0, NULL); +} + +static grn_obj * +func_highlight_html_create_keywords_table(grn_ctx *ctx, grn_obj *expression) +{ + grn_obj *keywords; + grn_obj *condition_ptr = NULL; + grn_obj *condition = NULL; + + keywords = grn_table_create(ctx, NULL, 0, NULL, + GRN_OBJ_TABLE_PAT_KEY, + grn_ctx_at(ctx, GRN_DB_SHORT_TEXT), + NULL); + + { + grn_obj *normalizer; + normalizer = grn_ctx_get(ctx, "NormalizerAuto", -1); + grn_obj_set_info(ctx, keywords, GRN_INFO_NORMALIZER, normalizer); + grn_obj_unlink(ctx, normalizer); + } + + condition_ptr = grn_expr_get_var(ctx, expression, + GRN_SELECT_INTERNAL_VAR_CONDITION, + strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); + if (condition_ptr) { + condition = GRN_PTR_VALUE(condition_ptr); + } + + if (condition) { + size_t i, n_keywords; + grn_obj current_keywords; + GRN_TEXT_INIT(¤t_keywords, GRN_OBJ_VECTOR); + grn_expr_get_keywords(ctx, condition, ¤t_keywords); + + n_keywords = grn_vector_size(ctx, ¤t_keywords); + for (i = 0; i < n_keywords; i++) { + const char *keyword; + unsigned int keyword_size; + keyword_size = grn_vector_get_element(ctx, + ¤t_keywords, + i, + &keyword, + NULL, + NULL); + grn_table_add(ctx, + keywords, + keyword, + keyword_size, + NULL); + } + GRN_OBJ_FIN(ctx, ¤t_keywords); + } + + return keywords; +} + +static grn_obj * +func_highlight_html(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *highlighted = NULL; + +#define N_REQUIRED_ARGS 1 + if (nargs == N_REQUIRED_ARGS) { + grn_obj *string = args[0]; + grn_obj *expression = NULL; + grn_obj *keywords; + grn_obj *keywords_ptr; + grn_bool use_html_escape = GRN_TRUE; + + grn_proc_get_info(ctx, user_data, NULL, NULL, &expression); + + keywords_ptr = grn_expr_get_var(ctx, expression, + GRN_FUNC_HIGHLIGHT_HTML_CACHE_NAME, + strlen(GRN_FUNC_HIGHLIGHT_HTML_CACHE_NAME)); + if (keywords_ptr) { + keywords = GRN_PTR_VALUE(keywords_ptr); + } else { + keywords_ptr = + grn_expr_get_or_add_var(ctx, expression, + GRN_FUNC_HIGHLIGHT_HTML_CACHE_NAME, + strlen(GRN_FUNC_HIGHLIGHT_HTML_CACHE_NAME)); + GRN_OBJ_FIN(ctx, keywords_ptr); + GRN_PTR_INIT(keywords_ptr, GRN_OBJ_OWN, GRN_DB_OBJECT); + + keywords = func_highlight_html_create_keywords_table(ctx, expression); + GRN_PTR_SET(ctx, keywords_ptr, keywords); + } + + highlighted = highlight_keywords(ctx, user_data, + string, keywords, use_html_escape, + "", + strlen(""), + "", + strlen("")); + } +#undef N_REQUIRED_ARGS + + if (!highlighted) { + highlighted = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_VOID, 0); + } + + return highlighted; +} + +void +grn_proc_init_highlight_html(grn_ctx *ctx) +{ + grn_proc_create(ctx, "highlight_html", -1, GRN_PROC_FUNCTION, + func_highlight_html, NULL, NULL, 0, NULL); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_in_records.c b/storage/mroonga/vendor/groonga/lib/proc/proc_in_records.c new file mode 100644 index 00000000..e3b8a7e3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_in_records.c @@ -0,0 +1,519 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" +#include "../grn_db.h" +#include "../grn_store.h" + +#include + +typedef struct { + int n_conditions; + grn_obj *condition_table; + grn_obj condition_columns; + grn_operator *condition_modes; + grn_obj *search_result; +} grn_in_records_data; + +static void +grn_in_records_data_free(grn_ctx *ctx, grn_in_records_data *data) +{ + int i; + int n_condition_columns; + + if (!data) { + return; + } + + GRN_PLUGIN_FREE(ctx, data->condition_modes); + + n_condition_columns = + GRN_BULK_VSIZE(&(data->condition_columns)) / sizeof(grn_obj *); + for (i = 0; i < n_condition_columns; i++) { + grn_obj *condition_column; + condition_column = GRN_PTR_VALUE_AT(&(data->condition_columns), i); + if (condition_column && condition_column->header.type == GRN_ACCESSOR) { + grn_obj_unlink(ctx, condition_column); + } + } + GRN_OBJ_FIN(ctx, &(data->condition_columns)); + + if (data->search_result) { + grn_obj_close(ctx, data->search_result); + } + + GRN_PLUGIN_FREE(ctx, data); +} + +static grn_obj * +func_in_records_init(grn_ctx *ctx, + int n_args, + grn_obj **args, + grn_user_data *user_data) +{ + grn_in_records_data *data; + grn_obj *condition_table; + grn_expr_code *codes; + int n_arg_codes; + int n_logical_args; + int n_conditions; + int i; + int nth; + + { + grn_obj *caller; + grn_expr *expr; + grn_expr_code *call_code; + + caller = grn_plugin_proc_get_caller(ctx, user_data); + expr = (grn_expr *)caller; + call_code = expr->codes + expr->codes_curr - 1; + n_logical_args = call_code->nargs - 1; + codes = expr->codes + 1; + n_arg_codes = expr->codes_curr - 2; + } + + if (n_logical_args < 4) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): wrong number of arguments (%d for 4..)", + n_logical_args); + return NULL; + } + + if ((n_logical_args % 3) != 1) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): the number of arguments must be 1 + 3n (%d)", + n_logical_args); + return NULL; + } + + n_conditions = (n_logical_args - 1) / 3; + + condition_table = codes[0].value; + if (!grn_obj_is_table(ctx, condition_table)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, condition_table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): the first argument must be a table: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + + data = GRN_PLUGIN_CALLOC(ctx, sizeof(grn_in_records_data)); + if (!data) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): failed to allocate internal data"); + return NULL; + } + user_data->ptr = data; + + data->n_conditions = n_conditions; + data->condition_table = condition_table; + GRN_PTR_INIT(&(data->condition_columns), GRN_OBJ_VECTOR, GRN_ID_NIL); + data->condition_modes = GRN_PLUGIN_MALLOCN(ctx, grn_operator, n_conditions); + if (!data->condition_modes) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): " + "failed to allocate internal data for condition modes"); + goto exit; + } + + for (i = 1, nth = 0; i < n_arg_codes; nth++) { + int value_i = i; + int mode_name_i; + grn_obj *mode_name; + int column_name_i; + grn_obj *column_name; + grn_obj *condition_column; + + value_i += codes[value_i].modify; + + mode_name_i = value_i + 1; + mode_name = codes[mode_name_i].value; + data->condition_modes[nth] = grn_proc_option_value_mode(ctx, + mode_name, + GRN_OP_EQUAL, + "in_records()"); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + + column_name_i = mode_name_i + 1; + column_name = codes[column_name_i].value; + if (!grn_obj_is_text_family_bulk(ctx, column_name)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, condition_table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): " + "the %dth argument must be column name as string: " + "<%.*s>", + column_name_i, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + goto exit; + } + + condition_column = grn_obj_column(ctx, condition_table, + GRN_TEXT_VALUE(column_name), + GRN_TEXT_LEN(column_name)); + if (!condition_column) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, condition_table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): " + "the %dth argument must be existing column name: " + "<%.*s>: <%.*s>", + column_name_i, + (int)GRN_TEXT_LEN(column_name), + GRN_TEXT_VALUE(column_name), + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + goto exit; + } + GRN_PTR_PUT(ctx, &(data->condition_columns), condition_column); + + i = column_name_i + 1; + } + + return NULL; + +exit : + grn_in_records_data_free(ctx, data); + + return NULL; +} + +static grn_obj * +func_in_records_next(grn_ctx *ctx, + int n_args, + grn_obj **args, + grn_user_data *user_data) +{ + grn_in_records_data *data = user_data->ptr; + grn_obj *found; + grn_obj *condition; + grn_obj *variable; + int i; + + found = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_BOOL, 0); + if (!found) { + return NULL; + } + GRN_BOOL_SET(ctx, found, GRN_FALSE); + + if (!data) { + return found; + } + + GRN_EXPR_CREATE_FOR_QUERY(ctx, + data->condition_table, + condition, + variable); + if (!condition) { + grn_rc rc = ctx->rc; + if (rc == GRN_SUCCESS) { + rc = GRN_NO_MEMORY_AVAILABLE; + } + GRN_PLUGIN_ERROR(ctx, + rc, + "in_records(): " + "failed to create internal expression: %s", + ctx->errbuf); + return found; + } + + for (i = 1; i < n_args; i += 3) { + int nth = (i - 1) / 3; + grn_obj *value = args[i]; + grn_obj *condition_column; + grn_operator condition_mode; + + condition_column = GRN_PTR_VALUE_AT(&(data->condition_columns), nth); + condition_mode = data->condition_modes[nth]; + + switch (condition_mode) { + case GRN_OP_EQUAL : + case GRN_OP_NOT_EQUAL : + grn_expr_append_obj(ctx, condition, condition_column, GRN_OP_GET_VALUE, 1); + grn_expr_append_obj(ctx, condition, value, GRN_OP_PUSH, 1); + grn_expr_append_op(ctx, condition, condition_mode, 2); + break; + case GRN_OP_LESS : + grn_expr_append_obj(ctx, condition, condition_column, GRN_OP_GET_VALUE, 1); + grn_expr_append_obj(ctx, condition, value, GRN_OP_PUSH, 1); + grn_expr_append_op(ctx, condition, GRN_OP_GREATER_EQUAL, 2); + break; + case GRN_OP_GREATER : + grn_expr_append_obj(ctx, condition, condition_column, GRN_OP_GET_VALUE, 1); + grn_expr_append_obj(ctx, condition, value, GRN_OP_PUSH, 1); + grn_expr_append_op(ctx, condition, GRN_OP_LESS_EQUAL, 2); + break; + case GRN_OP_LESS_EQUAL : + grn_expr_append_obj(ctx, condition, condition_column, GRN_OP_GET_VALUE, 1); + grn_expr_append_obj(ctx, condition, value, GRN_OP_PUSH, 1); + grn_expr_append_op(ctx, condition, GRN_OP_GREATER, 2); + break; + case GRN_OP_GREATER_EQUAL : + grn_expr_append_obj(ctx, condition, condition_column, GRN_OP_GET_VALUE, 1); + grn_expr_append_obj(ctx, condition, value, GRN_OP_PUSH, 1); + grn_expr_append_op(ctx, condition, GRN_OP_LESS, 2); + break; + default : + grn_expr_append_obj(ctx, condition, value, GRN_OP_PUSH, 1); + grn_expr_append_obj(ctx, condition, condition_column, GRN_OP_GET_VALUE, 1); + grn_expr_append_op(ctx, condition, condition_mode, 2); + break; + } + + if (nth > 0) { + grn_expr_append_op(ctx, condition, GRN_OP_AND, 2); + } + } + + data->search_result = grn_table_select(ctx, + data->condition_table, + condition, + data->search_result, + GRN_OP_OR); + if (grn_table_size(ctx, data->search_result) > 0) { + GRN_BOOL_SET(ctx, found, GRN_TRUE); + + GRN_TABLE_EACH_BEGIN(ctx, data->search_result, cursor, id) { + grn_table_cursor_delete(ctx, cursor); + } GRN_TABLE_EACH_END(ctx, cursor); + } + + grn_obj_close(ctx, condition); + + return found; +} + +static grn_obj * +func_in_records_fin(grn_ctx *ctx, + int n_args, + grn_obj **args, + grn_user_data *user_data) +{ + grn_in_records_data *data = user_data->ptr; + + grn_in_records_data_free(ctx, data); + + return NULL; +} + +static grn_rc +selector_in_records(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + int n_args, + grn_obj **args, + grn_obj *res, + grn_operator op) +{ + grn_obj *condition_table; + grn_operator *condition_modes = NULL; + grn_obj condition_columns; + int i, nth; + + /* TODO: Enable me when function call is supported. */ + return GRN_FUNCTION_NOT_IMPLEMENTED; + + if (n_args < 5) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): wrong number of arguments (%d for 4..)", + n_args - 1); + return ctx->rc; + } + + condition_table = args[1]; + if (!grn_obj_is_table(ctx, condition_table)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, condition_table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): the first argument must be a table: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return ctx->rc; + } + + condition_modes = GRN_PLUGIN_MALLOCN(ctx, grn_operator, (n_args - 2) / 3); + GRN_PTR_INIT(&condition_columns, GRN_OBJ_VECTOR, GRN_ID_NIL); + for (i = 2, nth = 0; i < n_args; i += 3, nth++) { + int mode_name_i = i + 1; + int column_name_i = i + 2; + grn_obj *mode_name; + grn_operator mode; + grn_obj *column_name; + grn_obj *condition_column; + + mode_name = args[mode_name_i]; + mode = grn_proc_option_value_mode(ctx, + mode_name, + GRN_OP_EQUAL, + "in_records()"); + if (ctx->rc != GRN_SUCCESS) { + goto exit; + } + + condition_modes[nth] = mode; + + column_name = args[column_name_i]; + if (!grn_obj_is_text_family_bulk(ctx, column_name)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, condition_table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): " + "the %dth argument must be column name as string: " + "<%.*s>", + column_name_i, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + goto exit; + } + + condition_column = grn_obj_column(ctx, condition_table, + GRN_TEXT_VALUE(column_name), + GRN_TEXT_LEN(column_name)); + if (!condition_column) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, condition_table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): " + "the %dth argument must be existing column name: " + "<%.*s>: <%.*s>", + column_name_i, + (int)GRN_TEXT_LEN(column_name), + GRN_TEXT_VALUE(column_name), + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + goto exit; + } + GRN_PTR_PUT(ctx, &condition_columns, condition_column); + } + + { + grn_obj condition_column_value; + + GRN_VOID_INIT(&condition_column_value); + GRN_TABLE_EACH_BEGIN(ctx, condition_table, cursor, id) { + grn_obj *sub_res = NULL; + + for (i = 2; i < n_args; i += 3) { + int nth = (i - 2) / 3; + grn_operator sub_op; + grn_obj *condition_column; + grn_operator condition_mode; + grn_obj *column = args[i]; + grn_obj *expr; + grn_obj *variable; + + if (nth == 0) { + sub_op = GRN_OP_OR; + } else { + sub_op = GRN_OP_AND; + } + + condition_column = GRN_PTR_VALUE_AT(&condition_columns, nth); + condition_mode = condition_modes[nth]; + + GRN_BULK_REWIND(&condition_column_value); + grn_obj_get_value(ctx, + condition_column, + id, + &condition_column_value); + + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expr, variable); + if (!expr) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "in_records(): failed to create expression"); + GRN_OBJ_FIN(ctx, &condition_column_value); + if (sub_res) { + grn_obj_close(ctx, sub_res); + } + goto exit; + } + grn_expr_append_obj(ctx, expr, column, GRN_OP_GET_VALUE, 1); + grn_expr_append_obj(ctx, expr, &condition_column_value, GRN_OP_PUSH, 1); + grn_expr_append_op(ctx, expr, condition_mode, 2); + sub_res = grn_table_select(ctx, table, expr, sub_res, sub_op); + grn_obj_close(ctx, expr); + } + + if (sub_res) { + grn_table_setoperation(ctx, res, sub_res, res, op); + grn_obj_close(ctx, sub_res); + } + } GRN_TABLE_EACH_END(ctx, cursor); + GRN_OBJ_FIN(ctx, &condition_column_value); + } + +exit : + GRN_PLUGIN_FREE(ctx, condition_modes); + + for (i = 2; i < n_args; i += 3) { + int nth = (i - 2) / 3; + grn_obj *condition_column; + condition_column = GRN_PTR_VALUE_AT(&condition_columns, nth); + if (condition_column && condition_column->header.type == GRN_ACCESSOR) { + grn_obj_unlink(ctx, condition_column); + } + } + GRN_OBJ_FIN(ctx, &condition_columns); + + return ctx->rc; +} + +void +grn_proc_init_in_records(grn_ctx *ctx) +{ + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "in_records", -1, GRN_PROC_FUNCTION, + func_in_records_init, + func_in_records_next, + func_in_records_fin, + 0, + NULL); + grn_proc_set_selector(ctx, selector_proc, selector_in_records); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_NOP); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_lock.c b/storage/mroonga/vendor/groonga/lib/proc/proc_lock.c new file mode 100644 index 00000000..9eaf808a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_lock.c @@ -0,0 +1,172 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" + +#include "../grn_ctx.h" + +#include + +static grn_obj * +command_lock_clear(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + int target_name_len; + grn_obj *target_name; + grn_obj *obj; + + target_name = grn_plugin_proc_get_var(ctx, user_data, "target_name", -1); + target_name_len = GRN_TEXT_LEN(target_name); + + if (target_name_len) { + obj = grn_ctx_get(ctx, GRN_TEXT_VALUE(target_name), target_name_len); + } else { + obj = grn_ctx_db(ctx); + } + + if (obj) { + grn_obj_clear_lock(ctx, obj); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[lock][clear] target object not found: <%.*s>", + target_name_len, GRN_TEXT_VALUE(target_name)); + } + + grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS); + + return NULL; +} + +void +grn_proc_init_clearlock(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + /* Deprecated. Use "lock_clear" instead. */ + grn_plugin_expr_var_init(ctx, &(vars[0]), "target_name", -1); + grn_plugin_command_create(ctx, + "clearlock", -1, + command_lock_clear, + 1, + vars); +} + +void +grn_proc_init_lock_clear(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "target_name", -1); + grn_plugin_command_create(ctx, + "lock_clear", -1, + command_lock_clear, + 1, + vars); +} + +static grn_obj * +command_lock_acquire(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + int target_name_len; + grn_obj *target_name; + grn_obj *obj; + + target_name = grn_plugin_proc_get_var(ctx, user_data, "target_name", -1); + target_name_len = GRN_TEXT_LEN(target_name); + + if (target_name_len) { + obj = grn_ctx_get(ctx, GRN_TEXT_VALUE(target_name), target_name_len); + } else { + obj = grn_ctx_db(ctx); + } + + if (obj) { + grn_obj_lock(ctx, obj, GRN_ID_NIL, grn_lock_timeout); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[lock][acquire] target object not found: <%.*s>", + target_name_len, GRN_TEXT_VALUE(target_name)); + } + + grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS); + + return NULL; +} + +void +grn_proc_init_lock_acquire(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "target_name", -1); + grn_plugin_command_create(ctx, + "lock_acquire", -1, + command_lock_acquire, + 1, + vars); +} + +static grn_obj * +command_lock_release(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + int target_name_len; + grn_obj *target_name; + grn_obj *obj; + + target_name = grn_plugin_proc_get_var(ctx, user_data, "target_name", -1); + target_name_len = GRN_TEXT_LEN(target_name); + + if (target_name_len) { + obj = grn_ctx_get(ctx, GRN_TEXT_VALUE(target_name), target_name_len); + } else { + obj = grn_ctx_db(ctx); + } + + if (obj) { + grn_obj_unlock(ctx, obj, GRN_ID_NIL); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[lock][release] target object not found: <%.*s>", + target_name_len, GRN_TEXT_VALUE(target_name)); + } + + grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS); + + return NULL; +} + +void +grn_proc_init_lock_release(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "target_name", -1); + grn_plugin_command_create(ctx, + "lock_release", -1, + command_lock_release, + 1, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_object.c b/storage/mroonga/vendor/groonga/lib/proc/proc_object.c new file mode 100644 index 00000000..380e6553 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_object.c @@ -0,0 +1,138 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" +#include "../grn_io.h" + +#include + +#include +#include + +static grn_obj * +command_object_exist(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *db; + grn_obj *name; + grn_id id; + + db = grn_ctx_db(ctx); + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + if (GRN_TEXT_LEN(name) == 0) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[object][exist] name is missing"); + grn_ctx_output_bool(ctx, GRN_FALSE); + return NULL; + } + + id = grn_table_get(ctx, db, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name)); + grn_ctx_output_bool(ctx, id != GRN_ID_NIL); + return NULL; +} + +void +grn_proc_init_object_exist(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "name", -1); + grn_plugin_command_create(ctx, + "object_exist", -1, + command_object_exist, + 1, + vars); +} + +static grn_obj * +command_object_remove(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *db; + grn_obj *name; + grn_bool force; + grn_obj *target; + grn_bool failed_to_open; + + db = grn_ctx_db(ctx); + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + force = grn_plugin_proc_get_var_bool(ctx, user_data, "force", -1, GRN_FALSE); + + if (GRN_TEXT_LEN(name) == 0) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[object][remove] name is missing"); + grn_ctx_output_bool(ctx, GRN_FALSE); + return NULL; + } + + target = grn_ctx_get(ctx, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name)); + if (target) { + grn_obj_remove(ctx, target); + if (!force || ctx->rc == GRN_SUCCESS) { + grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS); + return NULL; + } + grn_obj_close(ctx, target); + failed_to_open = GRN_TRUE; + } else { + failed_to_open = (ctx->rc != GRN_SUCCESS); + } + + if (force) { + grn_obj_remove_force(ctx, GRN_TEXT_VALUE(name), GRN_TEXT_LEN(name)); + grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS); + } else { + if (failed_to_open) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[object][remove] " + "failed to open the target object: <%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[object][remove] target object doesn't exist: <%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + } + grn_ctx_output_bool(ctx, GRN_FALSE); + } + + return NULL; +} + +void +grn_proc_init_object_remove(grn_ctx *ctx) +{ + grn_expr_var vars[2]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "name", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "force", -1); + grn_plugin_command_create(ctx, + "object_remove", -1, + command_object_remove, + 2, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_object_inspect.c b/storage/mroonga/vendor/groonga/lib/proc/proc_object_inspect.c new file mode 100644 index 00000000..eaa6ec4b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_object_inspect.c @@ -0,0 +1,614 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_pat.h" +#include "../grn_dat.h" +#include "../grn_ii.h" + +#include "../grn_proc.h" + +#include + +static void command_object_inspect_dispatch(grn_ctx *ctx, grn_obj *obj); + +static void +command_object_inspect_obj_name(grn_ctx *ctx, grn_obj *obj) +{ + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + name_size = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE); + grn_ctx_output_str(ctx, name, name_size); +} + +static void +command_object_inspect_obj_type(grn_ctx *ctx, uint8_t type) +{ + grn_ctx_output_map_open(ctx, "type", 2); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, type); + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_cstr(ctx, grn_obj_type_to_string(type)); + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_type(grn_ctx *ctx, grn_obj *type) +{ + if (!type) { + grn_ctx_output_null(ctx); + return; + } + + grn_ctx_output_map_open(ctx, "type", 4); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, grn_obj_id(ctx, type)); + grn_ctx_output_cstr(ctx, "name"); + command_object_inspect_obj_name(ctx, type); + grn_ctx_output_cstr(ctx, "type"); + command_object_inspect_obj_type(ctx, type->header.type); + grn_ctx_output_cstr(ctx, "size"); + if (type->header.type == GRN_TYPE) { + grn_ctx_output_uint64(ctx, grn_type_size(ctx, type)); + } else { + grn_ctx_output_uint64(ctx, sizeof(grn_id)); + } + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_disk_usage(grn_ctx *ctx, grn_obj *obj) +{ + grn_ctx_output_uint64(ctx, grn_obj_get_disk_usage(ctx, obj)); +} + +static void +command_object_inspect_table_hash_key_key(grn_ctx *ctx, grn_hash *hash) +{ + grn_ctx_output_map_open(ctx, "key", 3); + { + grn_ctx_output_cstr(ctx, "type"); + command_object_inspect_type(ctx, grn_ctx_at(ctx, hash->obj.header.domain)); + grn_ctx_output_cstr(ctx, "total_size"); + grn_ctx_output_uint64(ctx, grn_hash_total_key_size(ctx, hash)); + grn_ctx_output_cstr(ctx, "max_total_size"); + grn_ctx_output_uint64(ctx, grn_hash_max_total_key_size(ctx, hash)); + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_table_pat_key_key(grn_ctx *ctx, grn_pat *pat) +{ + grn_ctx_output_map_open(ctx, "key", 3); + { + grn_ctx_output_cstr(ctx, "type"); + command_object_inspect_type(ctx, grn_ctx_at(ctx, pat->obj.header.domain)); + grn_ctx_output_cstr(ctx, "total_size"); + grn_ctx_output_uint64(ctx, grn_pat_total_key_size(ctx, pat)); + grn_ctx_output_cstr(ctx, "max_total_size"); + grn_ctx_output_uint64(ctx, GRN_PAT_MAX_TOTAL_KEY_SIZE); + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_table_dat_key_key(grn_ctx *ctx, grn_dat *dat) +{ + grn_ctx_output_map_open(ctx, "key", 1); + { + grn_ctx_output_cstr(ctx, "type"); + command_object_inspect_type(ctx, grn_ctx_at(ctx, dat->obj.header.domain)); + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_table_key(grn_ctx *ctx, grn_obj *table) +{ + switch (table->header.type) { + case GRN_TABLE_HASH_KEY : + command_object_inspect_table_hash_key_key(ctx, (grn_hash *)table); + break; + case GRN_TABLE_PAT_KEY : + command_object_inspect_table_pat_key_key(ctx, (grn_pat *)table); + break; + case GRN_TABLE_DAT_KEY : + command_object_inspect_table_dat_key_key(ctx, (grn_dat *)table); + break; + case GRN_TABLE_NO_KEY : + grn_ctx_output_null(ctx); + break; + default : + break; + } +} + +static void +command_object_inspect_table_value(grn_ctx *ctx, grn_obj *table) +{ + if (table->header.type == GRN_TABLE_DAT_KEY) { + grn_ctx_output_null(ctx); + } else { + grn_ctx_output_map_open(ctx, "value", 1); + { + grn_id range_id = grn_obj_get_range(ctx, table); + grn_ctx_output_cstr(ctx, "type"); + command_object_inspect_type(ctx, grn_ctx_at(ctx, range_id)); + } + grn_ctx_output_map_close(ctx); + } +} + +static void +command_object_inspect_table(grn_ctx *ctx, grn_obj *obj) +{ + grn_ctx_output_map_open(ctx, "table", 7); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, grn_obj_id(ctx, obj)); + grn_ctx_output_cstr(ctx, "name"); + command_object_inspect_obj_name(ctx, obj); + grn_ctx_output_cstr(ctx, "type"); + command_object_inspect_obj_type(ctx, obj->header.type); + grn_ctx_output_cstr(ctx, "key"); + command_object_inspect_table_key(ctx, obj); + grn_ctx_output_cstr(ctx, "value"); + command_object_inspect_table_value(ctx, obj); + grn_ctx_output_cstr(ctx, "n_records"); + grn_ctx_output_uint64(ctx, grn_table_size(ctx, obj)); + grn_ctx_output_cstr(ctx, "disk_usage"); + command_object_inspect_disk_usage(ctx, obj); + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_column_name(grn_ctx *ctx, grn_obj *column) +{ + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + name_size = grn_column_name(ctx, column, name, GRN_TABLE_MAX_KEY_SIZE); + name[name_size] = '\0'; + grn_ctx_output_str(ctx, name, name_size); +} + +static void +command_object_inspect_column_type_name(grn_ctx *ctx, grn_obj *column) +{ + switch (column->header.type) { + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + switch (column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { + case GRN_OBJ_COLUMN_SCALAR : + grn_ctx_output_cstr(ctx, "scalar"); + break; + case GRN_OBJ_COLUMN_VECTOR : + grn_ctx_output_cstr(ctx, "vector"); + break; + } + break; + case GRN_COLUMN_INDEX : + grn_ctx_output_cstr(ctx, "index"); + break; + default: + break; + } +} + +static void +command_object_inspect_column_type(grn_ctx *ctx, grn_obj *column) +{ + grn_ctx_output_map_open(ctx, "type", 2); + { + grn_ctx_output_cstr(ctx, "name"); + command_object_inspect_column_type_name(ctx, column); + + grn_ctx_output_cstr(ctx, "raw"); + grn_ctx_output_map_open(ctx, "raw", 2); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, column->header.type); + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_cstr(ctx, grn_obj_type_to_string(column->header.type)); + } + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_column_index_value_statistics(grn_ctx *ctx, + grn_ii *ii) +{ + grn_ctx_output_map_open(ctx, "statistics", 11); + { + struct grn_ii_header *h = ii->header; + + grn_ctx_output_cstr(ctx, "max_section_id"); + grn_ctx_output_uint64(ctx, grn_ii_max_section(ii)); + + { + uint32_t max_id = 0; + uint32_t n_garbage_segments = 0; + uint32_t n_array_segments = 0; + uint32_t n_buffer_segments = 0; + + grn_ctx_output_cstr(ctx, "n_garbage_segments"); + { + uint32_t i; + + for (i = h->bgqtail; + i != h->bgqhead; + i = ((i + 1) & (GRN_II_BGQSIZE - 1))) { + uint32_t id = h->bgqbody[i]; + n_garbage_segments++; + if (id > max_id) { max_id = id; } + } + grn_ctx_output_uint64(ctx, n_garbage_segments); + } + + grn_ctx_output_cstr(ctx, "max_array_segment_id"); + grn_ctx_output_uint64(ctx, h->amax); + grn_ctx_output_cstr(ctx, "n_array_segments"); + { + uint32_t i; + + for (i = 0; i < GRN_II_MAX_LSEG; i++) { + uint32_t id = h->ainfo[i]; + if (id != GRN_II_PSEG_NOT_ASSIGNED) { + if (id > max_id) { max_id = id; } + n_array_segments++; + } + } + grn_ctx_output_uint64(ctx, n_array_segments); + } + + grn_ctx_output_cstr(ctx, "max_buffer_segment_id"); + grn_ctx_output_uint64(ctx, h->bmax); + grn_ctx_output_cstr(ctx, "n_buffer_segments"); + { + uint32_t i; + + for (i = 0; i < GRN_II_MAX_LSEG; i++) { + uint32_t id = h->binfo[i]; + if (id != GRN_II_PSEG_NOT_ASSIGNED) { + if (id > max_id) { max_id = id; } + n_buffer_segments++; + } + } + grn_ctx_output_uint64(ctx, n_buffer_segments); + } + + grn_ctx_output_cstr(ctx, "max_in_use_physical_segment_id"); + grn_ctx_output_uint64(ctx, max_id); + + grn_ctx_output_cstr(ctx, "n_unmanaged_segments"); + grn_ctx_output_uint64(ctx, + h->pnext - + n_array_segments - + n_buffer_segments - + n_garbage_segments); + } + + { + grn_ctx_output_cstr(ctx, "total_chunk_size"); + grn_ctx_output_uint64(ctx, h->total_chunk_size); + grn_ctx_output_cstr(ctx, "max_in_use_chunk_id"); + { + uint32_t i; + uint32_t max_id; + + for (max_id = 0, i = 0; i < (GRN_II_MAX_CHUNK >> 3); i++) { + uint8_t sub_chunk_info = h->chunks[i]; + uint8_t bit; + + if (sub_chunk_info == 0) { + continue; + } + for (bit = 0; bit < 8; bit++) { + if (sub_chunk_info & (1 << bit)) { + max_id = (i << 3) + sub_chunk_info; + } + } + } + grn_ctx_output_uint64(ctx, max_id); + } + grn_ctx_output_cstr(ctx, "n_garbage_chunks"); + grn_ctx_output_array_open(ctx, + "n_garbage_chunks", + GRN_II_N_CHUNK_VARIATION); + { + uint32_t i; + for (i = 0; i <= GRN_II_N_CHUNK_VARIATION; i++) { + grn_ctx_output_uint64(ctx, h->ngarbages[i]); + } + } + grn_ctx_output_array_close(ctx); + } + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_column_data_value_compress(grn_ctx *ctx, grn_obj *column) +{ + const char *compress = NULL; + grn_column_flags column_flags; + + column_flags = grn_column_get_flags(ctx, column); + switch (column_flags & GRN_OBJ_COMPRESS_MASK) { + case GRN_OBJ_COMPRESS_ZLIB : + compress = "zlib"; + break; + case GRN_OBJ_COMPRESS_LZ4 : + compress = "lz4"; + break; + case GRN_OBJ_COMPRESS_ZSTD : + compress = "zstd"; + break; + default : + break; + } + + if (compress) { + grn_ctx_output_cstr(ctx, compress); + } else { + grn_ctx_output_null(ctx); + } +} + +static void +command_object_inspect_column_value(grn_ctx *ctx, grn_obj *column) +{ + int n_elements = 1; + grn_bool is_index = (column->header.type == GRN_COLUMN_INDEX); + + if (is_index) { + n_elements += 5; + } else { + n_elements += 1; + } + grn_ctx_output_map_open(ctx, "value", n_elements); + { + grn_id range_id; + grn_column_flags column_flags; + + range_id = grn_obj_get_range(ctx, column); + column_flags = grn_column_get_flags(ctx, column); + + grn_ctx_output_cstr(ctx, "type"); + command_object_inspect_type(ctx, grn_ctx_at(ctx, range_id)); + if (is_index) { + grn_ctx_output_cstr(ctx, "section"); + grn_ctx_output_bool(ctx, (column_flags & GRN_OBJ_WITH_SECTION) != 0); + grn_ctx_output_cstr(ctx, "weight"); + grn_ctx_output_bool(ctx, (column_flags & GRN_OBJ_WITH_WEIGHT) != 0); + grn_ctx_output_cstr(ctx, "position"); + grn_ctx_output_bool(ctx, (column_flags & GRN_OBJ_WITH_POSITION) != 0); + grn_ctx_output_cstr(ctx, "size"); + if ((column_flags & GRN_OBJ_INDEX_SMALL) != 0) { + grn_ctx_output_cstr(ctx, "small"); + } else if ((column_flags & GRN_OBJ_INDEX_MEDIUM) != 0) { + grn_ctx_output_cstr(ctx, "medium"); + } else { + grn_ctx_output_cstr(ctx, "normal"); + } + grn_ctx_output_cstr(ctx, "statistics"); + command_object_inspect_column_index_value_statistics(ctx, + (grn_ii *)column); + } else { + grn_ctx_output_cstr(ctx, "compress"); + command_object_inspect_column_data_value_compress(ctx, column); + } + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_column_index_sources(grn_ctx *ctx, grn_obj *column) +{ + grn_obj *source_table; + grn_obj source_ids; + unsigned int i, n_ids; + + source_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); + + GRN_RECORD_INIT(&source_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); + grn_obj_get_info(ctx, column, GRN_INFO_SOURCE, &source_ids); + + n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); + grn_ctx_output_array_open(ctx, "sources", n_ids); + for (i = 0; i < n_ids; i++) { + grn_id source_id; + grn_obj *source; + + source_id = GRN_RECORD_VALUE_AT(&source_ids, i); + source = grn_ctx_at(ctx, source_id); + + grn_ctx_output_map_open(ctx, "source", 4); + { + grn_ctx_output_cstr(ctx, "id"); + if (grn_obj_is_table(ctx, source)) { + grn_ctx_output_null(ctx); + } else { + grn_ctx_output_uint64(ctx, source_id); + } + + grn_ctx_output_cstr(ctx, "name"); + if (grn_obj_is_table(ctx, source)) { + grn_ctx_output_cstr(ctx, "_key"); + } else { + command_object_inspect_column_name(ctx, source); + } + + grn_ctx_output_cstr(ctx, "table"); + command_object_inspect_table(ctx, source_table); + + grn_ctx_output_cstr(ctx, "full_name"); + if (grn_obj_is_table(ctx, source)) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int name_size; + name_size = grn_obj_name(ctx, source, name, GRN_TABLE_MAX_KEY_SIZE); + name[name_size] = '\0'; + grn_strcat(name, GRN_TABLE_MAX_KEY_SIZE, "._key"); + grn_ctx_output_cstr(ctx, name); + } else { + command_object_inspect_obj_name(ctx, source); + } + } + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_array_close(ctx); + + GRN_OBJ_FIN(ctx, &source_ids); +} + +static void +command_object_inspect_column(grn_ctx *ctx, grn_obj *column) +{ + int n_elements = 7; + grn_bool is_index = (column->header.type == GRN_COLUMN_INDEX); + + if (is_index) { + n_elements += 1; + } + grn_ctx_output_map_open(ctx, "column", n_elements); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, grn_obj_id(ctx, column)); + grn_ctx_output_cstr(ctx, "name"); + command_object_inspect_column_name(ctx, column); + grn_ctx_output_cstr(ctx, "table"); + command_object_inspect_table(ctx, grn_ctx_at(ctx, column->header.domain)); + grn_ctx_output_cstr(ctx, "full_name"); + command_object_inspect_obj_name(ctx, column); + grn_ctx_output_cstr(ctx, "type"); + command_object_inspect_column_type(ctx, column); + grn_ctx_output_cstr(ctx, "value"); + command_object_inspect_column_value(ctx, column); + if (is_index) { + grn_ctx_output_cstr(ctx, "sources"); + command_object_inspect_column_index_sources(ctx, column); + } + grn_ctx_output_cstr(ctx, "disk_usage"); + command_object_inspect_disk_usage(ctx, column); + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_db(grn_ctx *ctx, grn_obj *obj) +{ + grn_db *db = (grn_db *)obj; + + grn_ctx_output_map_open(ctx, "database", 3); + { + grn_ctx_output_cstr(ctx, "type"); + command_object_inspect_obj_type(ctx, obj->header.type); + grn_ctx_output_cstr(ctx, "name_table"); + command_object_inspect_dispatch(ctx, db->keys); + grn_ctx_output_cstr(ctx, "disk_usage"); + command_object_inspect_disk_usage(ctx, obj); + } + grn_ctx_output_map_close(ctx); +} + +static void +command_object_inspect_dispatch(grn_ctx *ctx, grn_obj *obj) +{ + switch (obj->header.type) { + case GRN_TYPE : + command_object_inspect_type(ctx, obj); + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + command_object_inspect_table(ctx, obj); + break; + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + command_object_inspect_column(ctx, obj); + break; + case GRN_DB : + command_object_inspect_db(ctx, obj); + break; + default : + { + GRN_PLUGIN_ERROR(ctx, + GRN_FUNCTION_NOT_IMPLEMENTED, + "[object][inspect] unsupported type: <%s>(%#x)", + grn_obj_type_to_string(obj->header.type), + obj->header.type); + grn_ctx_output_null(ctx); + break; + } + } +} + +static grn_obj * +command_object_inspect(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *name; + grn_obj *target; + + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + if (GRN_TEXT_LEN(name) == 0) { + target = grn_ctx_db(ctx); + } else { + target = grn_ctx_get(ctx, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name)); + if (!target) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[object][inspect] nonexistent target: <%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + grn_ctx_output_null(ctx); + return NULL; + } + } + + command_object_inspect_dispatch(ctx, target); + + return NULL; +} + +void +grn_proc_init_object_inspect(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "name", -1); + grn_plugin_command_create(ctx, + "object_inspect", -1, + command_object_inspect, + 1, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_object_list.c b/storage/mroonga/vendor/groonga/lib/proc/proc_object_list.c new file mode 100644 index 00000000..adb4c91b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_object_list.c @@ -0,0 +1,413 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" +#include "../grn_db.h" + +#include + +static void +command_object_list_dump_flags(grn_ctx *ctx, grn_obj_spec *spec) +{ + grn_obj flags; + + GRN_TEXT_INIT(&flags, 0); + + switch (spec->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + grn_dump_table_create_flags(ctx, spec->header.flags, &flags); + break; + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_INDEX : + grn_dump_column_create_flags(ctx, spec->header.flags, &flags); + break; + case GRN_TYPE : + if (spec->header.flags & GRN_OBJ_KEY_VAR_SIZE) { + GRN_TEXT_PUTS(ctx, &flags, "KEY_VAR_SIZE"); + } else { + switch (spec->header.flags & GRN_OBJ_KEY_MASK) { + case GRN_OBJ_KEY_UINT : + GRN_TEXT_PUTS(ctx, &flags, "KEY_UINT"); + break; + case GRN_OBJ_KEY_INT : + GRN_TEXT_PUTS(ctx, &flags, "KEY_INT"); + break; + case GRN_OBJ_KEY_FLOAT : + GRN_TEXT_PUTS(ctx, &flags, "KEY_FLOAT"); + break; + case GRN_OBJ_KEY_GEO_POINT : + GRN_TEXT_PUTS(ctx, &flags, "KEY_GEO_POINT"); + break; + } + } + break; + } + if (spec->header.flags & GRN_OBJ_CUSTOM_NAME) { + if (GRN_TEXT_LEN(&flags) > 0) { + GRN_TEXT_PUTS(ctx, &flags, "|"); + } + GRN_TEXT_PUTS(ctx, &flags, "CUSTOM_NAME"); + } + + grn_ctx_output_str(ctx, GRN_TEXT_VALUE(&flags), GRN_TEXT_LEN(&flags)); + + GRN_OBJ_FIN(ctx, &flags); +} + +static grn_obj * +command_object_list(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_db *db; + uint32_t n_objects = 0; + grn_obj vector; + + db = (grn_db *)grn_ctx_db(ctx); + if (!db->specs) { + grn_ctx_output_map_open(ctx, "objects", n_objects); + grn_ctx_output_map_close(ctx); + return NULL; + } + + GRN_TABLE_EACH_BEGIN_FLAGS(ctx, (grn_obj *)db, cursor, id, + GRN_CURSOR_BY_ID | GRN_CURSOR_ASCENDING) { + grn_io_win jw; + uint32_t value_len; + char *value; + + value = grn_ja_ref(ctx, db->specs, id, &jw, &value_len); + if (value) { + n_objects++; + grn_ja_unref(ctx, &jw); + } + } GRN_TABLE_EACH_END(ctx, cursor); + + GRN_OBJ_INIT(&vector, GRN_VECTOR, 0, GRN_DB_TEXT); + + grn_ctx_output_map_open(ctx, "objects", n_objects); + GRN_TABLE_EACH_BEGIN_FLAGS(ctx, (grn_obj *)db, cursor, id, + GRN_CURSOR_BY_ID | GRN_CURSOR_ASCENDING) { + void *name; + int name_size; + grn_io_win jw; + uint32_t value_len; + char *value; + unsigned int n_elements; + + value = grn_ja_ref(ctx, db->specs, id, &jw, &value_len); + if (!value) { + continue; + } + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + + grn_ctx_output_str(ctx, name, name_size); + + GRN_BULK_REWIND(&vector); + if (grn_vector_decode(ctx, &vector, value, value_len) != GRN_SUCCESS) { + grn_ctx_output_map_open(ctx, "object", 4); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_int64(ctx, id); + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_str(ctx, name, name_size); + grn_ctx_output_cstr(ctx, "opened"); + grn_ctx_output_bool(ctx, grn_ctx_is_opened(ctx, id)); + grn_ctx_output_cstr(ctx, "value_size"); + grn_ctx_output_uint64(ctx, value_len); + } + grn_ctx_output_map_close(ctx); + goto next; + } + + n_elements = grn_vector_size(ctx, &vector); + + { + uint32_t element_size; + grn_obj_spec *spec; + uint32_t n_properties = 8; + grn_bool need_sources = GRN_FALSE; + grn_bool need_token_filters = GRN_FALSE; + + element_size = grn_vector_get_element(ctx, + &vector, + GRN_SERIALIZED_SPEC_INDEX_SPEC, + (const char **)&spec, + NULL, + NULL); + if (element_size == 0) { + grn_ctx_output_map_open(ctx, "object", 4); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_int64(ctx, id); + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_str(ctx, name, name_size); + grn_ctx_output_cstr(ctx, "opened"); + grn_ctx_output_bool(ctx, grn_ctx_is_opened(ctx, id)); + grn_ctx_output_cstr(ctx, "n_elements"); + grn_ctx_output_uint64(ctx, n_elements); + } + grn_ctx_output_map_close(ctx); + goto next; + } + + switch (spec->header.type) { + case GRN_COLUMN_INDEX : + need_sources = GRN_TRUE; + n_properties++; + break; + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_NO_KEY : + need_token_filters = GRN_TRUE; + n_properties++; + break; + } + grn_ctx_output_map_open(ctx, "object", n_properties); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, id); + + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_str(ctx, name, name_size); + + grn_ctx_output_cstr(ctx, "opened"); + grn_ctx_output_bool(ctx, grn_ctx_is_opened(ctx, id)); + + grn_ctx_output_cstr(ctx, "n_elements"); + grn_ctx_output_uint64(ctx, n_elements); + + grn_ctx_output_cstr(ctx, "type"); + grn_ctx_output_map_open(ctx, "type", 2); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, spec->header.type); + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_cstr(ctx, grn_obj_type_to_string(spec->header.type)); + } + grn_ctx_output_map_close(ctx); + + grn_ctx_output_cstr(ctx, "flags"); + grn_ctx_output_map_open(ctx, "flags", 2); + { + grn_ctx_output_cstr(ctx, "value"); + grn_ctx_output_uint64(ctx, spec->header.flags); + grn_ctx_output_cstr(ctx, "names"); + command_object_list_dump_flags(ctx, spec); + } + grn_ctx_output_map_close(ctx); + + grn_ctx_output_cstr(ctx, "path"); + if (spec->header.flags & GRN_OBJ_CUSTOM_NAME) { + const char *path; + uint32_t path_size; + path_size = grn_vector_get_element(ctx, + &vector, + GRN_SERIALIZED_SPEC_INDEX_PATH, + &path, + NULL, + NULL); + grn_ctx_output_str(ctx, path, path_size); + } else { + switch (spec->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_INDEX : + { + char path[PATH_MAX]; + grn_db_generate_pathname(ctx, (grn_obj *)db, id, path); + grn_ctx_output_cstr(ctx, path); + } + break; + default : + grn_ctx_output_null(ctx); + break; + } + } + + switch (spec->header.type) { + case GRN_TYPE : + grn_ctx_output_cstr(ctx, "size"); + grn_ctx_output_uint64(ctx, spec->range); + break; + case GRN_PROC : + grn_ctx_output_cstr(ctx, "plugin_id"); + grn_ctx_output_uint64(ctx, spec->range); + break; + default : + grn_ctx_output_cstr(ctx, "range"); + grn_ctx_output_map_open(ctx, "range", 2); + { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + name_size = grn_table_get_key(ctx, + (grn_obj *)db, + spec->range, + name, + GRN_TABLE_MAX_KEY_SIZE); + + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, spec->range); + + grn_ctx_output_cstr(ctx, "name"); + if (name_size == 0) { + grn_ctx_output_null(ctx); + } else { + grn_ctx_output_str(ctx, name, name_size); + } + } + grn_ctx_output_map_close(ctx); + break; + } + + if (need_sources) { + const grn_id *source_ids; + uint32_t n_source_ids; + uint32_t i; + + if (n_elements > GRN_SERIALIZED_SPEC_INDEX_SOURCE) { + uint32_t element_size; + + element_size = grn_vector_get_element(ctx, + &vector, + GRN_SERIALIZED_SPEC_INDEX_SOURCE, + (const char **)&source_ids, + NULL, + NULL); + n_source_ids = element_size / sizeof(grn_id); + } else { + source_ids = NULL; + n_source_ids = 0; + } + + grn_ctx_output_cstr(ctx, "sources"); + grn_ctx_output_array_open(ctx, "sources", n_source_ids); + for (i = 0; i < n_source_ids; i++) { + grn_id source_id; + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + source_id = source_ids[i]; + name_size = grn_table_get_key(ctx, + (grn_obj *)db, + source_id, + name, + GRN_TABLE_MAX_KEY_SIZE); + + grn_ctx_output_map_open(ctx, "source", 2); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, source_id); + + grn_ctx_output_cstr(ctx, "name"); + if (name_size == 0) { + grn_ctx_output_null(ctx); + } else { + grn_ctx_output_str(ctx, name, name_size); + } + } + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_array_close(ctx); + } + + if (need_token_filters) { + const grn_id *token_filter_ids; + uint32_t n_token_filter_ids; + uint32_t i; + + if (n_elements > GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS) { + uint32_t element_size; + + element_size = grn_vector_get_element(ctx, + &vector, + GRN_SERIALIZED_SPEC_INDEX_TOKEN_FILTERS, + (const char **)&token_filter_ids, + NULL, + NULL); + n_token_filter_ids = element_size / sizeof(grn_id); + } else { + token_filter_ids = NULL; + n_token_filter_ids = 0; + } + + grn_ctx_output_cstr(ctx, "token_filters"); + grn_ctx_output_array_open(ctx, "token_filters", n_token_filter_ids); + for (i = 0; i < n_token_filter_ids; i++) { + grn_id token_filter_id; + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + token_filter_id = token_filter_ids[i]; + name_size = grn_table_get_key(ctx, + (grn_obj *)db, + token_filter_id, + name, + GRN_TABLE_MAX_KEY_SIZE); + + grn_ctx_output_map_open(ctx, "token_filter", 2); + { + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_uint64(ctx, token_filter_id); + + grn_ctx_output_cstr(ctx, "name"); + if (name_size == 0) { + grn_ctx_output_null(ctx); + } else { + grn_ctx_output_str(ctx, name, name_size); + } + } + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_array_close(ctx); + } + } + grn_ctx_output_map_close(ctx); + } + + next : + grn_ja_unref(ctx, &jw); + } GRN_TABLE_EACH_END(ctx, cursor); + grn_ctx_output_map_close(ctx); + + GRN_OBJ_FIN(ctx, &vector); + + return NULL; +} + +void +grn_proc_init_object_list(grn_ctx *ctx) +{ + grn_plugin_command_create(ctx, + "object_list", -1, + command_object_list, + 0, + NULL); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_query.c b/storage/mroonga/vendor/groonga/lib/proc/proc_query.c new file mode 100644 index 00000000..6dcf63e1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_query.c @@ -0,0 +1,118 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" + +#include + +static grn_obj * +command_query_expand(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + const char *expander; + size_t expander_size; + const char *query; + size_t query_size; + const char *flags_raw; + size_t flags_raw_size; + grn_expr_flags flags = GRN_EXPR_SYNTAX_QUERY; + const char *term_column; + size_t term_column_size; + const char *expanded_term_column; + size_t expanded_term_column_size; + grn_obj expanded_query; + + expander = grn_plugin_proc_get_var_string(ctx, + user_data, + "expander", + -1, + &expander_size); + query = grn_plugin_proc_get_var_string(ctx, + user_data, + "query", + -1, + &query_size); + flags_raw = grn_plugin_proc_get_var_string(ctx, + user_data, + "flags", + -1, + &flags_raw_size); + term_column = grn_plugin_proc_get_var_string(ctx, + user_data, + "term_column", + -1, + &term_column_size); + expanded_term_column = + grn_plugin_proc_get_var_string(ctx, + user_data, + "expanded_term_column", + -1, + &expanded_term_column_size); + + if (flags_raw_size > 0) { + flags |= grn_proc_expr_query_flags_parse(ctx, + flags_raw, + flags_raw_size, + "[query][expand]"); + } else { + flags |= GRN_EXPR_ALLOW_PRAGMA | GRN_EXPR_ALLOW_COLUMN; + } + + if (ctx->rc != GRN_SUCCESS) { + return NULL; + } + + GRN_TEXT_INIT(&expanded_query, 0); + grn_proc_syntax_expand_query(ctx, + query, + query_size, + flags, + expander, + expander_size, + term_column, + term_column_size, + expanded_term_column, + expanded_term_column_size, + &expanded_query, + "[query][expand]"); + if (ctx->rc == GRN_SUCCESS) { + grn_ctx_output_str(ctx, + GRN_TEXT_VALUE(&expanded_query), + GRN_TEXT_LEN(&expanded_query)); + } + GRN_OBJ_FIN(ctx, &expanded_query); + + return NULL; +} + +void +grn_proc_init_query_expand(grn_ctx *ctx) +{ + grn_expr_var vars[5]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "expander", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "query", -1); + grn_plugin_expr_var_init(ctx, &(vars[2]), "flags", -1); + grn_plugin_expr_var_init(ctx, &(vars[3]), "term_column", -1); + grn_plugin_expr_var_init(ctx, &(vars[4]), "expanded_term_column", -1); + grn_plugin_command_create(ctx, + "query_expand", -1, + command_query_expand, + 5, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_query_log_flags.c b/storage/mroonga/vendor/groonga/lib/proc/proc_query_log_flags.c new file mode 100644 index 00000000..b05d1abf --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_query_log_flags.c @@ -0,0 +1,220 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" + +#include + +static grn_obj * +command_query_log_flags_get(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + unsigned int current_flags; + grn_obj inspected_flags; + + current_flags = grn_query_logger_get_flags(ctx); + GRN_TEXT_INIT(&inspected_flags, 0); + + grn_inspect_query_log_flags(ctx, &inspected_flags,current_flags); + grn_ctx_output_str(ctx, + GRN_TEXT_VALUE(&inspected_flags), + GRN_TEXT_LEN(&inspected_flags)); + + GRN_OBJ_FIN(ctx, &inspected_flags); + + return NULL; +} + +void +grn_proc_init_query_log_flags_get(grn_ctx *ctx) +{ + grn_plugin_command_create(ctx, + "query_log_flags_get", -1, + command_query_log_flags_get, + 0, + NULL); +} + +typedef enum { + UPDATE_SET, + UPDATE_ADD, + UPDATE_REMOVE +} grn_query_log_flags_update_mode; + +static void +grn_query_log_flags_update(grn_ctx *ctx, + grn_obj *flags_text, + grn_query_log_flags_update_mode mode, + const char *error_message_tag) +{ + unsigned int previous_flags; + unsigned int flags = 0; + + previous_flags = grn_query_logger_get_flags(ctx); + if (GRN_TEXT_LEN(flags_text) == 0) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "%s no query log flags", + error_message_tag); + grn_ctx_output_null(ctx); + return; + } + + if (!grn_query_log_flags_parse(GRN_TEXT_VALUE(flags_text), + GRN_TEXT_LEN(flags_text), + &flags)) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "%s invalid query log flags: <%.*s>", + error_message_tag, + (int)GRN_TEXT_LEN(flags_text), + GRN_TEXT_VALUE(flags_text)); + grn_ctx_output_null(ctx); + return; + } + + switch (mode) { + case UPDATE_SET : + grn_query_logger_set_flags(ctx, flags); + break; + case UPDATE_ADD : + grn_query_logger_add_flags(ctx, flags); + break; + case UPDATE_REMOVE : + grn_query_logger_remove_flags(ctx, flags); + break; + } + + { + unsigned int current_flags; + grn_obj inspected_flags; + + current_flags = grn_query_logger_get_flags(ctx); + GRN_TEXT_INIT(&inspected_flags, 0); + + grn_ctx_output_map_open(ctx, "query_log_flags", 2); + + grn_inspect_query_log_flags(ctx, &inspected_flags, previous_flags); + grn_ctx_output_cstr(ctx, "previous"); + grn_ctx_output_str(ctx, + GRN_TEXT_VALUE(&inspected_flags), + GRN_TEXT_LEN(&inspected_flags)); + + GRN_BULK_REWIND(&inspected_flags); + grn_inspect_query_log_flags(ctx, &inspected_flags, current_flags); + grn_ctx_output_cstr(ctx, "current"); + grn_ctx_output_str(ctx, + GRN_TEXT_VALUE(&inspected_flags), + GRN_TEXT_LEN(&inspected_flags)); + + grn_ctx_output_map_close(ctx); + + GRN_OBJ_FIN(ctx, &inspected_flags); + } + + return; +} + +static grn_obj * +command_query_log_flags_set(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *flags_text; + + flags_text = grn_plugin_proc_get_var(ctx, user_data, "flags", -1); + grn_query_log_flags_update(ctx, + flags_text, + UPDATE_SET, + "[query-log][flags][set]"); + return NULL; +} + +void +grn_proc_init_query_log_flags_set(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "flags", -1); + grn_plugin_command_create(ctx, + "query_log_flags_set", -1, + command_query_log_flags_set, + 1, + vars); +} + +static grn_obj * +command_query_log_flags_add(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *flags_text; + + flags_text = grn_plugin_proc_get_var(ctx, user_data, "flags", -1); + grn_query_log_flags_update(ctx, + flags_text, + UPDATE_ADD, + "[query-log][flags][add]"); + return NULL; +} + +void +grn_proc_init_query_log_flags_add(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "flags", -1); + grn_plugin_command_create(ctx, + "query_log_flags_add", -1, + command_query_log_flags_add, + 1, + vars); +} + +static grn_obj * +command_query_log_flags_remove(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *flags_text; + + flags_text = grn_plugin_proc_get_var(ctx, user_data, "flags", -1); + grn_query_log_flags_update(ctx, + flags_text, + UPDATE_REMOVE, + "[query-log][flags][remove]"); + return NULL; +} + +void +grn_proc_init_query_log_flags_remove(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "flags", -1); + grn_plugin_command_create(ctx, + "query_log_flags_remove", -1, + command_query_log_flags_remove, + 1, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_schema.c b/storage/mroonga/vendor/groonga/lib/proc/proc_schema.c new file mode 100644 index 00000000..061c145a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_schema.c @@ -0,0 +1,1226 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" + +#include "../grn_db.h" + +#include + +typedef struct { + grn_bool is_close_opened_object_mode; +} grn_schema_data; + +static void +command_schema_output_id(grn_ctx *ctx, grn_obj *obj) +{ + if (obj) { + grn_id id; + id = grn_obj_id(ctx, obj); + grn_ctx_output_uint64(ctx, id); + } else { + grn_ctx_output_null(ctx); + } +} + +static void +command_schema_output_name(grn_ctx *ctx, grn_obj *obj) +{ + if (obj) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int name_size; + name_size = grn_obj_name(ctx, obj, name, GRN_TABLE_MAX_KEY_SIZE); + grn_ctx_output_str(ctx, name, name_size); + } else { + grn_ctx_output_null(ctx); + } +} + +static void +command_schema_output_column_name(grn_ctx *ctx, grn_obj *column) +{ + char name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int name_size; + name_size = grn_column_name(ctx, column, name, GRN_TABLE_MAX_KEY_SIZE); + grn_ctx_output_str(ctx, name, name_size); +} + +static void +command_schema_output_type(grn_ctx *ctx, const char *type_label, grn_obj *type) +{ + if (!type) { + grn_ctx_output_null(ctx); + return; + } + + grn_ctx_output_map_open(ctx, type_label, 3); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, type); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_name(ctx, type); + + grn_ctx_output_cstr(ctx, "type"); + if (grn_obj_is_table(ctx, type)) { + grn_ctx_output_cstr(ctx, "reference"); + } else { + grn_ctx_output_cstr(ctx, "type"); + } + grn_ctx_output_map_close(ctx); +} + +static void +command_schema_output_key_type(grn_ctx *ctx, grn_obj *key_type) +{ + command_schema_output_type(ctx, "key_type", key_type); +} + +static void +command_schema_output_value_type(grn_ctx *ctx, grn_obj *value_type) +{ + command_schema_output_type(ctx, "value_type", value_type); +} + +static void +command_schema_output_command(grn_ctx *ctx, + const char *command_name, + grn_obj *arguments) +{ + grn_ctx_output_map_open(ctx, "command", 3); + + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_cstr(ctx, command_name); + + grn_ctx_output_cstr(ctx, "arguments"); + { + int i, n; + + n = grn_vector_size(ctx, arguments); + grn_ctx_output_map_open(ctx, "arguments", n / 2); + for (i = 0; i < n; i += 2) { + const char *name; + unsigned int name_size; + const char *value; + unsigned int value_size; + + name_size = grn_vector_get_element(ctx, arguments, i, &name, + NULL, NULL); + value_size = grn_vector_get_element(ctx, arguments, i + 1, &value, + NULL, NULL); + grn_ctx_output_str(ctx, name, name_size); + grn_ctx_output_str(ctx, value, value_size); + } + grn_ctx_output_map_close(ctx); + } + + grn_ctx_output_cstr(ctx, "command_line"); + { + int i, n; + grn_obj command_line; + + GRN_TEXT_INIT(&command_line, 0); + GRN_TEXT_PUTS(ctx, &command_line, command_name); + n = grn_vector_size(ctx, arguments); + for (i = 0; i < n; i += 2) { + const char *name; + unsigned int name_size; + const char *value; + unsigned int value_size; + + name_size = grn_vector_get_element(ctx, arguments, i, &name, + NULL, NULL); + value_size = grn_vector_get_element(ctx, arguments, i + 1, &value, + NULL, NULL); + grn_text_printf(ctx, &command_line, + " --%.*s %.*s", + name_size, name, + value_size, value); + } + grn_ctx_output_str(ctx, + GRN_TEXT_VALUE(&command_line), + GRN_TEXT_LEN(&command_line)); + GRN_OBJ_FIN(ctx, &command_line); + } + + grn_ctx_output_map_close(ctx); +} + +static void +command_schema_output_plugins(grn_ctx *ctx) +{ + grn_obj plugin_names; + unsigned int i, n; + + GRN_TEXT_INIT(&plugin_names, GRN_OBJ_VECTOR); + + grn_plugin_get_names(ctx, &plugin_names); + + grn_ctx_output_cstr(ctx, "plugins"); + + n = grn_vector_size(ctx, &plugin_names); + grn_ctx_output_map_open(ctx, "plugins", n); + for (i = 0; i < n; i++) { + const char *name; + unsigned int name_size; + + name_size = grn_vector_get_element(ctx, &plugin_names, i, &name, NULL, NULL); + grn_ctx_output_str(ctx, name, name_size); + + grn_ctx_output_map_open(ctx, "plugin", 1); + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_str(ctx, name, name_size); + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_map_close(ctx); + + GRN_OBJ_FIN(ctx, &plugin_names); +} + +static void +command_schema_output_types(grn_ctx *ctx) +{ + unsigned int n_types; + + n_types = 0; + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + if (grn_id_is_builtin_type(ctx, id)) { + n_types++; + } + } GRN_DB_EACH_END(ctx, cursor); + + grn_ctx_output_cstr(ctx, "types"); + + grn_ctx_output_map_open(ctx, "types", n_types); + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + grn_obj *type; + + if (!grn_id_is_builtin_type(ctx, id)) { + continue; + } + + type = grn_ctx_at(ctx, id); + + command_schema_output_name(ctx, type); + + grn_ctx_output_map_open(ctx, "type", 5); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, type); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_name(ctx, type); + + grn_ctx_output_cstr(ctx, "size"); + grn_ctx_output_int64(ctx, grn_type_size(ctx, type)); + + grn_ctx_output_cstr(ctx, "can_be_key_type"); + grn_ctx_output_bool(ctx, grn_type_size(ctx, type) <= GRN_TABLE_MAX_KEY_SIZE); + + grn_ctx_output_cstr(ctx, "can_be_value_type"); + grn_ctx_output_bool(ctx, !(type->header.flags & GRN_OBJ_KEY_VAR_SIZE)); + + grn_ctx_output_map_close(ctx); + } GRN_DB_EACH_END(ctx, cursor); + grn_ctx_output_map_close(ctx); +} + +static void +command_schema_output_tokenizers(grn_ctx *ctx, grn_schema_data *data) +{ + grn_obj tokenizer_ids; + unsigned int i, n; + + GRN_RECORD_INIT(&tokenizer_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + void *name; + int name_size; + grn_obj *object; + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (data->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + object = grn_ctx_at(ctx, id); + if (object) { + if (grn_obj_is_tokenizer_proc(ctx, object)) { + GRN_RECORD_PUT(ctx, &tokenizer_ids, id); + } + } else { + /* XXX: this clause is executed when MeCab tokenizer is enabled in + database but the groonga isn't supported MeCab. + We should return error mesage about it and error exit status + but it's too difficult for this architecture. :< */ + GRN_PLUGIN_CLEAR_ERROR(ctx); + } + + if (data->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_DB_EACH_END(ctx, cursor); + + grn_ctx_output_cstr(ctx, "tokenizers"); + + n = GRN_BULK_VSIZE(&tokenizer_ids) / sizeof(grn_id); + grn_ctx_output_map_open(ctx, "tokenizers", n); + for (i = 0; i < n; i++) { + grn_id tokenizer_id; + grn_obj *tokenizer; + + tokenizer_id = GRN_RECORD_VALUE_AT(&tokenizer_ids, i); + tokenizer = grn_ctx_at(ctx, tokenizer_id); + + command_schema_output_name(ctx, tokenizer); + + grn_ctx_output_map_open(ctx, "tokenizer", 2); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, tokenizer); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_name(ctx, tokenizer); + + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_map_close(ctx); + + GRN_OBJ_FIN(ctx, &tokenizer_ids); +} + +static void +command_schema_output_normalizers(grn_ctx *ctx, grn_schema_data *data) +{ + grn_obj normalizer_ids; + unsigned int i, n; + + GRN_RECORD_INIT(&normalizer_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + void *name; + int name_size; + grn_obj *object; + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (data->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + object = grn_ctx_at(ctx, id); + if (object) { + if (grn_obj_is_normalizer_proc(ctx, object)) { + GRN_RECORD_PUT(ctx, &normalizer_ids, id); + } + } else { + /* XXX: this clause is executed when MeCab normalizer is enabled in + database but the groonga isn't supported MeCab. + We should return error mesage about it and error exit status + but it's too difficult for this architecture. :< */ + GRN_PLUGIN_CLEAR_ERROR(ctx); + } + + if (data->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_DB_EACH_END(ctx, cursor); + + grn_ctx_output_cstr(ctx, "normalizers"); + + n = GRN_BULK_VSIZE(&normalizer_ids) / sizeof(grn_id); + grn_ctx_output_map_open(ctx, "normalizers", n); + for (i = 0; i < n; i++) { + grn_id normalizer_id; + grn_obj *normalizer; + + normalizer_id = GRN_RECORD_VALUE_AT(&normalizer_ids, i); + normalizer = grn_ctx_at(ctx, normalizer_id); + + command_schema_output_name(ctx, normalizer); + + grn_ctx_output_map_open(ctx, "normalizer", 2); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, normalizer); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_name(ctx, normalizer); + + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_map_close(ctx); + + GRN_OBJ_FIN(ctx, &normalizer_ids); +} + +static void +command_schema_output_token_filters(grn_ctx *ctx, grn_schema_data *data) +{ + grn_obj token_filter_ids; + unsigned int i, n; + + GRN_RECORD_INIT(&token_filter_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + void *name; + int name_size; + grn_obj *object; + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (data->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + object = grn_ctx_at(ctx, id); + if (object) { + if (grn_obj_is_token_filter_proc(ctx, object)) { + GRN_RECORD_PUT(ctx, &token_filter_ids, id); + } + } else { + /* XXX: this clause is executed when MeCab normalizer is enabled in + database but the groonga isn't supported MeCab. + We should return error mesage about it and error exit status + but it's too difficult for this architecture. :< */ + GRN_PLUGIN_CLEAR_ERROR(ctx); + } + + if (data->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_DB_EACH_END(ctx, cursor); + + grn_ctx_output_cstr(ctx, "token_filters"); + + n = GRN_BULK_VSIZE(&token_filter_ids) / sizeof(grn_id); + grn_ctx_output_map_open(ctx, "token_filters", n); + for (i = 0; i < n; i++) { + grn_id token_filter_id; + grn_obj *token_filter; + + token_filter_id = GRN_RECORD_VALUE_AT(&token_filter_ids, i); + token_filter = grn_ctx_at(ctx, token_filter_id); + + command_schema_output_name(ctx, token_filter); + + grn_ctx_output_map_open(ctx, "token_filter", 2); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, token_filter); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_name(ctx, token_filter); + + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_map_close(ctx); + + GRN_OBJ_FIN(ctx, &token_filter_ids); +} + +static const char * +command_schema_table_type_name(grn_ctx *ctx, grn_obj *table) +{ + const char *name = "unknown"; + + switch (table->header.type) { + case GRN_TABLE_NO_KEY : + name = "array"; + break; + case GRN_TABLE_HASH_KEY : + name = "hash table"; + break; + case GRN_TABLE_PAT_KEY : + name = "patricia trie"; + break; + case GRN_TABLE_DAT_KEY : + name = "double array trie"; + break; + default : + break; + } + + return name; +} + +static void +command_schema_table_output_key_type(grn_ctx *ctx, grn_obj *table) +{ + grn_obj *key_type = NULL; + + if (table->header.type != GRN_TABLE_NO_KEY && + table->header.domain != GRN_ID_NIL) { + key_type = grn_ctx_at(ctx, table->header.domain); + } + + command_schema_output_key_type(ctx, key_type); +} + +static void +command_schema_table_output_value_type(grn_ctx *ctx, grn_obj *table) +{ + grn_obj *value_type = NULL; + grn_id range = GRN_ID_NIL; + + if (table->header.type != GRN_TABLE_DAT_KEY) { + range = grn_obj_get_range(ctx, table); + } + if (range != GRN_ID_NIL) { + value_type = grn_ctx_at(ctx, range); + } + + command_schema_output_value_type(ctx, value_type); +} + +static void +command_schema_table_output_tokenizer(grn_ctx *ctx, grn_obj *table) +{ + grn_obj *tokenizer; + + tokenizer = grn_obj_get_info(ctx, table, GRN_INFO_DEFAULT_TOKENIZER, NULL); + if (!tokenizer) { + grn_ctx_output_null(ctx); + return; + } + + grn_ctx_output_map_open(ctx, "tokenizer", 2); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, tokenizer); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_name(ctx, tokenizer); + + grn_ctx_output_map_close(ctx); +} + +static void +command_schema_table_output_normalizer(grn_ctx *ctx, grn_obj *table) +{ + grn_obj *normalizer; + + normalizer = grn_obj_get_info(ctx, table, GRN_INFO_NORMALIZER, NULL); + if (!normalizer) { + grn_ctx_output_null(ctx); + return; + } + + grn_ctx_output_map_open(ctx, "normalizer", 2); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, normalizer); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_name(ctx, normalizer); + + grn_ctx_output_map_close(ctx); +} + +static void +command_schema_table_output_token_filters(grn_ctx *ctx, grn_obj *table) +{ + grn_obj token_filters; + int i, n; + + GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, GRN_DB_OBJECT); + if (table->header.type != GRN_TABLE_NO_KEY) { + grn_obj_get_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); + } + + n = GRN_BULK_VSIZE(&token_filters) / sizeof(grn_obj *); + grn_ctx_output_array_open(ctx, "token_filters", n); + for (i = 0; i < n; i++) { + grn_obj *token_filter; + + token_filter = GRN_PTR_VALUE_AT(&token_filters, i); + + grn_ctx_output_map_open(ctx, "token_filter", 2); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, token_filter); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_name(ctx, token_filter); + + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_array_close(ctx); + + GRN_OBJ_FIN(ctx, &token_filters); +} + +static void +command_schema_table_command_collect_arguments(grn_ctx *ctx, + grn_obj *table, + grn_obj *arguments) +{ +#define ADD(name_, value_) \ + grn_vector_add_element(ctx, arguments, \ + name_, strlen(name_), \ + 0, GRN_DB_TEXT); \ + grn_vector_add_element(ctx, arguments, \ + value_, strlen(value_), \ + 0, GRN_DB_TEXT) + +#define ADD_OBJECT_NAME(name_, object_) do { \ + char object_name[GRN_TABLE_MAX_KEY_SIZE]; \ + unsigned int object_name_size; \ + object_name_size = grn_obj_name(ctx, object_, \ + object_name, \ + GRN_TABLE_MAX_KEY_SIZE); \ + object_name[object_name_size] = '\0'; \ + ADD(name_, object_name); \ + } while (GRN_FALSE) + + ADD_OBJECT_NAME("name", table); + + { + grn_obj flags; + grn_table_flags table_flags; + grn_table_flags ignored_flags = GRN_OBJ_KEY_NORMALIZE | GRN_OBJ_PERSISTENT; + GRN_TEXT_INIT(&flags, 0); + grn_table_get_info(ctx, table, &table_flags, NULL, NULL, NULL, NULL); + grn_dump_table_create_flags(ctx, + table_flags & ~ignored_flags, + &flags); + GRN_TEXT_PUTC(ctx, &flags, '\0'); + ADD("flags", GRN_TEXT_VALUE(&flags)); + GRN_OBJ_FIN(ctx, &flags); + } + + { + grn_obj *key_type = NULL; + + if (table->header.type != GRN_TABLE_NO_KEY && + table->header.domain != GRN_ID_NIL) { + key_type = grn_ctx_at(ctx, table->header.domain); + } + if (key_type) { + ADD_OBJECT_NAME("key_type", key_type); + } + } + + { + grn_obj *value_type = NULL; + grn_id range = GRN_ID_NIL; + + if (table->header.type != GRN_TABLE_DAT_KEY) { + range = grn_obj_get_range(ctx, table); + } + if (range != GRN_ID_NIL) { + value_type = grn_ctx_at(ctx, range); + } + if (value_type) { + ADD_OBJECT_NAME("value_type", value_type); + } + } + + { + grn_obj *tokenizer; + tokenizer = grn_obj_get_info(ctx, table, GRN_INFO_DEFAULT_TOKENIZER, NULL); + if (tokenizer) { + ADD_OBJECT_NAME("default_tokenizer", tokenizer); + } + } + + { + grn_obj *normalizer; + normalizer = grn_obj_get_info(ctx, table, GRN_INFO_NORMALIZER, NULL); + if (!normalizer && (table->header.flags & GRN_OBJ_KEY_NORMALIZE)) { + normalizer = grn_ctx_get(ctx, "NormalizerAuto", -1); + } + if (normalizer) { + ADD_OBJECT_NAME("normalizer", normalizer); + } + } + + if (table->header.type != GRN_TABLE_NO_KEY) { + grn_obj token_filters; + int n; + + GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, GRN_DB_OBJECT); + grn_obj_get_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); + n = GRN_BULK_VSIZE(&token_filters) / sizeof(grn_obj *); + if (n > 0) { + grn_obj token_filter_names; + int i; + + GRN_TEXT_INIT(&token_filter_names, 0); + for (i = 0; i < n; i++) { + grn_obj *token_filter; + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + token_filter = GRN_PTR_VALUE_AT(&token_filters, i); + name_size = grn_obj_name(ctx, token_filter, + name, GRN_TABLE_MAX_KEY_SIZE); + if (i > 0) { + GRN_TEXT_PUTC(ctx, &token_filter_names, ','); + } + GRN_TEXT_PUT(ctx, &token_filter_names, name, name_size); + } + GRN_TEXT_PUTC(ctx, &token_filter_names, '\0'); + ADD("token_filters", GRN_TEXT_VALUE(&token_filter_names)); + GRN_OBJ_FIN(ctx, &token_filter_names); + } + GRN_OBJ_FIN(ctx, &token_filters); + } + +#undef ADD_OBJECT_NAME +#undef ADD +} + +static void +command_schema_table_output_command(grn_ctx *ctx, grn_obj *table) +{ + grn_obj arguments; + + GRN_TEXT_INIT(&arguments, GRN_OBJ_VECTOR); + command_schema_table_command_collect_arguments(ctx, table, &arguments); + + command_schema_output_command(ctx, "table_create", &arguments); + + GRN_OBJ_FIN(ctx, &arguments); +} + +static void +command_schema_column_output_type(grn_ctx *ctx, grn_obj *column) +{ + switch (column->header.type) { + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + switch (column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { + case GRN_OBJ_COLUMN_SCALAR : + grn_ctx_output_cstr(ctx, "scalar"); + break; + case GRN_OBJ_COLUMN_VECTOR : + grn_ctx_output_cstr(ctx, "vector"); + break; + } + break; + case GRN_COLUMN_INDEX : + grn_ctx_output_cstr(ctx, "index"); + break; + } +} + +static void +command_schema_column_output_value_type(grn_ctx *ctx, grn_obj *column) +{ + grn_obj *value_type; + value_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); + command_schema_output_value_type(ctx, value_type); +} + +static void +command_schema_column_output_compress(grn_ctx *ctx, grn_obj *column) +{ + const char *compress = NULL; + + if (column->header.type != GRN_COLUMN_INDEX) { + switch (column->header.flags & GRN_OBJ_COMPRESS_MASK) { + case GRN_OBJ_COMPRESS_ZLIB : + compress = "zlib"; + break; + case GRN_OBJ_COMPRESS_LZ4 : + compress = "lz4"; + break; + case GRN_OBJ_COMPRESS_ZSTD : + compress = "zstd"; + break; + default : + break; + } + } + + if (compress) { + grn_ctx_output_cstr(ctx, compress); + } else { + grn_ctx_output_null(ctx); + } +} + +static void +command_schema_column_output_sources(grn_ctx *ctx, grn_obj *column) +{ + grn_obj *source_table; + grn_obj source_ids; + unsigned int i, n_ids; + + source_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); + + GRN_RECORD_INIT(&source_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); + + if (column->header.type == GRN_COLUMN_INDEX) { + grn_obj_get_info(ctx, column, GRN_INFO_SOURCE, &source_ids); + } + + n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); + grn_ctx_output_array_open(ctx, "sources", n_ids); + for (i = 0; i < n_ids; i++) { + grn_id source_id; + grn_obj *source; + + source_id = GRN_RECORD_VALUE_AT(&source_ids, i); + source = grn_ctx_at(ctx, source_id); + + grn_ctx_output_map_open(ctx, "source", 4); + + grn_ctx_output_cstr(ctx, "id"); + if (grn_obj_is_table(ctx, source)) { + command_schema_output_id(ctx, NULL); + } else { + command_schema_output_id(ctx, source); + } + + grn_ctx_output_cstr(ctx, "name"); + if (grn_obj_is_table(ctx, source)) { + grn_ctx_output_cstr(ctx, "_key"); + } else { + command_schema_output_column_name(ctx, source); + } + + grn_ctx_output_cstr(ctx, "table"); + command_schema_output_name(ctx, source_table); + + grn_ctx_output_cstr(ctx, "full_name"); + if (grn_obj_is_table(ctx, source)) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int name_size; + name_size = grn_obj_name(ctx, source, name, GRN_TABLE_MAX_KEY_SIZE); + name[name_size] = '\0'; + grn_strcat(name, GRN_TABLE_MAX_KEY_SIZE, "._key"); + grn_ctx_output_cstr(ctx, name); + } else { + command_schema_output_name(ctx, source); + } + + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_array_close(ctx); + + GRN_OBJ_FIN(ctx, &source_ids); +} + +static void +command_schema_output_indexes(grn_ctx *ctx, grn_obj *object) +{ + uint32_t i; + grn_index_datum *index_data = NULL; + uint32_t n_index_data = 0; + + n_index_data = grn_column_get_all_index_data(ctx, object, NULL, 0); + if (n_index_data > 0) { + index_data = GRN_PLUGIN_MALLOC(ctx, + sizeof(grn_index_datum) * n_index_data); + if (!index_data) { + GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, + "[schema] failed to allocate memory for indexes"); + return; + } + grn_column_get_all_index_data(ctx, object, index_data, n_index_data); + } + + grn_ctx_output_array_open(ctx, "indexes", n_index_data); + for (i = 0; i < n_index_data; i++) { + grn_obj *lexicon; + + grn_ctx_output_map_open(ctx, "index", 5); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, index_data[i].index); + + grn_ctx_output_cstr(ctx, "full_name"); + command_schema_output_name(ctx, index_data[i].index); + + grn_ctx_output_cstr(ctx, "table"); + lexicon = grn_ctx_at(ctx, index_data[i].index->header.domain); + command_schema_output_name(ctx, lexicon); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_column_name(ctx, index_data[i].index); + + grn_ctx_output_cstr(ctx, "section"); + grn_ctx_output_uint64(ctx, index_data[i].section); + + grn_ctx_output_map_close(ctx); + } + grn_ctx_output_array_close(ctx); + + if (index_data) { + GRN_PLUGIN_FREE(ctx, index_data); + } +} + +static void +command_schema_column_command_collect_arguments(grn_ctx *ctx, + grn_obj *table, + grn_obj *column, + grn_obj *arguments) +{ +#define ADD(name_, value_) \ + grn_vector_add_element(ctx, arguments, \ + name_, strlen(name_), \ + 0, GRN_DB_TEXT); \ + grn_vector_add_element(ctx, arguments, \ + value_, strlen(value_), \ + 0, GRN_DB_TEXT) + +#define ADD_OBJECT_NAME(name_, object_) do { \ + char object_name[GRN_TABLE_MAX_KEY_SIZE]; \ + unsigned int object_name_size; \ + object_name_size = grn_obj_name(ctx, object_, \ + object_name, \ + GRN_TABLE_MAX_KEY_SIZE); \ + object_name[object_name_size] = '\0'; \ + ADD(name_, object_name); \ + } while (GRN_FALSE) + + ADD_OBJECT_NAME("table", table); + { + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int column_name_size; + column_name_size = grn_column_name(ctx, column, + column_name, GRN_TABLE_MAX_KEY_SIZE); + column_name[column_name_size] = '\0'; + ADD("name", column_name); + } + + { + grn_obj flags; + grn_column_flags column_flags; + + GRN_TEXT_INIT(&flags, 0); + column_flags = grn_column_get_flags(ctx, column); + grn_dump_column_create_flags(ctx, + column_flags & ~GRN_OBJ_PERSISTENT, + &flags); + GRN_TEXT_PUTC(ctx, &flags, '\0'); + ADD("flags", GRN_TEXT_VALUE(&flags)); + GRN_OBJ_FIN(ctx, &flags); + } + + { + grn_obj *value_type; + + value_type = grn_ctx_at(ctx, grn_obj_get_range(ctx, column)); + ADD_OBJECT_NAME("type", value_type); + } + + if (column->header.type == GRN_COLUMN_INDEX) { + grn_obj source_ids; + unsigned int n_ids; + + GRN_RECORD_INIT(&source_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); + grn_obj_get_info(ctx, column, GRN_INFO_SOURCE, &source_ids); + + n_ids = GRN_BULK_VSIZE(&source_ids) / sizeof(grn_id); + if (n_ids > 0) { + grn_obj sources; + unsigned int i; + + GRN_TEXT_INIT(&sources, 0); + for (i = 0; i < n_ids; i++) { + grn_id source_id; + grn_obj *source; + char name[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int name_size; + + source_id = GRN_RECORD_VALUE_AT(&source_ids, i); + source = grn_ctx_at(ctx, source_id); + + if (grn_obj_is_table(ctx, source)) { + grn_strcpy(name, GRN_TABLE_MAX_KEY_SIZE, "_key"); + name_size = strlen(name); + } else { + name_size = grn_column_name(ctx, source, name, GRN_TABLE_MAX_KEY_SIZE); + } + if (i > 0) { + GRN_TEXT_PUTC(ctx, &sources, ','); + } + GRN_TEXT_PUT(ctx, &sources, name, name_size); + } + GRN_TEXT_PUTC(ctx, &sources, '\0'); + ADD("source", GRN_TEXT_VALUE(&sources)); + GRN_OBJ_FIN(ctx, &sources); + } + GRN_OBJ_FIN(ctx, &source_ids); + } + +#undef ADD_OBJECT_NAME +#undef ADD +} + +static void +command_schema_column_output_command(grn_ctx *ctx, + grn_obj *table, + grn_obj *column) +{ + grn_obj arguments; + + GRN_TEXT_INIT(&arguments, GRN_OBJ_VECTOR); + command_schema_column_command_collect_arguments(ctx, table, column, &arguments); + + command_schema_output_command(ctx, "column_create", &arguments); + + GRN_OBJ_FIN(ctx, &arguments); +} + +static void +command_schema_column_output(grn_ctx *ctx, grn_obj *table, grn_obj *column) +{ + if (!column) { + return; + } + + command_schema_output_column_name(ctx, column); + + grn_ctx_output_map_open(ctx, "column", 13); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, column); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_column_name(ctx, column); + + grn_ctx_output_cstr(ctx, "table"); + command_schema_output_name(ctx, table); + + grn_ctx_output_cstr(ctx, "full_name"); + command_schema_output_name(ctx, column); + + grn_ctx_output_cstr(ctx, "type"); + command_schema_column_output_type(ctx, column); + + grn_ctx_output_cstr(ctx, "value_type"); + command_schema_column_output_value_type(ctx, column); + + grn_ctx_output_cstr(ctx, "compress"); + command_schema_column_output_compress(ctx, column); + + grn_ctx_output_cstr(ctx, "section"); + grn_ctx_output_bool(ctx, (column->header.flags & GRN_OBJ_WITH_SECTION) != 0); + + grn_ctx_output_cstr(ctx, "weight"); + grn_ctx_output_bool(ctx, (column->header.flags & GRN_OBJ_WITH_WEIGHT) != 0); + + grn_ctx_output_cstr(ctx, "position"); + grn_ctx_output_bool(ctx, (column->header.flags & GRN_OBJ_WITH_POSITION) != 0); + + grn_ctx_output_cstr(ctx, "sources"); + command_schema_column_output_sources(ctx, column); + + grn_ctx_output_cstr(ctx, "indexes"); + command_schema_output_indexes(ctx, column); + + grn_ctx_output_cstr(ctx, "command"); + command_schema_column_output_command(ctx, table, column); + + grn_ctx_output_map_close(ctx); +} + +static void +command_schema_table_output_columns(grn_ctx *ctx, + grn_obj *table, + grn_schema_data *data) +{ + grn_hash *columns; + + columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); + if (!columns) { + grn_ctx_output_map_open(ctx, "columns", 0); + grn_ctx_output_map_close(ctx); + return; + } + + grn_table_columns(ctx, table, "", 0, (grn_obj *)columns); + grn_ctx_output_map_open(ctx, "columns", grn_hash_size(ctx, columns)); + { + grn_id *key; + GRN_HASH_EACH(ctx, columns, id, &key, NULL, NULL, { + grn_obj *column; + + if (data->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + column = grn_ctx_at(ctx, *key); + command_schema_column_output(ctx, table, column); + + if (data->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + }); + } + grn_ctx_output_map_close(ctx); + grn_hash_close(ctx, columns); +} + +static void +command_schema_output_table(grn_ctx *ctx, + grn_schema_data *data, + grn_obj *table) +{ + command_schema_output_name(ctx, table); + + grn_ctx_output_map_open(ctx, "table", 11); + + grn_ctx_output_cstr(ctx, "id"); + command_schema_output_id(ctx, table); + + grn_ctx_output_cstr(ctx, "name"); + command_schema_output_name(ctx, table); + + grn_ctx_output_cstr(ctx, "type"); + grn_ctx_output_cstr(ctx, command_schema_table_type_name(ctx, table)); + + grn_ctx_output_cstr(ctx, "key_type"); + command_schema_table_output_key_type(ctx, table); + + grn_ctx_output_cstr(ctx, "value_type"); + command_schema_table_output_value_type(ctx, table); + + grn_ctx_output_cstr(ctx, "tokenizer"); + command_schema_table_output_tokenizer(ctx, table); + + grn_ctx_output_cstr(ctx, "normalizer"); + command_schema_table_output_normalizer(ctx, table); + + grn_ctx_output_cstr(ctx, "token_filters"); + command_schema_table_output_token_filters(ctx, table); + + grn_ctx_output_cstr(ctx, "indexes"); + command_schema_output_indexes(ctx, table); + + grn_ctx_output_cstr(ctx, "command"); + command_schema_table_output_command(ctx, table); + + grn_ctx_output_cstr(ctx, "columns"); + command_schema_table_output_columns(ctx, table, data); + + grn_ctx_output_map_close(ctx); +} + +static void +command_schema_output_tables(grn_ctx *ctx, grn_schema_data *data) +{ + grn_obj table_ids; + unsigned int i, n; + + GRN_RECORD_INIT(&table_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); + GRN_DB_EACH_BEGIN_BY_KEY(ctx, cursor, id) { + void *name; + int name_size; + grn_obj *object; + + if (grn_id_is_builtin(ctx, id)) { + continue; + } + + name_size = grn_table_cursor_get_key(ctx, cursor, &name); + if (grn_obj_name_is_column(ctx, name, name_size)) { + continue; + } + + if (data->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + object = grn_ctx_at(ctx, id); + if (!object) { + /* XXX: this clause is executed when MeCab tokenizer is enabled in + database but the groonga isn't supported MeCab. + We should return error mesage about it and error exit status + but it's too difficult for this architecture. :< */ + GRN_PLUGIN_CLEAR_ERROR(ctx); + goto next_loop; + } + + if (grn_obj_is_table(ctx, object)) { + GRN_RECORD_PUT(ctx, &table_ids, id); + } + + next_loop : + if (data->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } GRN_TABLE_EACH_END(ctx, cursor); + + n = GRN_BULK_VSIZE(&table_ids) / sizeof(grn_id); + + grn_ctx_output_cstr(ctx, "tables"); + grn_ctx_output_map_open(ctx, "tables", n); + for (i = 0; i < n; i++) { + grn_id table_id; + grn_obj *table; + + if (data->is_close_opened_object_mode) { + grn_ctx_push_temporary_open_space(ctx); + } + + table_id = GRN_RECORD_VALUE_AT(&table_ids, i); + table = grn_ctx_at(ctx, table_id); + + command_schema_output_table(ctx, data, table); + + if (data->is_close_opened_object_mode) { + grn_ctx_pop_temporary_open_space(ctx); + } + } + grn_ctx_output_map_close(ctx); + + GRN_OBJ_FIN(ctx, &table_ids); +} + +static grn_obj * +command_schema(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_schema_data data; + + data.is_close_opened_object_mode = (grn_thread_get_limit() == 1); + + grn_ctx_output_map_open(ctx, "schema", 6); + command_schema_output_plugins(ctx); + command_schema_output_types(ctx); + command_schema_output_tokenizers(ctx, &data); + command_schema_output_normalizers(ctx, &data); + command_schema_output_token_filters(ctx, &data); + command_schema_output_tables(ctx, &data); + grn_ctx_output_map_close(ctx); + + return NULL; +} + +void +grn_proc_init_schema(grn_ctx *ctx) +{ + grn_plugin_command_create(ctx, + "schema", -1, + command_schema, + 0, + NULL); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_select.c b/storage/mroonga/vendor/groonga/lib/proc/proc_select.c new file mode 100644 index 00000000..a665b1cc --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_select.c @@ -0,0 +1,3809 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" +#include "../grn_raw_string.h" +#include "../grn_expr.h" +#include "../grn_str.h" +#include "../grn_output.h" +#include "../grn_util.h" +#include "../grn_cache.h" +#include "../grn_ii.h" + +#include "../grn_ts.h" + +#include + +#define GRN_SELECT_INTERNAL_VAR_MATCH_COLUMNS "$match_columns" + +#define DEFAULT_DRILLDOWN_LIMIT 10 +#define DEFAULT_DRILLDOWN_OUTPUT_COLUMNS "_key, _nsubrecs" + +typedef enum { + GRN_COLUMN_STAGE_INITIAL, + GRN_COLUMN_STAGE_FILTERED, + GRN_COLUMN_STAGE_OUTPUT +} grn_column_stage; + +typedef struct { + grn_raw_string label; + grn_column_stage stage; + grn_obj *type; + grn_obj_flags flags; + grn_raw_string value; + struct { + grn_raw_string sort_keys; + grn_raw_string group_keys; + } window; +} grn_column_data; + +typedef struct { + grn_hash *initial; + grn_hash *filtered; + grn_hash *output; +} grn_columns; + +typedef struct { + grn_raw_string match_columns; + grn_raw_string query; + grn_raw_string query_expander; + grn_raw_string query_flags; + grn_raw_string filter; + struct { + grn_obj *match_columns; + grn_obj *expression; + } condition; + grn_obj *filtered; +} grn_filter_data; + +typedef struct { + grn_raw_string label; + grn_filter_data filter; + grn_raw_string sort_keys; + grn_raw_string output_columns; + int offset; + int limit; + grn_obj *table; +} grn_slice_data; + +typedef struct { + grn_raw_string label; + grn_raw_string keys; + grn_table_sort_key *parsed_keys; + int n_parsed_keys; + grn_raw_string sort_keys; + grn_raw_string output_columns; + int offset; + int limit; + grn_table_group_flags calc_types; + grn_raw_string calc_target_name; + grn_raw_string filter; + grn_raw_string table_name; + grn_columns columns; + grn_table_group_result result; + grn_obj *filtered_result; +} grn_drilldown_data; + +typedef struct _grn_select_output_formatter grn_select_output_formatter; + +typedef struct { + /* inputs */ + grn_raw_string table; + grn_filter_data filter; + grn_raw_string scorer; + grn_raw_string sort_keys; + grn_raw_string output_columns; + int offset; + int limit; + grn_hash *slices; + grn_drilldown_data drilldown; + grn_hash *drilldowns; + grn_raw_string cache; + grn_raw_string match_escalation_threshold; + grn_raw_string adjuster; + grn_columns columns; + + /* for processing */ + struct { + grn_obj *target; + grn_obj *initial; + grn_obj *result; + grn_obj *sorted; + grn_obj *output; + } tables; + uint16_t cacheable; + uint16_t taintable; + struct { + int n_elements; + grn_select_output_formatter *formatter; + } output; +} grn_select_data; + +typedef void grn_select_output_slices_label_func(grn_ctx *ctx, + grn_select_data *data); +typedef void grn_select_output_slices_open_func(grn_ctx *ctx, + grn_select_data *data, + unsigned int n_result_sets); +typedef void grn_select_output_slices_close_func(grn_ctx *ctx, + grn_select_data *data); +typedef void grn_select_output_slice_label_func(grn_ctx *ctx, + grn_select_data *data, + grn_slice_data *slice); +typedef void grn_select_output_drilldowns_label_func(grn_ctx *ctx, + grn_select_data *data); +typedef void grn_select_output_drilldowns_open_func(grn_ctx *ctx, + grn_select_data *data, + unsigned int n_result_sets); +typedef void grn_select_output_drilldowns_close_func(grn_ctx *ctx, + grn_select_data *data); +typedef void grn_select_output_drilldown_label_func(grn_ctx *ctx, + grn_select_data *data, + grn_drilldown_data *drilldown); + +struct _grn_select_output_formatter { + grn_select_output_slices_label_func *slices_label; + grn_select_output_slices_open_func *slices_open; + grn_select_output_slices_close_func *slices_close; + grn_select_output_slice_label_func *slice_label; + grn_select_output_drilldowns_label_func *drilldowns_label; + grn_select_output_drilldowns_open_func *drilldowns_open; + grn_select_output_drilldowns_close_func *drilldowns_close; + grn_select_output_drilldown_label_func *drilldown_label; +}; + +grn_rc +grn_proc_syntax_expand_query(grn_ctx *ctx, + const char *query, + unsigned int query_len, + grn_expr_flags flags, + const char *query_expander_name, + unsigned int query_expander_name_len, + const char *term_column_name, + unsigned int term_column_name_len, + const char *expanded_term_column_name, + unsigned int expanded_term_column_name_len, + grn_obj *expanded_query, + const char *error_message_tag) +{ + grn_obj *query_expander; + + query_expander = grn_ctx_get(ctx, + query_expander_name, + query_expander_name_len); + if (!query_expander) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "%s nonexistent query expander: <%.*s>", + error_message_tag, + (int)query_expander_name_len, + query_expander_name); + return ctx->rc; + } + + if (expanded_term_column_name_len == 0) { + return grn_expr_syntax_expand_query(ctx, query, query_len, flags, + query_expander, expanded_query); + } + + if (!grn_obj_is_table(ctx, query_expander)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, query_expander); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "%s query expander with expanded term column " + "must be table: <%.*s>", + error_message_tag, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return ctx->rc; + } + + { + grn_obj *term_column = NULL; + grn_obj *expanded_term_column; + + expanded_term_column = grn_obj_column(ctx, + query_expander, + expanded_term_column_name, + expanded_term_column_name_len); + if (!expanded_term_column) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, query_expander); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "%s nonexistent expanded term column: <%.*s>: " + "query expander: <%.*s>", + error_message_tag, + (int)expanded_term_column_name_len, + expanded_term_column_name, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return ctx->rc; + } + + if (term_column_name_len > 0) { + term_column = grn_obj_column(ctx, + query_expander, + term_column_name, + term_column_name_len); + if (!term_column) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, query_expander); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "%s nonexistent term column: <%.*s>: " + "query expander: <%.*s>", + error_message_tag, + (int)term_column_name_len, + term_column_name, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + if (grn_obj_is_accessor(ctx, expanded_term_column)) { + grn_obj_unlink(ctx, expanded_term_column); + } + return ctx->rc; + } + } + + grn_expr_syntax_expand_query_by_table(ctx, + query, query_len, + flags, + term_column, + expanded_term_column, + expanded_query); + if (grn_obj_is_accessor(ctx, term_column)) { + grn_obj_unlink(ctx, term_column); + } + if (grn_obj_is_accessor(ctx, expanded_term_column)) { + grn_obj_unlink(ctx, expanded_term_column); + } + return ctx->rc; + } +} + +static grn_table_group_flags +grn_parse_table_group_calc_types(grn_ctx *ctx, + const char *calc_types, + unsigned int calc_types_len) +{ + grn_table_group_flags flags = 0; + const char *calc_types_end = calc_types + calc_types_len; + + while (calc_types < calc_types_end) { + if (*calc_types == ',' || *calc_types == ' ') { + calc_types += 1; + continue; + } + +#define CHECK_TABLE_GROUP_CALC_TYPE(name)\ + if (((unsigned long) (calc_types_end - calc_types) >= (unsigned long) (sizeof(#name) - 1)) && \ + (!memcmp(calc_types, #name, sizeof(#name) - 1))) {\ + flags |= GRN_TABLE_GROUP_CALC_ ## name;\ + calc_types += sizeof(#name) - 1;\ + continue;\ + } + + CHECK_TABLE_GROUP_CALC_TYPE(COUNT); + CHECK_TABLE_GROUP_CALC_TYPE(MAX); + CHECK_TABLE_GROUP_CALC_TYPE(MIN); + CHECK_TABLE_GROUP_CALC_TYPE(SUM); + CHECK_TABLE_GROUP_CALC_TYPE(AVG); + +#define GRN_TABLE_GROUP_CALC_NONE 0 + CHECK_TABLE_GROUP_CALC_TYPE(NONE); +#undef GRN_TABLE_GROUP_CALC_NONE + + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "invalid table group calc type: <%.*s>", + (int)(calc_types_end - calc_types), + calc_types); + return 0; +#undef CHECK_TABLE_GROUP_CALC_TYPE + } + + return flags; +} + +static const char * +grn_column_stage_name(grn_column_stage stage) +{ + switch (stage) { + case GRN_COLUMN_STAGE_INITIAL : + return "initial"; + case GRN_COLUMN_STAGE_FILTERED : + return "filtered"; + case GRN_COLUMN_STAGE_OUTPUT : + return "output"; + default : + return "unknown"; + } +} + +static grn_bool +grn_column_data_init(grn_ctx *ctx, + const char *label, + size_t label_len, + grn_column_stage stage, + grn_hash **columns) +{ + void *column_raw; + grn_column_data *column; + int added; + + if (!*columns) { + *columns = grn_hash_create(ctx, + NULL, + GRN_TABLE_MAX_KEY_SIZE, + sizeof(grn_column_data), + GRN_OBJ_TABLE_HASH_KEY | + GRN_OBJ_KEY_VAR_SIZE | + GRN_HASH_TINY); + } + if (!*columns) { + return GRN_FALSE; + } + + grn_hash_add(ctx, + *columns, + label, + label_len, + &column_raw, + &added); + if (!added) { + return GRN_TRUE; + } + + column = column_raw; + column->label.value = label; + column->label.length = label_len; + column->stage = stage; + column->type = grn_ctx_at(ctx, GRN_DB_TEXT); + column->flags = GRN_OBJ_COLUMN_SCALAR; + GRN_RAW_STRING_INIT(column->value); + GRN_RAW_STRING_INIT(column->window.sort_keys); + GRN_RAW_STRING_INIT(column->window.group_keys); + + return GRN_TRUE; +} + +static grn_bool +grn_column_data_fill(grn_ctx *ctx, + grn_column_data *column, + grn_obj *type_raw, + grn_obj *flags, + grn_obj *value, + grn_obj *window_sort_keys, + grn_obj *window_group_keys) +{ + if (type_raw && GRN_TEXT_LEN(type_raw) > 0) { + grn_obj *type; + + type = grn_ctx_get(ctx, GRN_TEXT_VALUE(type_raw), GRN_TEXT_LEN(type_raw)); + if (!type) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][columns][%s][%.*s] unknown type: <%.*s>", + grn_column_stage_name(column->stage), + (int)(column->label.length), + column->label.value, + (int)(GRN_TEXT_LEN(type_raw)), + GRN_TEXT_VALUE(type_raw)); + return GRN_FALSE; + } + if (!(grn_obj_is_type(ctx, type) || grn_obj_is_table(ctx, type))) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, type); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][columns][%s][%.*s] invalid type: %.*s", + grn_column_stage_name(column->stage), + (int)(column->label.length), + column->label.value, + (int)(GRN_TEXT_LEN(&inspected)), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + grn_obj_unlink(ctx, type); + return GRN_FALSE; + } + column->type = type; + } + + if (flags && GRN_TEXT_LEN(flags) > 0) { + char error_message_tag[GRN_TABLE_MAX_KEY_SIZE]; + + grn_snprintf(error_message_tag, + GRN_TABLE_MAX_KEY_SIZE, + GRN_TABLE_MAX_KEY_SIZE, + "[select][columns][%s][%.*s]", + grn_column_stage_name(column->stage), + (int)(column->label.length), + column->label.value); + column->flags = + grn_proc_column_parse_flags(ctx, + error_message_tag, + GRN_TEXT_VALUE(flags), + GRN_TEXT_VALUE(flags) + GRN_TEXT_LEN(flags)); + if (ctx->rc != GRN_SUCCESS) { + return GRN_FALSE; + } + } + + GRN_RAW_STRING_FILL(column->value, value); + GRN_RAW_STRING_FILL(column->window.sort_keys, window_sort_keys); + GRN_RAW_STRING_FILL(column->window.group_keys, window_group_keys); + + return GRN_TRUE; +} + +static grn_bool +grn_column_data_collect(grn_ctx *ctx, + grn_user_data *user_data, + grn_hash *columns, + const char *prefix_label, + size_t prefix_label_len) +{ + grn_hash_cursor *cursor = NULL; + + cursor = grn_hash_cursor_open(ctx, columns, + NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + return GRN_FALSE; + } + + while (grn_hash_cursor_next(ctx, cursor)) { + grn_column_data *column; + char key_name[GRN_TABLE_MAX_KEY_SIZE]; + grn_obj *type = NULL; + grn_obj *flags = NULL; + grn_obj *value = NULL; + struct { + grn_obj *sort_keys; + grn_obj *group_keys; + } window; + + window.sort_keys = NULL; + window.group_keys = NULL; + + grn_hash_cursor_get_value(ctx, cursor, (void **)&column); + +#define GET_VAR_RAW(parameter_key, name) \ + if (!name) { \ + grn_snprintf(key_name, \ + GRN_TABLE_MAX_KEY_SIZE, \ + GRN_TABLE_MAX_KEY_SIZE, \ + "%.*s%s[%.*s]." # name, \ + (int)prefix_label_len, \ + prefix_label, \ + parameter_key, \ + (int)(column->label.length), \ + column->label.value); \ + name = grn_plugin_proc_get_var(ctx, user_data, key_name, -1); \ + } + +#define GET_VAR(name) do { \ + GET_VAR_RAW("columns", name); \ + /* For backward compatibility */ \ + GET_VAR_RAW("column", name); \ + } while (GRN_FALSE) + + GET_VAR(type); + GET_VAR(flags); + GET_VAR(value); + GET_VAR(window.sort_keys); + GET_VAR(window.group_keys); + +#undef GET_VAR + +#undef GET_VAR_RAW + + grn_column_data_fill(ctx, column, + type, flags, value, + window.sort_keys, + window.group_keys); + } + grn_hash_cursor_close(ctx, cursor); + return GRN_TRUE; +} + +static void +grn_columns_init(grn_ctx *ctx, grn_columns *columns) +{ + columns->initial = NULL; + columns->filtered = NULL; + columns->output = NULL; +} + +static void +grn_columns_fin(grn_ctx *ctx, grn_columns *columns) +{ + if (columns->initial) { + grn_hash_close(ctx, columns->initial); + } + + if (columns->filtered) { + grn_hash_close(ctx, columns->filtered); + } + + if (columns->output) { + grn_hash_close(ctx, columns->output); + } +} + +static grn_bool +grn_columns_collect(grn_ctx *ctx, + grn_user_data *user_data, + grn_columns *columns, + const char *prefix, + const char *base_prefix, + size_t base_prefix_len) +{ + grn_obj *vars; + grn_table_cursor *cursor; + size_t prefix_len; + const char *suffix = "].stage"; + size_t suffix_len; + + vars = grn_plugin_proc_get_vars(ctx, user_data); + cursor = grn_table_cursor_open(ctx, vars, NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + return GRN_FALSE; + } + + prefix_len = strlen(prefix); + suffix_len = strlen(suffix); + while (grn_table_cursor_next(ctx, cursor)) { + void *key; + char *variable_name; + unsigned int variable_name_len; + char *column_name; + size_t column_name_len; + void *value_raw; + grn_obj *value; + grn_column_stage stage; + grn_hash **target_columns; + + variable_name_len = grn_table_cursor_get_key(ctx, cursor, &key); + variable_name = key; + if (variable_name_len < base_prefix_len + prefix_len + suffix_len + 1) { + continue; + } + + if (base_prefix_len > 0) { + if (memcmp(base_prefix, variable_name, base_prefix_len) != 0) { + continue; + } + } + + if (memcmp(prefix, variable_name + base_prefix_len, prefix_len) != 0) { + continue; + } + + if (memcmp(suffix, + variable_name + (variable_name_len - suffix_len), + suffix_len) != 0) { + continue; + } + + grn_table_cursor_get_value(ctx, cursor, &value_raw); + value = value_raw; + if (GRN_TEXT_EQUAL_CSTRING(value, "initial")) { + stage = GRN_COLUMN_STAGE_INITIAL; + target_columns = &(columns->initial); + } else if (GRN_TEXT_EQUAL_CSTRING(value, "filtered")) { + stage = GRN_COLUMN_STAGE_FILTERED; + target_columns = &(columns->filtered); + } else if (GRN_TEXT_EQUAL_CSTRING(value, "output")) { + stage = GRN_COLUMN_STAGE_OUTPUT; + target_columns = &(columns->output); + } else { + continue; + } + + column_name = variable_name + base_prefix_len + prefix_len; + column_name_len = + variable_name_len - base_prefix_len - prefix_len - suffix_len; + if (!grn_column_data_init(ctx, + column_name, + column_name_len, + stage, + target_columns)) { + grn_table_cursor_close(ctx, cursor); + return GRN_FALSE; + } + } + grn_table_cursor_close(ctx, cursor); + + return GRN_TRUE; +} + +static grn_bool +grn_columns_fill(grn_ctx *ctx, + grn_user_data *user_data, + grn_columns *columns, + const char *prefix, + size_t prefix_length) +{ + if (!grn_columns_collect(ctx, user_data, columns, + "columns[", prefix, prefix_length)) { + return GRN_FALSE; + } + + /* For backward compatibility */ + if (!grn_columns_collect(ctx, user_data, columns, + "column[", prefix, prefix_length)) { + return GRN_FALSE; + } + + if (columns->initial) { + if (!grn_column_data_collect(ctx, + user_data, + columns->initial, + prefix, + prefix_length)) { + return GRN_FALSE; + } + } + + if (columns->filtered) { + if (!grn_column_data_collect(ctx, + user_data, + columns->filtered, + prefix, + prefix_length)) { + return GRN_FALSE; + } + } + + if (columns->output) { + if (!grn_column_data_collect(ctx, + user_data, + columns->output, + prefix, + prefix_length)) { + return GRN_FALSE; + } + } + + return GRN_TRUE; +} + +static void +grn_filter_data_init(grn_ctx *ctx, grn_filter_data *data) +{ + GRN_RAW_STRING_INIT(data->match_columns); + GRN_RAW_STRING_INIT(data->query); + GRN_RAW_STRING_INIT(data->query_expander); + GRN_RAW_STRING_INIT(data->query_flags); + GRN_RAW_STRING_INIT(data->filter); + data->condition.match_columns = NULL; + data->condition.expression = NULL; + data->filtered = NULL; +} + +static void +grn_filter_data_fin(grn_ctx *ctx, grn_filter_data *data) +{ + if (data->filtered) { + grn_obj_unlink(ctx, data->filtered); + } + if (data->condition.expression) { + grn_obj_close(ctx, data->condition.expression); + } + if (data->condition.match_columns) { + grn_obj_close(ctx, data->condition.match_columns); + } +} + +static void +grn_filter_data_fill(grn_ctx *ctx, + grn_filter_data *data, + grn_obj *match_columns, + grn_obj *query, + grn_obj *query_expander, + grn_obj *query_flags, + grn_obj *filter) +{ + GRN_RAW_STRING_FILL(data->match_columns, match_columns); + GRN_RAW_STRING_FILL(data->query, query); + GRN_RAW_STRING_FILL(data->query_expander, query_expander); + GRN_RAW_STRING_FILL(data->query_flags, query_flags); + GRN_RAW_STRING_FILL(data->filter, filter); +} + +static grn_bool +grn_filter_data_execute(grn_ctx *ctx, + grn_filter_data *data, + grn_obj *table, + const char *tag) +{ + grn_obj *variable; + + if (data->query.length == 0 && data->filter.length == 0) { + return GRN_TRUE; + } + + GRN_EXPR_CREATE_FOR_QUERY(ctx, + table, + data->condition.expression, + variable); + if (!data->condition.expression) { + grn_rc rc = ctx->rc; + if (rc == GRN_SUCCESS) { + rc = GRN_NO_MEMORY_AVAILABLE; + } + GRN_PLUGIN_ERROR(ctx, + rc, + "%s[condition] " + "failed to create expression for condition: %s", + tag, + ctx->errbuf); + return GRN_FALSE; + } + + if (data->query.length > 0) { + if (data->match_columns.length > 0) { + GRN_EXPR_CREATE_FOR_QUERY(ctx, + table, + data->condition.match_columns, + variable); + if (!data->condition.match_columns) { + grn_rc rc = ctx->rc; + if (rc == GRN_SUCCESS) { + rc = GRN_NO_MEMORY_AVAILABLE; + } + GRN_PLUGIN_ERROR(ctx, + rc, + "%s[match_columns] " + "failed to create expression for match columns: " + "<%.*s>: %s", + tag, + (int)(data->match_columns.length), + data->match_columns.value, + ctx->errbuf); + return GRN_FALSE; + } + + grn_expr_parse(ctx, + data->condition.match_columns, + data->match_columns.value, + data->match_columns.length, + NULL, GRN_OP_MATCH, GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc != GRN_SUCCESS) { + return GRN_FALSE; + } + } + + { + grn_expr_flags flags; + grn_obj query_expander_buf; + const char *query = data->query.value; + unsigned int query_len = data->query.length; + + flags = GRN_EXPR_SYNTAX_QUERY; + if (data->query_flags.length) { + flags |= grn_proc_expr_query_flags_parse(ctx, + data->query_flags.value, + data->query_flags.length, + tag); + if (ctx->rc != GRN_SUCCESS) { + return GRN_FALSE; + } + } else { + flags |= GRN_EXPR_ALLOW_PRAGMA|GRN_EXPR_ALLOW_COLUMN; + } + + GRN_TEXT_INIT(&query_expander_buf, 0); + if (data->query_expander.length > 0) { + grn_rc rc; + rc = grn_proc_syntax_expand_query(ctx, + data->query.value, + data->query.length, + flags, + data->query_expander.value, + data->query_expander.length, + NULL, 0, + NULL, 0, + &query_expander_buf, + tag); + if (rc == GRN_SUCCESS) { + query = GRN_TEXT_VALUE(&query_expander_buf); + query_len = GRN_TEXT_LEN(&query_expander_buf); + } else { + GRN_OBJ_FIN(ctx, &query_expander_buf); + return GRN_FALSE; + } + } + + grn_expr_parse(ctx, + data->condition.expression, + query, + query_len, + data->condition.match_columns, + GRN_OP_MATCH, + GRN_OP_AND, + flags); + GRN_OBJ_FIN(ctx, &query_expander_buf); + + if (ctx->rc != GRN_SUCCESS) { + return GRN_FALSE; + } + } + } + + if (data->filter.length > 0) { + grn_expr_parse(ctx, + data->condition.expression, + data->filter.value, + data->filter.length, + data->condition.match_columns, + GRN_OP_MATCH, + GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc != GRN_SUCCESS) { + return GRN_FALSE; + } + + if (data->query.length > 0) { + grn_expr_append_op(ctx, data->condition.expression, GRN_OP_AND, 2); + } + + if (ctx->rc != GRN_SUCCESS) { + return GRN_FALSE; + } + } + + data->filtered = grn_table_select(ctx, + table, + data->condition.expression, + NULL, + GRN_OP_OR); + + return ctx->rc == GRN_SUCCESS; +} + +static void +grn_slice_data_init(grn_ctx *ctx, + grn_slice_data *slice, + const char *label, + size_t label_len) +{ + slice->label.value = label; + slice->label.length = label_len; + grn_filter_data_init(ctx, &(slice->filter)); + GRN_RAW_STRING_INIT(slice->sort_keys); + GRN_RAW_STRING_INIT(slice->output_columns); + slice->offset = 0; + slice->limit = GRN_SELECT_DEFAULT_LIMIT; + slice->table = NULL; +} + +static void +grn_slice_data_fin(grn_ctx *ctx, grn_slice_data *slice) +{ + grn_filter_data_fin(ctx, &(slice->filter)); +} + +static void +grn_slice_data_fill(grn_ctx *ctx, + grn_slice_data *slice, + grn_obj *match_columns, + grn_obj *query, + grn_obj *query_expander, + grn_obj *query_flags, + grn_obj *filter, + grn_obj *sort_keys, + grn_obj *output_columns, + grn_obj *offset, + grn_obj *limit) +{ + grn_filter_data_fill(ctx, + &(slice->filter), + match_columns, + query, + query_expander, + query_flags, + filter); + + GRN_RAW_STRING_FILL(slice->sort_keys, sort_keys); + + GRN_RAW_STRING_FILL(slice->output_columns, output_columns); + if (slice->output_columns.length == 0) { + slice->output_columns.value = GRN_SELECT_DEFAULT_OUTPUT_COLUMNS; + slice->output_columns.length = strlen(GRN_SELECT_DEFAULT_OUTPUT_COLUMNS); + } + + slice->offset = grn_proc_option_value_int32(ctx, offset, 0); + slice->limit = grn_proc_option_value_int32(ctx, + limit, + GRN_SELECT_DEFAULT_LIMIT); +} + +static void +grn_drilldown_data_init(grn_ctx *ctx, + grn_drilldown_data *drilldown, + const char *label, + size_t label_len) +{ + drilldown->label.value = label; + drilldown->label.length = label_len; + GRN_RAW_STRING_INIT(drilldown->keys); + drilldown->parsed_keys = NULL; + drilldown->n_parsed_keys = 0; + GRN_RAW_STRING_INIT(drilldown->sort_keys); + GRN_RAW_STRING_INIT(drilldown->output_columns); + drilldown->offset = 0; + drilldown->limit = DEFAULT_DRILLDOWN_LIMIT; + drilldown->calc_types = 0; + GRN_RAW_STRING_INIT(drilldown->calc_target_name); + GRN_RAW_STRING_INIT(drilldown->filter); + GRN_RAW_STRING_INIT(drilldown->table_name); + grn_columns_init(ctx, &(drilldown->columns)); + drilldown->result.table = NULL; + drilldown->filtered_result = NULL; +} + +static void +grn_drilldown_data_fin(grn_ctx *ctx, grn_drilldown_data *drilldown) +{ + grn_table_group_result *result; + + grn_columns_fin(ctx, &(drilldown->columns)); + + if (drilldown->filtered_result) { + grn_obj_close(ctx, drilldown->filtered_result); + } + + result = &(drilldown->result); + if (result->table) { + if (result->calc_target) { + grn_obj_unlink(ctx, result->calc_target); + } + if (result->table) { + grn_obj_close(ctx, result->table); + } + } +} + +static void +grn_drilldown_data_fill(grn_ctx *ctx, + grn_drilldown_data *drilldown, + grn_obj *keys, + grn_obj *sort_keys, + grn_obj *output_columns, + grn_obj *offset, + grn_obj *limit, + grn_obj *calc_types, + grn_obj *calc_target, + grn_obj *filter, + grn_obj *table) +{ + GRN_RAW_STRING_FILL(drilldown->keys, keys); + + GRN_RAW_STRING_FILL(drilldown->sort_keys, sort_keys); + + GRN_RAW_STRING_FILL(drilldown->output_columns, output_columns); + if (drilldown->output_columns.length == 0) { + drilldown->output_columns.value = DEFAULT_DRILLDOWN_OUTPUT_COLUMNS; + drilldown->output_columns.length = strlen(DEFAULT_DRILLDOWN_OUTPUT_COLUMNS); + } + + if (offset && GRN_TEXT_LEN(offset)) { + drilldown->offset = + grn_atoi(GRN_TEXT_VALUE(offset), GRN_BULK_CURR(offset), NULL); + } else { + drilldown->offset = 0; + } + + if (limit && GRN_TEXT_LEN(limit)) { + drilldown->limit = + grn_atoi(GRN_TEXT_VALUE(limit), GRN_BULK_CURR(limit), NULL); + } else { + drilldown->limit = DEFAULT_DRILLDOWN_LIMIT; + } + + if (calc_types && GRN_TEXT_LEN(calc_types)) { + drilldown->calc_types = + grn_parse_table_group_calc_types(ctx, + GRN_TEXT_VALUE(calc_types), + GRN_TEXT_LEN(calc_types)); + } else { + drilldown->calc_types = 0; + } + + GRN_RAW_STRING_FILL(drilldown->calc_target_name, calc_target); + + GRN_RAW_STRING_FILL(drilldown->filter, filter); + + GRN_RAW_STRING_FILL(drilldown->table_name, table); +} + +grn_expr_flags +grn_proc_expr_query_flags_parse(grn_ctx *ctx, + const char *query_flags, + size_t query_flags_size, + const char *error_message_tag) +{ + grn_expr_flags flags = 0; + const char *query_flags_end = query_flags + query_flags_size; + + while (query_flags < query_flags_end) { + if (*query_flags == '|' || *query_flags == ' ') { + query_flags += 1; + continue; + } + +#define CHECK_EXPR_FLAG(name) \ + if (((unsigned long) (query_flags_end - query_flags) >= (unsigned long) (sizeof(#name) - 1)) && \ + (memcmp(query_flags, #name, sizeof(#name) - 1) == 0) && \ + (((query_flags_end - query_flags) == (sizeof(#name) - 1)) || \ + (query_flags[sizeof(#name) - 1] == '|') || \ + (query_flags[sizeof(#name) - 1] == ' '))) { \ + flags |= GRN_EXPR_ ## name; \ + query_flags += sizeof(#name) - 1; \ + continue; \ + } + + CHECK_EXPR_FLAG(ALLOW_PRAGMA); + CHECK_EXPR_FLAG(ALLOW_COLUMN); + CHECK_EXPR_FLAG(ALLOW_UPDATE); + CHECK_EXPR_FLAG(ALLOW_LEADING_NOT); + CHECK_EXPR_FLAG(QUERY_NO_SYNTAX_ERROR); + +#define GRN_EXPR_NONE 0 + CHECK_EXPR_FLAG(NONE); +#undef GNR_EXPR_NONE + + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "%s invalid query flag: <%.*s>", + error_message_tag, + (int)(query_flags_end - query_flags), + query_flags); + return 0; +#undef CHECK_EXPR_FLAG + } + + return flags; +} + +static void +grn_select_expression_set_condition(grn_ctx *ctx, + grn_obj *expression, + grn_obj *condition) +{ + grn_obj *condition_ptr; + + if (!expression) { + return; + } + + condition_ptr = + grn_expr_get_or_add_var(ctx, expression, + GRN_SELECT_INTERNAL_VAR_CONDITION, + GRN_SELECT_INTERNAL_VAR_CONDITION_LEN); + GRN_PTR_INIT(condition_ptr, 0, GRN_DB_OBJECT); + GRN_PTR_SET(ctx, condition_ptr, condition); +} + +grn_bool +grn_proc_select_format_init(grn_ctx *ctx, + grn_obj_format *format, + grn_obj *result_set, + int n_hits, + int offset, + int limit, + const char *columns, + int columns_len, + grn_obj *condition) +{ + grn_rc rc; + + GRN_OBJ_FORMAT_INIT(format, n_hits, offset, limit, offset); + format->flags = + GRN_OBJ_FORMAT_WITH_COLUMN_NAMES| + GRN_OBJ_FORMAT_XML_ELEMENT_RESULTSET; + rc = grn_output_format_set_columns(ctx, + format, + result_set, + columns, + columns_len); + if (rc != GRN_SUCCESS) { + GRN_OBJ_FORMAT_FIN(ctx, format); + return GRN_FALSE; + } + + grn_select_expression_set_condition(ctx, format->expression, condition); + + return ctx->rc == GRN_SUCCESS; +} + +grn_bool +grn_proc_select_format_fin(grn_ctx *ctx, grn_obj_format *format) +{ + GRN_OBJ_FORMAT_FIN(ctx, format); + + return ctx->rc == GRN_SUCCESS; +} + +grn_bool +grn_proc_select_output_columns_open(grn_ctx *ctx, + grn_obj_format *format, + grn_obj *res, + int n_hits, + int offset, + int limit, + const char *columns, + int columns_len, + grn_obj *condition, + uint32_t n_additional_elements) +{ + grn_bool succeeded; + + if (!grn_proc_select_format_init(ctx, + format, + res, + n_hits, + offset, + limit, + columns, + columns_len, + condition)) { + return GRN_FALSE; + } + + GRN_OUTPUT_RESULT_SET_OPEN(res, format, n_additional_elements); + succeeded = (ctx->rc == GRN_SUCCESS); + if (!succeeded) { + GRN_OUTPUT_RESULT_SET_CLOSE(res, format); + } + + return succeeded; +} + +grn_bool +grn_proc_select_output_columns_close(grn_ctx *ctx, + grn_obj_format *format, + grn_obj *result_set) +{ + GRN_OUTPUT_RESULT_SET_CLOSE(result_set, format); + + return grn_proc_select_format_fin(ctx, format); +} + +grn_bool +grn_proc_select_output_columns(grn_ctx *ctx, + grn_obj *res, + int n_hits, + int offset, + int limit, + const char *columns, + int columns_len, + grn_obj *condition) +{ + grn_obj_format format; + uint32_t n_additional_elements = 0; + + if (!grn_proc_select_output_columns_open(ctx, + &format, + res, + n_hits, + offset, + limit, + columns, + columns_len, + condition, + n_additional_elements)) { + return GRN_FALSE; + } + + return grn_proc_select_output_columns_close(ctx, &format, res); +} + +static grn_obj * +grn_select_create_all_selected_result_table(grn_ctx *ctx, + grn_obj *table) +{ + grn_obj *result; + grn_posting posting; + + result = grn_table_create(ctx, NULL, 0, NULL, + GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, + table, NULL); + if (!result) { + return NULL; + } + + memset(&posting, 0, sizeof(grn_posting)); + GRN_TABLE_EACH_BEGIN(ctx, table, cursor, id) { + posting.rid = id; + grn_ii_posting_add(ctx, + &posting, + (grn_hash *)(result), + GRN_OP_OR); + } GRN_TABLE_EACH_END(ctx, cursor); + + return result; +} + +static grn_obj * +grn_select_create_no_sort_keys_sorted_table(grn_ctx *ctx, + grn_select_data *data, + grn_obj *table) +{ + grn_obj *sorted; + grn_table_cursor *cursor; + + sorted = grn_table_create(ctx, NULL, 0, NULL, + GRN_OBJ_TABLE_NO_KEY, + NULL, + table); + + if (!sorted) { + return NULL; + } + + cursor = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, + data->offset, + data->limit, + GRN_CURSOR_ASCENDING); + if (cursor) { + grn_id id; + while ((id = grn_table_cursor_next(ctx, cursor))) { + grn_id *value; + if (grn_array_add(ctx, (grn_array *)sorted, (void **)&value)) { + *value = id; + } + } + grn_table_cursor_close(ctx, cursor); + } + + return sorted; +} + + +static void +grn_select_apply_columns(grn_ctx *ctx, + grn_select_data *data, + grn_obj *table, + grn_hash *columns) +{ + grn_hash_cursor *columns_cursor; + + columns_cursor = grn_hash_cursor_open(ctx, columns, + NULL, 0, NULL, 0, 0, -1, 0); + if (!columns_cursor) { + return; + } + + while (grn_hash_cursor_next(ctx, columns_cursor) != GRN_ID_NIL) { + grn_column_data *column_data; + grn_obj *column; + grn_obj *expression; + grn_obj *record; + + grn_hash_cursor_get_value(ctx, columns_cursor, (void **)&column_data); + + column = grn_column_create(ctx, + table, + column_data->label.value, + column_data->label.length, + NULL, + column_data->flags, + column_data->type); + if (!column) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] failed to create column: %s", + grn_column_stage_name(column_data->stage), + (int)(column_data->label.length), + column_data->label.value, + ctx->errbuf); + break; + } + + GRN_EXPR_CREATE_FOR_QUERY(ctx, table, expression, record); + if (!expression) { + grn_obj_close(ctx, column); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] " + "failed to create expression to compute value: %s", + grn_column_stage_name(column_data->stage), + (int)(column_data->label.length), + column_data->label.value, + ctx->errbuf); + break; + } + grn_expr_parse(ctx, + expression, + column_data->value.value, + column_data->value.length, + NULL, + GRN_OP_MATCH, + GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc != GRN_SUCCESS) { + grn_obj_close(ctx, expression); + grn_obj_close(ctx, column); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] " + "failed to parse value: <%.*s>: %s", + grn_column_stage_name(column_data->stage), + (int)(column_data->label.length), + column_data->label.value, + (int)(column_data->value.length), + column_data->value.value, + ctx->errbuf); + break; + } + grn_select_expression_set_condition(ctx, + expression, + data->filter.condition.expression); + + if (column_data->window.sort_keys.length > 0 || + column_data->window.group_keys.length > 0) { + grn_window_definition definition; + grn_rc rc; + + if (column_data->window.sort_keys.length > 0) { + int n_sort_keys; + definition.sort_keys = + grn_table_sort_key_from_str(ctx, + column_data->window.sort_keys.value, + column_data->window.sort_keys.length, + table, &n_sort_keys); + definition.n_sort_keys = n_sort_keys; + if (!definition.sort_keys) { + grn_obj_close(ctx, expression); + grn_obj_close(ctx, column); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] " + "failed to parse sort keys: %s", + grn_column_stage_name(column_data->stage), + (int)(column_data->label.length), + column_data->label.value, + ctx->errbuf); + break; + } + } else { + definition.sort_keys = NULL; + definition.n_sort_keys = 0; + } + + if (column_data->window.group_keys.length > 0) { + int n_group_keys; + definition.group_keys = + grn_table_sort_key_from_str(ctx, + column_data->window.group_keys.value, + column_data->window.group_keys.length, + table, &n_group_keys); + definition.n_group_keys = n_group_keys; + if (!definition.group_keys) { + grn_obj_close(ctx, expression); + grn_obj_close(ctx, column); + if (definition.sort_keys) { + grn_table_sort_key_close(ctx, + definition.sort_keys, + definition.n_sort_keys); + } + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] " + "failed to parse group keys: %s", + grn_column_stage_name(column_data->stage), + (int)(column_data->label.length), + column_data->label.value, + ctx->errbuf); + break; + } + } else { + definition.group_keys = NULL; + definition.n_group_keys = 0; + } + + rc = grn_table_apply_window_function(ctx, + table, + column, + &definition, + expression); + if (definition.sort_keys) { + grn_table_sort_key_close(ctx, + definition.sort_keys, + definition.n_sort_keys); + } + if (definition.group_keys) { + grn_table_sort_key_close(ctx, + definition.group_keys, + definition.n_group_keys); + } + if (rc != GRN_SUCCESS) { + grn_obj_close(ctx, expression); + grn_obj_close(ctx, column); + break; + } + } else { + grn_rc rc; + rc = grn_table_apply_expr(ctx, table, column, expression); + if (rc != GRN_SUCCESS) { + grn_obj_close(ctx, expression); + grn_obj_close(ctx, column); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][column][%s][%.*s] " + "failed to apply expression to generate column values: " + "%s", + grn_column_stage_name(column_data->stage), + (int)(column_data->label.length), + column_data->label.value, + ctx->errbuf); + break; + } + } + + grn_obj_close(ctx, expression); + + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "columns[%.*s](%d)", + (int)(column_data->label.length), + column_data->label.value, + grn_table_size(ctx, table)); + } + + grn_hash_cursor_close(ctx, columns_cursor); +} + +static grn_bool +grn_select_apply_initial_columns(grn_ctx *ctx, + grn_select_data *data) +{ + if (!data->columns.initial) { + return GRN_TRUE; + } + + data->tables.initial = + grn_select_create_all_selected_result_table(ctx, data->tables.target); + if (!data->tables.initial) { + return GRN_FALSE; + } + + grn_select_apply_columns(ctx, + data, + data->tables.initial, + data->columns.initial); + + return ctx->rc == GRN_SUCCESS; +} + +static grn_bool +grn_select_filter(grn_ctx *ctx, + grn_select_data *data) +{ + if (!grn_filter_data_execute(ctx, + &(data->filter), + data->tables.initial, + "[select]")) { + return GRN_FALSE; + } + + data->tables.result = data->filter.filtered; + if (!data->tables.result) { + data->tables.result = data->tables.initial; + } + + { + grn_expr *expression; + expression = (grn_expr *)(data->filter.condition.expression); + if (expression) { + data->cacheable *= expression->cacheable; + data->taintable += expression->taintable; + } + } + + return GRN_TRUE; +} + +static grn_bool +grn_select_apply_filtered_columns(grn_ctx *ctx, + grn_select_data *data) +{ + if (!data->columns.filtered) { + return GRN_TRUE; + } + + if (data->tables.result == data->tables.initial) { + data->tables.result = + grn_select_create_all_selected_result_table(ctx, data->tables.initial); + if (!data->tables.result) { + return GRN_FALSE; + } + } + + grn_select_apply_columns(ctx, + data, + data->tables.result, + data->columns.filtered); + + return ctx->rc == GRN_SUCCESS; +} + +static int +grn_select_apply_adjuster_execute_ensure_factor(grn_ctx *ctx, + grn_obj *factor_object) +{ + if (!factor_object) { + return 1; + } else if (factor_object->header.domain == GRN_DB_INT32) { + return GRN_INT32_VALUE(factor_object); + } else { + grn_rc rc; + grn_obj int32_object; + int factor; + GRN_INT32_INIT(&int32_object, 0); + rc = grn_obj_cast(ctx, factor_object, &int32_object, GRN_FALSE); + if (rc == GRN_SUCCESS) { + factor = GRN_INT32_VALUE(&int32_object); + } else { + /* TODO: Log or return error? */ + factor = 1; + } + GRN_OBJ_FIN(ctx, &int32_object); + return factor; + } +} + +static void +grn_select_apply_adjuster_execute_adjust(grn_ctx *ctx, + grn_obj *table, + grn_obj *column, + grn_obj *value, + grn_obj *factor) +{ + grn_obj *index; + unsigned int n_indexes; + int factor_value; + + n_indexes = grn_column_index(ctx, column, GRN_OP_MATCH, &index, 1, NULL); + if (n_indexes == 0) { + char column_name[GRN_TABLE_MAX_KEY_SIZE]; + int column_name_size; + column_name_size = grn_obj_name(ctx, column, + column_name, GRN_TABLE_MAX_KEY_SIZE); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "adjuster requires index column for the target column: " + "<%.*s>", + column_name_size, + column_name); + return; + } + + factor_value = grn_select_apply_adjuster_execute_ensure_factor(ctx, factor); + + { + grn_search_optarg options; + memset(&options, 0, sizeof(grn_search_optarg)); + + options.mode = GRN_OP_EXACT; + options.similarity_threshold = 0; + options.max_interval = 0; + options.weight_vector = NULL; + options.vector_size = factor_value; + options.proc = NULL; + options.max_size = 0; + options.scorer = NULL; + + grn_obj_search(ctx, index, value, table, GRN_OP_ADJUST, &options); + } +} + +static void +grn_select_apply_adjuster_execute(grn_ctx *ctx, + grn_obj *table, + grn_obj *adjuster) +{ + grn_expr *expr = (grn_expr *)adjuster; + grn_expr_code *code, *code_end; + + code = expr->codes; + code_end = expr->codes + expr->codes_curr; + while (code < code_end) { + grn_obj *column, *value, *factor; + + if (code->op == GRN_OP_PLUS) { + code++; + continue; + } + + column = code->value; + code++; + value = code->value; + code++; + code++; /* op == GRN_OP_MATCH */ + if ((code_end - code) >= 2 && code[1].op == GRN_OP_STAR) { + factor = code->value; + code++; + code++; /* op == GRN_OP_STAR */ + } else { + factor = NULL; + } + grn_select_apply_adjuster_execute_adjust(ctx, table, column, value, factor); + } +} + +static grn_bool +grn_select_apply_adjuster(grn_ctx *ctx, + grn_select_data *data) +{ + grn_obj *adjuster; + grn_obj *record; + grn_rc rc; + + if (data->adjuster.length == 0) { + return GRN_TRUE; + } + + GRN_EXPR_CREATE_FOR_QUERY(ctx, data->tables.target, adjuster, record); + if (!adjuster) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][adjuster] " + "failed to create expression: %s", + ctx->errbuf); + return GRN_FALSE; + } + + rc = grn_expr_parse(ctx, adjuster, + data->adjuster.value, + data->adjuster.length, + NULL, + GRN_OP_MATCH, GRN_OP_ADJUST, + GRN_EXPR_SYNTAX_ADJUSTER); + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, adjuster); + GRN_PLUGIN_ERROR(ctx, + rc, + "[select][adjuster] " + "failed to parse: %s", + ctx->errbuf); + return GRN_FALSE; + } + + data->cacheable *= ((grn_expr *)adjuster)->cacheable; + data->taintable += ((grn_expr *)adjuster)->taintable; + grn_select_apply_adjuster_execute(ctx, data->tables.result, adjuster); + grn_obj_unlink(ctx, adjuster); + + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "adjust(%d)", grn_table_size(ctx, data->tables.result)); + + return GRN_TRUE; +} + +static grn_bool +grn_select_apply_scorer(grn_ctx *ctx, + grn_select_data *data) +{ + grn_obj *scorer; + grn_obj *record; + grn_rc rc = GRN_SUCCESS; + + if (data->scorer.length == 0) { + return GRN_TRUE; + } + + GRN_EXPR_CREATE_FOR_QUERY(ctx, data->tables.result, scorer, record); + if (!scorer) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][scorer] " + "failed to create expression: %s", + ctx->errbuf); + return GRN_FALSE; + } + + rc = grn_expr_parse(ctx, + scorer, + data->scorer.value, + data->scorer.length, + NULL, + GRN_OP_MATCH, + GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT|GRN_EXPR_ALLOW_UPDATE); + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, scorer); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][scorer] " + "failed to parse: %s", + ctx->errbuf); + return GRN_FALSE; + } + + data->cacheable *= ((grn_expr *)scorer)->cacheable; + data->taintable += ((grn_expr *)scorer)->taintable; + GRN_TABLE_EACH_BEGIN(ctx, data->tables.result, cursor, id) { + GRN_RECORD_SET(ctx, record, id); + grn_expr_exec(ctx, scorer, 0); + if (ctx->rc) { + rc = ctx->rc; + GRN_PLUGIN_ERROR(ctx, + rc, + "[select][scorer] " + "failed to execute: <%.*s>: %s", + (int)(data->scorer.length), + data->scorer.value, + ctx->errbuf); + break; + } + } GRN_TABLE_EACH_END(ctx, cursor); + grn_obj_unlink(ctx, scorer); + + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "score(%d)", grn_table_size(ctx, data->tables.result)); + + return rc == GRN_SUCCESS; +} + +static grn_bool +grn_select_sort(grn_ctx *ctx, + grn_select_data *data) +{ + grn_table_sort_key *keys; + uint32_t n_keys; + + if (data->sort_keys.length == 0) { + return GRN_TRUE; + } + + keys = grn_table_sort_key_from_str(ctx, + data->sort_keys.value, + data->sort_keys.length, + data->tables.result, + &n_keys); + if (!keys) { + if (ctx->rc == GRN_SUCCESS) { + return GRN_TRUE; + } else { + GRN_PLUGIN_ERROR(ctx, + ctx->rc, + "[select][sort] " + "failed to parse: <%.*s>: %s", + (int)(data->sort_keys.length), + data->sort_keys.value, + ctx->errbuf); + return GRN_FALSE; + } + } + + data->tables.sorted = grn_table_create(ctx, NULL, 0, NULL, + GRN_OBJ_TABLE_NO_KEY, + NULL, + data->tables.result); + if (!data->tables.sorted) { + GRN_PLUGIN_ERROR(ctx, + ctx->rc, + "[select][sort] " + "failed to create table to store sorted record: " + "<%.*s>: %s", + (int)(data->sort_keys.length), + data->sort_keys.value, + ctx->errbuf); + return GRN_FALSE; + } + + grn_table_sort(ctx, + data->tables.result, + data->offset, + data->limit, + data->tables.sorted, + keys, + n_keys); + + grn_table_sort_key_close(ctx, keys, n_keys); + + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "sort(%d)", data->limit); + + return ctx->rc == GRN_SUCCESS; +} + +static grn_bool +grn_select_apply_output_columns(grn_ctx *ctx, + grn_select_data *data) +{ + if (!data->columns.output) { + return GRN_TRUE; + } + + if (!data->tables.sorted) { + data->tables.sorted = + grn_select_create_no_sort_keys_sorted_table(ctx, + data, + data->tables.result); + if (!data->tables.sorted) { + return GRN_FALSE; + } + } + + grn_select_apply_columns(ctx, + data, + data->tables.sorted, + data->columns.output); + + return ctx->rc == GRN_SUCCESS; +} + +static grn_bool +grn_select_output_match_open(grn_ctx *ctx, + grn_select_data *data, + grn_obj_format *format, + uint32_t n_additional_elements) +{ + grn_bool succeeded = GRN_TRUE; + int offset; + grn_obj *output_table; + + if (data->tables.sorted) { + offset = 0; + output_table = data->tables.sorted; + } else { + offset = data->offset; + output_table = data->tables.result; + } + succeeded = + grn_proc_select_output_columns_open(ctx, + format, + output_table, + grn_table_size(ctx, data->tables.result), + offset, + data->limit, + data->output_columns.value, + data->output_columns.length, + data->filter.condition.expression, + n_additional_elements); + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "output(%d)", data->limit); + + return succeeded; +} + +static grn_bool +grn_select_output_match_close(grn_ctx *ctx, + grn_select_data *data, + grn_obj_format *format) +{ + grn_obj *output_table; + + if (data->tables.sorted) { + output_table = data->tables.sorted; + } else { + output_table = data->tables.result; + } + + return grn_proc_select_output_columns_close(ctx, format, output_table); +} + +static grn_bool +grn_select_output_match(grn_ctx *ctx, grn_select_data *data) +{ + grn_obj_format format; + uint32_t n_additional_elements = 0; + + if (!grn_select_output_match_open(ctx, data, &format, n_additional_elements)) { + return GRN_FALSE; + } + + return grn_select_output_match_close(ctx, data, &format); +} + +static grn_bool +grn_select_slice_execute(grn_ctx *ctx, + grn_select_data *data, + grn_obj *table, + grn_slice_data *slice) +{ + char tag[GRN_TABLE_MAX_KEY_SIZE]; + grn_filter_data *filter; + + grn_snprintf(tag, GRN_TABLE_MAX_KEY_SIZE, GRN_TABLE_MAX_KEY_SIZE, + "[select][slices][%.*s]", + (int)(slice->label.length), + slice->label.value); + filter = &(slice->filter); + if (filter->query.length == 0 && filter->filter.length == 0) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "%s slice requires query or filter", + tag); + return GRN_FALSE; + } + + if (!grn_filter_data_execute(ctx, filter, table, tag)) { + return GRN_FALSE; + } + + slice->table = filter->filtered; + + return GRN_TRUE; +} + +static grn_bool +grn_select_slices_execute(grn_ctx *ctx, + grn_select_data *data, + grn_obj *table, + grn_hash *slices) +{ + grn_bool succeeded = GRN_TRUE; + + GRN_HASH_EACH_BEGIN(ctx, slices, cursor, id) { + grn_slice_data *slice; + + grn_hash_cursor_get_value(ctx, cursor, (void **)&slice); + if (!grn_select_slice_execute(ctx, data, table, slice)) { + succeeded = GRN_FALSE; + break; + } + } GRN_HASH_EACH_END(ctx, cursor); + + return succeeded; +} + +static grn_bool +grn_select_prepare_slices(grn_ctx *ctx, + grn_select_data *data) +{ + if (!data->slices) { + return GRN_TRUE; + } + + if (!grn_select_slices_execute(ctx, data, data->tables.result, data->slices)) { + return GRN_FALSE; + } + + data->output.n_elements += 1; + + return GRN_TRUE; +} + +static grn_bool +grn_select_output_slices(grn_ctx *ctx, + grn_select_data *data) +{ + grn_bool succeeded = GRN_TRUE; + unsigned int n_available_results = 0; + + if (!data->slices) { + return GRN_TRUE; + } + + data->output.formatter->slices_label(ctx, data); + + GRN_HASH_EACH_BEGIN(ctx, data->slices, cursor, id) { + grn_slice_data *slice; + + grn_hash_cursor_get_value(ctx, cursor, (void **)&slice); + if (slice->table) { + n_available_results++; + } + } GRN_HASH_EACH_END(ctx, cursor); + + data->output.formatter->slices_open(ctx, data, n_available_results); + + GRN_HASH_EACH_BEGIN(ctx, data->slices, cursor, id) { + grn_slice_data *slice; + uint32_t n_hits; + int offset; + int limit; + + grn_hash_cursor_get_value(ctx, cursor, (void **)&slice); + if (!slice->table) { + continue; + } + + n_hits = grn_table_size(ctx, slice->table); + + offset = slice->offset; + limit = slice->limit; + grn_normalize_offset_and_limit(ctx, n_hits, &offset, &limit); + + if (slice->sort_keys.length > 0) { + grn_table_sort_key *sort_keys; + uint32_t n_sort_keys; + sort_keys = grn_table_sort_key_from_str(ctx, + slice->sort_keys.value, + slice->sort_keys.length, + slice->table, &n_sort_keys); + if (sort_keys) { + grn_obj *sorted; + sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY, + NULL, slice->table); + if (sorted) { + grn_table_sort(ctx, slice->table, offset, limit, + sorted, sort_keys, n_sort_keys); + data->output.formatter->slice_label(ctx, data, slice); + if (!grn_proc_select_output_columns(ctx, + sorted, + n_hits, + 0, + limit, + slice->output_columns.value, + slice->output_columns.length, + slice->filter.condition.expression)) { + succeeded = GRN_FALSE; + } + grn_obj_unlink(ctx, sorted); + } + grn_table_sort_key_close(ctx, sort_keys, n_sort_keys); + } else { + succeeded = GRN_FALSE; + } + } else { + data->output.formatter->slice_label(ctx, data, slice); + if (!grn_proc_select_output_columns(ctx, + slice->table, + n_hits, + offset, + limit, + slice->output_columns.value, + slice->output_columns.length, + slice->filter.condition.expression)) { + succeeded = GRN_FALSE; + } + } + + if (!succeeded) { + break; + } + + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "slice(%d)[%.*s]", + n_hits, + (int)(slice->label.length), + slice->label.value); + } GRN_HASH_EACH_END(ctx, cursor); + + data->output.formatter->slices_close(ctx, data); + + return succeeded; +} + +static grn_bool +grn_select_drilldown_execute(grn_ctx *ctx, + grn_select_data *data, + grn_obj *table, + grn_hash *drilldowns, + grn_id id) +{ + grn_table_sort_key *keys = NULL; + unsigned int n_keys = 0; + grn_obj *target_table = table; + grn_drilldown_data *drilldown; + grn_table_group_result *result; + + drilldown = + (grn_drilldown_data *)grn_hash_get_value_(ctx, drilldowns, id, NULL); + result = &(drilldown->result); + + result->limit = 1; + result->flags = GRN_TABLE_GROUP_CALC_COUNT; + result->op = 0; + result->max_n_subrecs = 0; + result->key_begin = 0; + result->key_end = 0; + if (result->calc_target) { + grn_obj_unlink(ctx, result->calc_target); + } + result->calc_target = NULL; + + if (drilldown->table_name.length > 0) { + grn_id dependent_id; + dependent_id = grn_hash_get(ctx, + drilldowns, + drilldown->table_name.value, + drilldown->table_name.length, + NULL); + if (dependent_id == GRN_ID_NIL) { + if (data->slices) { + grn_slice_data *slice; + dependent_id = grn_hash_get(ctx, + data->slices, + drilldown->table_name.value, + drilldown->table_name.length, + NULL); + if (dependent_id) { + slice = + (grn_slice_data *)grn_hash_get_value_(ctx, data->slices, + dependent_id, NULL); + target_table = slice->table; + } + } + if (dependent_id == GRN_ID_NIL) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[select][drilldowns][%.*s][table] " + "nonexistent label: <%.*s>", + (int)(drilldown->label.length), + drilldown->label.value, + (int)(drilldown->table_name.length), + drilldown->table_name.value); + return GRN_FALSE; + } + } else { + grn_drilldown_data *dependent_drilldown; + grn_table_group_result *dependent_result; + + dependent_drilldown = + (grn_drilldown_data *)grn_hash_get_value_(ctx, + drilldowns, + dependent_id, + NULL); + dependent_result = &(dependent_drilldown->result); + target_table = dependent_result->table; + } + } + + if (drilldown->parsed_keys) { + result->key_end = drilldown->n_parsed_keys; + } else if (drilldown->keys.length > 0) { + keys = grn_table_sort_key_from_str(ctx, + drilldown->keys.value, + drilldown->keys.length, + target_table, &n_keys); + if (!keys) { + GRN_PLUGIN_CLEAR_ERROR(ctx); + return GRN_FALSE; + } + + result->key_end = n_keys - 1; + if (n_keys > 1) { + result->max_n_subrecs = 1; + } + } + + if (drilldown->calc_target_name.length > 0) { + result->calc_target = grn_obj_column(ctx, target_table, + drilldown->calc_target_name.value, + drilldown->calc_target_name.length); + } + if (result->calc_target) { + result->flags |= drilldown->calc_types; + } + + if (drilldown->parsed_keys) { + grn_table_group(ctx, + target_table, + drilldown->parsed_keys, + drilldown->n_parsed_keys, + result, + 1); + } else { + grn_table_group(ctx, target_table, keys, n_keys, result, 1); + } + + if (keys) { + grn_table_sort_key_close(ctx, keys, n_keys); + } + + if (!result->table) { + return GRN_FALSE; + } + + if (drilldown->columns.initial) { + grn_select_apply_columns(ctx, + data, + result->table, + drilldown->columns.initial); + } + + if (drilldown->filter.length > 0) { + grn_obj *expression; + grn_obj *record; + GRN_EXPR_CREATE_FOR_QUERY(ctx, result->table, expression, record); + if (!expression) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][drilldowns]%s%.*s%s[filter] " + "failed to create expression for filter: %s", + drilldown->label.length > 0 ? "[" : "", + (int)(drilldown->label.length), + drilldown->label.value, + drilldown->label.length > 0 ? "]" : "", + ctx->errbuf); + return GRN_FALSE; + } + grn_expr_parse(ctx, + expression, + drilldown->filter.value, + drilldown->filter.length, + NULL, + GRN_OP_MATCH, + GRN_OP_AND, + GRN_EXPR_SYNTAX_SCRIPT); + if (ctx->rc != GRN_SUCCESS) { + grn_obj_close(ctx, expression); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][drilldowns]%s%.*s%s[filter] " + "failed to parse filter: <%.*s>: %s", + drilldown->label.length > 0 ? "[" : "", + (int)(drilldown->label.length), + drilldown->label.value, + drilldown->label.length > 0 ? "]" : "", + (int)(drilldown->filter.length), + drilldown->filter.value, + ctx->errbuf); + return GRN_FALSE; + } + drilldown->filtered_result = grn_table_select(ctx, + result->table, + expression, + NULL, + GRN_OP_OR); + if (ctx->rc != GRN_SUCCESS) { + grn_obj_close(ctx, expression); + if (drilldown->filtered_result) { + grn_obj_close(ctx, drilldown->filtered_result); + drilldown->filtered_result = NULL; + } + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][drilldowns]%s%.*s%s[filter] " + "failed to execute filter: <%.*s>: %s", + drilldown->label.length > 0 ? "[" : "", + (int)(drilldown->label.length), + drilldown->label.value, + drilldown->label.length > 0 ? "]" : "", + (int)(drilldown->filter.length), + drilldown->filter.value, + ctx->errbuf); + return GRN_FALSE; + } + grn_obj_close(ctx, expression); + } + + { + unsigned int n_hits; + + if (drilldown->filtered_result) { + n_hits = grn_table_size(ctx, drilldown->filtered_result); + } else { + n_hits = grn_table_size(ctx, result->table); + } + if (data->drilldown.keys.length == 0) { + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "drilldowns[%.*s](%u)", + (int)(drilldown->label.length), + drilldown->label.value, + n_hits); + } else { + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "drilldown(%u)", + n_hits); + } + } + + return GRN_TRUE; +} + +typedef enum { + TSORT_STATUS_NOT_VISITED, + TSORT_STATUS_VISITING, + TSORT_STATUS_VISITED +} tsort_status; + +static grn_bool +drilldown_tsort_visit(grn_ctx *ctx, + grn_hash *drilldowns, + tsort_status *statuses, + grn_obj *ids, + grn_id id) +{ + grn_bool cycled = GRN_TRUE; + uint32_t index = id - 1; + + switch (statuses[index]) { + case TSORT_STATUS_VISITING : + cycled = GRN_TRUE; + break; + case TSORT_STATUS_VISITED : + cycled = GRN_FALSE; + break; + case TSORT_STATUS_NOT_VISITED : + cycled = GRN_FALSE; + statuses[index] = TSORT_STATUS_VISITING; + { + grn_drilldown_data *drilldown; + drilldown = + (grn_drilldown_data *)grn_hash_get_value_(ctx, drilldowns, id, NULL); + if (drilldown->table_name.length > 0) { + grn_id dependent_id; + dependent_id = grn_hash_get(ctx, drilldowns, + drilldown->table_name.value, + drilldown->table_name.length, + NULL); + if (dependent_id != GRN_ID_NIL) { + cycled = drilldown_tsort_visit(ctx, + drilldowns, + statuses, + ids, + dependent_id); + if (cycled) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[select][drilldowns][%.*s][table] " + "cycled dependency: <%.*s>", + (int)(drilldown->label.length), + drilldown->label.value, + (int)(drilldown->table_name.length), + drilldown->table_name.value); + } + } + } + } + if (!cycled) { + statuses[index] = TSORT_STATUS_VISITED; + GRN_RECORD_PUT(ctx, ids, id); + } + break; + } + + return cycled; +} + +static grn_bool +drilldown_tsort_body(grn_ctx *ctx, + grn_hash *drilldowns, + tsort_status *statuses, + grn_obj *ids) +{ + grn_bool succeeded = GRN_TRUE; + + GRN_HASH_EACH_BEGIN(ctx, drilldowns, cursor, id) { + if (drilldown_tsort_visit(ctx, drilldowns, statuses, ids, id)) { + succeeded = GRN_FALSE; + break; + } + } GRN_HASH_EACH_END(ctx, cursor); + + return succeeded; +} + +static void +drilldown_tsort_init(grn_ctx *ctx, + tsort_status *statuses, + size_t n_statuses) +{ + size_t i; + for (i = 0; i < n_statuses; i++) { + statuses[i] = TSORT_STATUS_NOT_VISITED; + } +} + +static grn_bool +drilldown_tsort(grn_ctx *ctx, + grn_hash *drilldowns, + grn_obj *ids) +{ + tsort_status *statuses; + size_t n_statuses; + grn_bool succeeded; + + n_statuses = grn_hash_size(ctx, drilldowns); + statuses = GRN_PLUGIN_MALLOCN(ctx, tsort_status, n_statuses); + if (!statuses) { + return GRN_FALSE; + } + + drilldown_tsort_init(ctx, statuses, n_statuses); + succeeded = drilldown_tsort_body(ctx, drilldowns, statuses, ids); + GRN_PLUGIN_FREE(ctx, statuses); + return succeeded; +} + +static grn_bool +grn_select_drilldowns_execute(grn_ctx *ctx, + grn_select_data *data) +{ + grn_bool succeeded = GRN_TRUE; + grn_obj tsorted_ids; + size_t i; + size_t n_drilldowns; + + GRN_RECORD_INIT(&tsorted_ids, GRN_OBJ_VECTOR, GRN_ID_NIL); + if (!drilldown_tsort(ctx, data->drilldowns, &tsorted_ids)) { + succeeded = GRN_FALSE; + goto exit; + } + + n_drilldowns = GRN_BULK_VSIZE(&tsorted_ids) / sizeof(grn_id); + for (i = 0; i < n_drilldowns; i++) { + grn_id id; + + id = GRN_RECORD_VALUE_AT(&tsorted_ids, i); + if (!grn_select_drilldown_execute(ctx, + data, + data->tables.result, + data->drilldowns, + id)) { + if (ctx->rc != GRN_SUCCESS) { + succeeded = GRN_FALSE; + break; + } + } + } + +exit : + GRN_OBJ_FIN(ctx, &tsorted_ids); + + return succeeded; +} + +static grn_drilldown_data * +grn_select_data_drilldowns_add(grn_ctx *ctx, + grn_select_data *data, + const char *label, + size_t label_len) +{ + grn_drilldown_data *drilldown = NULL; + int added; + + if (!data->drilldowns) { + data->drilldowns = grn_hash_create(ctx, + NULL, + GRN_TABLE_MAX_KEY_SIZE, + sizeof(grn_drilldown_data), + GRN_OBJ_TABLE_HASH_KEY | + GRN_OBJ_KEY_VAR_SIZE | + GRN_HASH_TINY); + if (!data->drilldowns) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][drilldowns] " + "failed to allocate drilldowns data: %s", + ctx->errbuf); + return NULL; + } + } + + grn_hash_add(ctx, + data->drilldowns, + label, + label_len, + (void **)&drilldown, + &added); + if (added) { + grn_drilldown_data_init(ctx, drilldown, label, label_len); + } + + return drilldown; +} + +static grn_bool +grn_select_prepare_drilldowns(grn_ctx *ctx, + grn_select_data *data) +{ + if (data->drilldown.keys.length > 0) { + data->drilldown.parsed_keys = + grn_table_sort_key_from_str(ctx, + data->drilldown.keys.value, + data->drilldown.keys.length, + data->tables.result, + &(data->drilldown.n_parsed_keys)); + if (data->drilldown.parsed_keys) { + int i; + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + for (i = 0; i < data->drilldown.n_parsed_keys; i++) { + grn_drilldown_data *drilldown; + + GRN_BULK_REWIND(&buffer); + grn_text_printf(ctx, &buffer, "drilldown%d", i); + drilldown = grn_select_data_drilldowns_add(ctx, + data, + GRN_TEXT_VALUE(&buffer), + GRN_TEXT_LEN(&buffer)); + if (!drilldown) { + continue; + } + + drilldown->parsed_keys = data->drilldown.parsed_keys + i; + drilldown->n_parsed_keys = 1; + +#define COPY(field) \ + drilldown->field = data->drilldown.field + + COPY(sort_keys); + COPY(output_columns); + COPY(offset); + COPY(limit); + COPY(calc_types); + COPY(calc_target_name); + COPY(filter); + +#undef COPY + } + } + } + + if (!data->drilldowns) { + return GRN_TRUE; + } + + if (!grn_select_drilldowns_execute(ctx, data)) { + return GRN_FALSE; + } + + { + unsigned int n_available_results = 0; + + GRN_HASH_EACH_BEGIN(ctx, data->drilldowns, cursor, id) { + grn_drilldown_data *drilldown; + grn_table_group_result *result; + + grn_hash_cursor_get_value(ctx, cursor, (void **)&drilldown); + result = &(drilldown->result); + if (result->table) { + n_available_results++; + } + } GRN_HASH_EACH_END(ctx, cursor); + + if (data->drilldown.keys.length > 0) { + data->output.n_elements += n_available_results; + } else { + if (n_available_results > 0) { + data->output.n_elements += 1; + } + } + } + + return GRN_TRUE; +} + +static grn_bool +grn_select_output_drilldowns(grn_ctx *ctx, + grn_select_data *data) +{ + grn_bool succeeded = GRN_TRUE; + unsigned int n_available_results = 0; + grn_bool is_labeled; + + if (!data->drilldowns) { + return GRN_TRUE; + } + + data->output.formatter->drilldowns_label(ctx, data); + + GRN_HASH_EACH_BEGIN(ctx, data->drilldowns, cursor, id) { + grn_drilldown_data *drilldown; + grn_table_group_result *result; + + grn_hash_cursor_get_value(ctx, cursor, (void **)&drilldown); + result = &(drilldown->result); + if (result->table) { + n_available_results++; + } + } GRN_HASH_EACH_END(ctx, cursor); + + is_labeled = (data->drilldown.keys.length == 0); + + data->output.formatter->drilldowns_open(ctx, data, n_available_results); + + GRN_HASH_EACH_BEGIN(ctx, data->drilldowns, cursor, id) { + grn_drilldown_data *drilldown; + grn_table_group_result *result; + grn_obj *target_table; + uint32_t n_hits; + int offset; + int limit; + + grn_hash_cursor_get_value(ctx, cursor, (void **)&drilldown); + result = &(drilldown->result); + + if (!result->table) { + continue; + } + + if (drilldown->filtered_result) { + target_table = drilldown->filtered_result; + } else { + target_table = result->table; + } + + n_hits = grn_table_size(ctx, target_table); + + offset = drilldown->offset; + limit = drilldown->limit; + grn_normalize_offset_and_limit(ctx, n_hits, &offset, &limit); + + if (drilldown->sort_keys.length > 0) { + grn_table_sort_key *sort_keys; + uint32_t n_sort_keys; + sort_keys = grn_table_sort_key_from_str(ctx, + drilldown->sort_keys.value, + drilldown->sort_keys.length, + target_table, &n_sort_keys); + if (sort_keys) { + grn_obj *sorted; + sorted = grn_table_create(ctx, NULL, 0, NULL, GRN_OBJ_TABLE_NO_KEY, + NULL, target_table); + if (sorted) { + grn_table_sort(ctx, target_table, offset, limit, + sorted, sort_keys, n_sort_keys); + data->output.formatter->drilldown_label(ctx, data, drilldown); + if (!grn_proc_select_output_columns(ctx, + sorted, + n_hits, + 0, + limit, + drilldown->output_columns.value, + drilldown->output_columns.length, + data->filter.condition.expression)) { + succeeded = GRN_FALSE; + } + grn_obj_unlink(ctx, sorted); + } + grn_table_sort_key_close(ctx, sort_keys, n_sort_keys); + } else { + succeeded = GRN_FALSE; + } + } else { + data->output.formatter->drilldown_label(ctx, data, drilldown); + if (!grn_proc_select_output_columns(ctx, + target_table, + n_hits, + offset, + limit, + drilldown->output_columns.value, + drilldown->output_columns.length, + data->filter.condition.expression)) { + succeeded = GRN_FALSE; + } + } + + if (!succeeded) { + break; + } + + if (is_labeled) { + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "output.drilldowns[%.*s](%d)", + (int)(drilldown->label.length), + drilldown->label.value, + n_hits); + } else { + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "output.drilldown(%d)", n_hits); + } + } GRN_HASH_EACH_END(ctx, cursor); + + data->output.formatter->drilldowns_close(ctx, data); + + return succeeded; +} + +static grn_bool +grn_select_output(grn_ctx *ctx, grn_select_data *data) +{ + grn_bool succeeded = GRN_TRUE; + + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + GRN_OUTPUT_ARRAY_OPEN("RESULT", data->output.n_elements); + succeeded = grn_select_output_match(ctx, data); + if (succeeded) { + succeeded = grn_select_output_slices(ctx, data); + } + if (succeeded) { + succeeded = grn_select_output_drilldowns(ctx, data); + } + GRN_OUTPUT_ARRAY_CLOSE(); + } else { + grn_obj_format format; + uint32_t n_additional_elements = 0; + + if (data->slices) { + n_additional_elements++; + } + if (data->drilldowns) { + n_additional_elements++; + } + + succeeded = grn_select_output_match_open(ctx, + data, + &format, + n_additional_elements); + if (succeeded) { + succeeded = grn_select_output_slices(ctx, data); + if (succeeded) { + succeeded = grn_select_output_drilldowns(ctx, data); + } + if (!grn_select_output_match_close(ctx, data, &format)) { + succeeded = GRN_FALSE; + } + } + } + + return succeeded; +} + +static void +grn_select_output_slices_label_v1(grn_ctx *ctx, grn_select_data *data) +{ +} + +static void +grn_select_output_slices_open_v1(grn_ctx *ctx, + grn_select_data *data, + unsigned int n_result_sets) +{ + GRN_OUTPUT_MAP_OPEN("SLICES", n_result_sets); +} + +static void +grn_select_output_slices_close_v1(grn_ctx *ctx, grn_select_data *data) +{ + GRN_OUTPUT_MAP_CLOSE(); +} + +static void +grn_select_output_slice_label_v1(grn_ctx *ctx, + grn_select_data *data, + grn_slice_data *slice) +{ + GRN_OUTPUT_STR(slice->label.value, slice->label.length); +} + +static void +grn_select_output_drilldowns_label_v1(grn_ctx *ctx, grn_select_data *data) +{ +} + +static void +grn_select_output_drilldowns_open_v1(grn_ctx *ctx, + grn_select_data *data, + unsigned int n_result_sets) +{ + if (data->drilldown.keys.length == 0) { + GRN_OUTPUT_MAP_OPEN("DRILLDOWNS", n_result_sets); + } +} + +static void +grn_select_output_drilldowns_close_v1(grn_ctx *ctx, grn_select_data *data) +{ + if (data->drilldown.keys.length == 0) { + GRN_OUTPUT_MAP_CLOSE(); + } +} + +static void +grn_select_output_drilldown_label_v1(grn_ctx *ctx, + grn_select_data *data, + grn_drilldown_data *drilldown) +{ + if (data->drilldown.keys.length == 0) { + GRN_OUTPUT_STR(drilldown->label.value, drilldown->label.length); + } +} + +static grn_select_output_formatter grn_select_output_formatter_v1 = { + grn_select_output_slices_label_v1, + grn_select_output_slices_open_v1, + grn_select_output_slices_close_v1, + grn_select_output_slice_label_v1, + grn_select_output_drilldowns_label_v1, + grn_select_output_drilldowns_open_v1, + grn_select_output_drilldowns_close_v1, + grn_select_output_drilldown_label_v1 +}; + +static void +grn_select_output_slices_label_v3(grn_ctx *ctx, grn_select_data *data) +{ + GRN_OUTPUT_CSTR("slices"); +} + +static void +grn_select_output_slices_open_v3(grn_ctx *ctx, + grn_select_data *data, + unsigned int n_result_sets) +{ + GRN_OUTPUT_MAP_OPEN("slices", n_result_sets); +} + +static void +grn_select_output_slices_close_v3(grn_ctx *ctx, grn_select_data *data) +{ + GRN_OUTPUT_MAP_CLOSE(); +} + +static void +grn_select_output_slice_label_v3(grn_ctx *ctx, + grn_select_data *data, + grn_slice_data *slice) +{ + GRN_OUTPUT_STR(slice->label.value, slice->label.length); +} + +static void +grn_select_output_drilldowns_label_v3(grn_ctx *ctx, grn_select_data *data) +{ + GRN_OUTPUT_CSTR("drilldowns"); +} + +static void +grn_select_output_drilldowns_open_v3(grn_ctx *ctx, + grn_select_data *data, + unsigned int n_result_sets) +{ + GRN_OUTPUT_MAP_OPEN("drilldowns", n_result_sets); +} + +static void +grn_select_output_drilldowns_close_v3(grn_ctx *ctx, grn_select_data *data) +{ + GRN_OUTPUT_MAP_CLOSE(); +} + +static void +grn_select_output_drilldown_label_v3(grn_ctx *ctx, + grn_select_data *data, + grn_drilldown_data *drilldown) +{ + if (data->drilldown.keys.length == 0) { + GRN_OUTPUT_STR(drilldown->label.value, drilldown->label.length); + } else { + grn_obj *key; + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_len; + + key = drilldown->parsed_keys[0].key; + switch (key->header.type) { + case GRN_COLUMN_FIX_SIZE : + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_INDEX : + name_len = grn_column_name(ctx, key, name, GRN_TABLE_MAX_KEY_SIZE); + break; + default : + name_len = grn_obj_name(ctx, key, name, GRN_TABLE_MAX_KEY_SIZE); + break; + } + GRN_OUTPUT_STR(name, name_len); + } +} + +static grn_select_output_formatter grn_select_output_formatter_v3 = { + grn_select_output_slices_label_v3, + grn_select_output_slices_open_v3, + grn_select_output_slices_close_v3, + grn_select_output_slice_label_v3, + grn_select_output_drilldowns_label_v3, + grn_select_output_drilldowns_open_v3, + grn_select_output_drilldowns_close_v3, + grn_select_output_drilldown_label_v3 +}; + +static grn_rc +grn_select(grn_ctx *ctx, grn_select_data *data) +{ + uint32_t nhits; + grn_obj *outbuf = ctx->impl->output.buf; + grn_content_type output_type = ctx->impl->output.type; + char cache_key[GRN_CACHE_MAX_KEY_SIZE]; + uint32_t cache_key_size; + long long int threshold, original_threshold = 0; + grn_cache *cache_obj = grn_cache_current_get(ctx); + + if (grn_ctx_get_command_version(ctx) < GRN_COMMAND_VERSION_3) { + data->output.formatter = &grn_select_output_formatter_v1; + } else { + data->output.formatter = &grn_select_output_formatter_v3; + } + + data->cacheable = 1; + data->taintable = 0; + + data->output.n_elements = 0; + + grn_raw_string_lstrip(ctx, &(data->filter.query)); + + cache_key_size = + data->table.length + 1 + + data->filter.match_columns.length + 1 + + data->filter.query.length + 1 + + data->filter.filter.length + 1 + + data->scorer.length + 1 + + data->sort_keys.length + 1 + + data->output_columns.length + 1 + + data->match_escalation_threshold.length + 1 + + data->filter.query_expander.length + 1 + + data->filter.query_flags.length + 1 + + data->adjuster.length + 1 + + sizeof(grn_content_type) + + sizeof(int) * 2 + + sizeof(grn_command_version) + + sizeof(grn_bool); + if (data->slices) { + GRN_HASH_EACH_BEGIN(ctx, data->slices, cursor, id) { + grn_slice_data *slice; + grn_hash_cursor_get_value(ctx, cursor, (void **)&slice); + grn_raw_string_lstrip(ctx, &(slice->filter.query)); + cache_key_size += + slice->filter.match_columns.length + 1 + + slice->filter.query.length + 1 + + slice->filter.query_expander.length + 1 + + slice->filter.query_flags.length + 1 + + slice->filter.filter.length + 1 + + slice->sort_keys.length + 1 + + slice->output_columns.length + 1 + + slice->label.length + 1 + + sizeof(int) * 2; + } GRN_HASH_EACH_END(ctx, cursor); + } +#define DRILLDOWN_CACHE_SIZE(drilldown) \ + drilldown->keys.length + 1 + \ + drilldown->sort_keys.length + 1 + \ + drilldown->output_columns.length + 1 + \ + drilldown->label.length + 1 + \ + drilldown->calc_target_name.length + 1 + \ + drilldown->filter.length + 1 + \ + drilldown->table_name.length + 1 + \ + sizeof(int) * 2 + \ + sizeof(grn_table_group_flags) + if (data->drilldown.keys.length > 0) { + grn_drilldown_data *drilldown = &(data->drilldown); + cache_key_size += DRILLDOWN_CACHE_SIZE(drilldown); + } + if (data->drilldowns) { + GRN_HASH_EACH_BEGIN(ctx, data->drilldowns, cursor, id) { + grn_drilldown_data *drilldown; + grn_hash_cursor_get_value(ctx, cursor, (void **)&drilldown); + cache_key_size += DRILLDOWN_CACHE_SIZE(drilldown); + } GRN_HASH_EACH_END(ctx, cursor); + } +#undef DRILLDOWN_CACHE_SIZE + if (cache_key_size <= GRN_CACHE_MAX_KEY_SIZE) { + char *cp = cache_key; + +#define PUT_CACHE_KEY(string) \ + if ((string).value) \ + grn_memcpy(cp, (string).value, (string).length); \ + cp += (string).length; \ + *cp++ = '\0' + + PUT_CACHE_KEY(data->table); + PUT_CACHE_KEY(data->filter.match_columns); + PUT_CACHE_KEY(data->filter.query); + PUT_CACHE_KEY(data->filter.filter); + PUT_CACHE_KEY(data->scorer); + PUT_CACHE_KEY(data->sort_keys); + PUT_CACHE_KEY(data->output_columns); + if (data->slices) { + GRN_HASH_EACH_BEGIN(ctx, data->slices, cursor, id) { + grn_slice_data *slice; + grn_hash_cursor_get_value(ctx, cursor, (void **)&slice); + PUT_CACHE_KEY(slice->filter.match_columns); + PUT_CACHE_KEY(slice->filter.query); + PUT_CACHE_KEY(slice->filter.query_expander); + PUT_CACHE_KEY(slice->filter.query_flags); + PUT_CACHE_KEY(slice->filter.filter); + PUT_CACHE_KEY(slice->sort_keys); + PUT_CACHE_KEY(slice->output_columns); + PUT_CACHE_KEY(slice->label); + grn_memcpy(cp, &(slice->offset), sizeof(int)); + cp += sizeof(int); + grn_memcpy(cp, &(slice->limit), sizeof(int)); + cp += sizeof(int); + } GRN_HASH_EACH_END(ctx, cursor); + } +#define PUT_CACHE_KEY_DRILLDOWN(drilldown) do { \ + PUT_CACHE_KEY(drilldown->keys); \ + PUT_CACHE_KEY(drilldown->sort_keys); \ + PUT_CACHE_KEY(drilldown->output_columns); \ + PUT_CACHE_KEY(drilldown->label); \ + PUT_CACHE_KEY(drilldown->calc_target_name); \ + PUT_CACHE_KEY(drilldown->filter); \ + PUT_CACHE_KEY(drilldown->table_name); \ + grn_memcpy(cp, &(drilldown->offset), sizeof(int)); \ + cp += sizeof(int); \ + grn_memcpy(cp, &(drilldown->limit), sizeof(int)); \ + cp += sizeof(int); \ + grn_memcpy(cp, \ + &(drilldown->calc_types), \ + sizeof(grn_table_group_flags)); \ + cp += sizeof(grn_table_group_flags); \ + } while (GRN_FALSE) + if (data->drilldown.keys.length > 0) { + grn_drilldown_data *drilldown = &(data->drilldown); + PUT_CACHE_KEY_DRILLDOWN(drilldown); + } + if (data->drilldowns) { + GRN_HASH_EACH_BEGIN(ctx, data->drilldowns, cursor, id) { + grn_drilldown_data *drilldown; + grn_hash_cursor_get_value(ctx, cursor, (void **)&drilldown); + PUT_CACHE_KEY_DRILLDOWN(drilldown); + } GRN_HASH_EACH_END(ctx, cursor); + } +#undef PUT_CACHE_KEY_DRILLDOWN + PUT_CACHE_KEY(data->match_escalation_threshold); + PUT_CACHE_KEY(data->filter.query_expander); + PUT_CACHE_KEY(data->filter.query_flags); + PUT_CACHE_KEY(data->adjuster); + grn_memcpy(cp, &output_type, sizeof(grn_content_type)); + cp += sizeof(grn_content_type); + grn_memcpy(cp, &(data->offset), sizeof(int)); + cp += sizeof(int); + grn_memcpy(cp, &(data->limit), sizeof(int)); + cp += sizeof(int); + grn_memcpy(cp, &(ctx->impl->command.version), sizeof(grn_command_version)); + cp += sizeof(grn_command_version); + grn_memcpy(cp, &(ctx->impl->output.is_pretty), sizeof(grn_bool)); + cp += sizeof(grn_bool); +#undef PUT_CACHE_KEY + + { + grn_rc rc; + rc = grn_cache_fetch(ctx, cache_obj, cache_key, cache_key_size, outbuf); + if (rc == GRN_SUCCESS) { + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_CACHE, + ":", "cache(%" GRN_FMT_LLD ")", + (long long int)GRN_TEXT_LEN(outbuf)); + return ctx->rc; + } + } + } + if (data->match_escalation_threshold.length) { + const char *end, *rest; + original_threshold = grn_ctx_get_match_escalation_threshold(ctx); + end = + data->match_escalation_threshold.value + + data->match_escalation_threshold.length; + threshold = grn_atoll(data->match_escalation_threshold.value, end, &rest); + if (end == rest) { + grn_ctx_set_match_escalation_threshold(ctx, threshold); + } + } + + data->tables.target = grn_ctx_get(ctx, data->table.value, data->table.length); + if (!data->tables.target) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][table] invalid name: <%.*s>", + (int)(data->table.length), + data->table.value); + goto exit; + } + + { + if (data->filter.filter.length > 0 && + (data->filter.filter.value[0] == '?') && + (ctx->impl->output.type == GRN_CONTENT_JSON)) { + ctx->rc = grn_ts_select(ctx, data->tables.target, + data->filter.filter.value + 1, + data->filter.filter.length - 1, + data->scorer.value, + data->scorer.length, + data->sort_keys.value, + data->sort_keys.length, + data->output_columns.value, + data->output_columns.length, + data->offset, + data->limit); + if (!ctx->rc && + data->cacheable > 0 && + cache_key_size <= GRN_CACHE_MAX_KEY_SIZE && + (!data->cache.value || + data->cache.length != 2 || + data->cache.value[0] != 'n' || + data->cache.value[1] != 'o')) { + grn_cache_update(ctx, cache_obj, cache_key, cache_key_size, outbuf); + } + goto exit; + } + + data->tables.initial = data->tables.target; + if (!grn_select_apply_initial_columns(ctx, data)) { + goto exit; + } + + if (!grn_select_filter(ctx, data)) { + goto exit; + } + + nhits = grn_table_size(ctx, data->tables.result); + GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_SIZE, + ":", "select(%d)", nhits); + + if (!grn_select_apply_filtered_columns(ctx, data)) { + goto exit; + } + + { + grn_bool succeeded; + + /* For select results */ + data->output.n_elements = 1; + + if (!grn_select_apply_adjuster(ctx, data)) { + goto exit; + } + + if (!grn_select_apply_scorer(ctx, data)) { + goto exit; + } + + grn_normalize_offset_and_limit(ctx, nhits, + &(data->offset), &(data->limit)); + + if (!grn_select_sort(ctx, data)) { + goto exit; + } + + if (!grn_select_apply_output_columns(ctx, data)) { + goto exit; + } + + if (!grn_select_prepare_slices(ctx, data)) { + goto exit; + } + + if (!grn_select_prepare_drilldowns(ctx, data)) { + goto exit; + } + + succeeded = grn_select_output(ctx, data); + if (!succeeded) { + goto exit; + } + } + if (!ctx->rc && + data->cacheable && + cache_key_size <= GRN_CACHE_MAX_KEY_SIZE && + (!data->cache.value || + data->cache.length != 2 || + data->cache.value[0] != 'n' || + data->cache.value[1] != 'o')) { + grn_cache_update(ctx, cache_obj, cache_key, cache_key_size, outbuf); + } + if (data->taintable > 0) { + grn_db_touch(ctx, DB_OBJ(data->tables.target)->db); + } + } + +exit : + if (data->match_escalation_threshold.length > 0) { + grn_ctx_set_match_escalation_threshold(ctx, original_threshold); + } + + /* GRN_LOG(ctx, GRN_LOG_NONE, "%d", ctx->seqno); */ + + return ctx->rc; +} + +static grn_slice_data * +grn_select_data_slices_add(grn_ctx *ctx, + grn_select_data *data, + const char *label, + size_t label_len) +{ + grn_slice_data *slice = NULL; + int added; + + if (!data->slices) { + data->slices = grn_hash_create(ctx, + NULL, + GRN_TABLE_MAX_KEY_SIZE, + sizeof(grn_slice_data), + GRN_OBJ_TABLE_HASH_KEY | + GRN_OBJ_KEY_VAR_SIZE | + GRN_HASH_TINY); + if (!data->slices) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[select][slices] " + "failed to allocate slices data: %s", + ctx->errbuf); + return NULL; + } + } + + grn_hash_add(ctx, + data->slices, + label, + label_len, + (void **)&slice, + &added); + if (added) { + grn_slice_data_init(ctx, slice, label, label_len); + } + + return slice; +} + +static grn_bool +grn_select_data_fill_slice_labels(grn_ctx *ctx, + grn_user_data *user_data, + grn_select_data *data) +{ + grn_obj *vars; + grn_table_cursor *cursor; + const char *prefix = "slices["; + int prefix_len; + + vars = grn_plugin_proc_get_vars(ctx, user_data); + + cursor = grn_table_cursor_open(ctx, vars, NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + return GRN_FALSE; + } + + prefix_len = strlen(prefix); + while (grn_table_cursor_next(ctx, cursor)) { + void *key; + char *name; + int name_len; + name_len = grn_table_cursor_get_key(ctx, cursor, &key); + name = key; + if (name_len > prefix_len + 1 && + strncmp(prefix, name, prefix_len) == 0) { + const char *label_end; + size_t label_len; + label_end = memchr(name + prefix_len + 1, + ']', + name_len - prefix_len - 1); + if (!label_end) { + continue; + } + label_len = (label_end - name) - prefix_len; + grn_select_data_slices_add(ctx, + data, + name + prefix_len, + label_len); + } + } + grn_table_cursor_close(ctx, cursor); + + return GRN_TRUE; +} + +static grn_bool +grn_select_data_fill_slices(grn_ctx *ctx, + grn_user_data *user_data, + grn_select_data *data) +{ + if (!grn_select_data_fill_slice_labels(ctx, user_data, data)) { + return GRN_FALSE; + } + + GRN_HASH_EACH_BEGIN(ctx, data->slices, cursor, id) { + grn_slice_data *slice; + char slice_label[GRN_TABLE_MAX_KEY_SIZE]; + char key_name[GRN_TABLE_MAX_KEY_SIZE]; + grn_obj *match_columns; + grn_obj *query; + grn_obj *query_expander; + grn_obj *query_flags; + grn_obj *filter; + grn_obj *sort_keys; + grn_obj *output_columns; + grn_obj *offset; + grn_obj *limit; + + grn_hash_cursor_get_value(ctx, cursor, (void **)&slice); + + grn_snprintf(slice_label, + GRN_TABLE_MAX_KEY_SIZE, + GRN_TABLE_MAX_KEY_SIZE, + "slices[%.*s].", + (int)(slice->label.length), + slice->label.value); + +#define GET_VAR(name) \ + grn_snprintf(key_name, \ + GRN_TABLE_MAX_KEY_SIZE, \ + GRN_TABLE_MAX_KEY_SIZE, \ + "%s%s", slice_label, #name); \ + name = grn_plugin_proc_get_var(ctx, user_data, key_name, -1); + + GET_VAR(match_columns); + GET_VAR(query); + GET_VAR(query_expander); + GET_VAR(query_flags); + GET_VAR(filter); + GET_VAR(sort_keys); + GET_VAR(output_columns); + GET_VAR(offset); + GET_VAR(limit); + +#undef GET_VAR + + grn_slice_data_fill(ctx, + slice, + match_columns, + query, + query_expander, + query_flags, + filter, + sort_keys, + output_columns, + offset, + limit); + } GRN_HASH_EACH_END(ctx, cursor); + + return GRN_TRUE; +} + +static grn_bool +grn_select_data_fill_drilldown_labels(grn_ctx *ctx, + grn_user_data *user_data, + grn_select_data *data, + const char *prefix) +{ + grn_obj *vars; + grn_table_cursor *cursor; + int prefix_len; + + vars = grn_plugin_proc_get_vars(ctx, user_data); + + cursor = grn_table_cursor_open(ctx, vars, NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + return GRN_FALSE; + } + + prefix_len = strlen(prefix); + while (grn_table_cursor_next(ctx, cursor)) { + void *key; + char *name; + int name_len; + name_len = grn_table_cursor_get_key(ctx, cursor, &key); + name = key; + if (name_len > prefix_len + 1 && + strncmp(prefix, name, prefix_len) == 0) { + const char *label_end; + size_t label_len; + label_end = memchr(name + prefix_len + 1, + ']', + name_len - prefix_len - 1); + if (!label_end) { + continue; + } + label_len = (label_end - name) - prefix_len; + grn_select_data_drilldowns_add(ctx, + data, + name + prefix_len, + label_len); + } + } + grn_table_cursor_close(ctx, cursor); + + return GRN_TRUE; +} + +static grn_bool +grn_select_data_fill_drilldown_columns(grn_ctx *ctx, + grn_user_data *user_data, + grn_drilldown_data *drilldown, + const char *parameter_key) +{ + char prefix[GRN_TABLE_MAX_KEY_SIZE]; + + grn_snprintf(prefix, + GRN_TABLE_MAX_KEY_SIZE, + GRN_TABLE_MAX_KEY_SIZE, + "%s[%.*s].", + parameter_key, + (int)(drilldown->label.length), + drilldown->label.value); + return grn_columns_fill(ctx, + user_data, + &(drilldown->columns), + prefix, + strlen(prefix)); +} + +static grn_bool +grn_select_data_fill_drilldowns(grn_ctx *ctx, + grn_user_data *user_data, + grn_select_data *data) +{ + grn_obj *drilldown; + + drilldown = grn_plugin_proc_get_var(ctx, user_data, "drilldown", -1); + if (GRN_TEXT_LEN(drilldown) > 0) { + grn_obj *sort_keys; + + sort_keys = grn_plugin_proc_get_var(ctx, user_data, + "drilldown_sort_keys", -1); + if (GRN_TEXT_LEN(sort_keys) == 0) { + /* For backward compatibility */ + sort_keys = grn_plugin_proc_get_var(ctx, user_data, + "drilldown_sortby", -1); + } + grn_drilldown_data_fill(ctx, + &(data->drilldown), + drilldown, + sort_keys, + grn_plugin_proc_get_var(ctx, user_data, + "drilldown_output_columns", + -1), + grn_plugin_proc_get_var(ctx, user_data, + "drilldown_offset", -1), + grn_plugin_proc_get_var(ctx, user_data, + "drilldown_limit", -1), + grn_plugin_proc_get_var(ctx, user_data, + "drilldown_calc_types", -1), + grn_plugin_proc_get_var(ctx, user_data, + "drilldown_calc_target", -1), + grn_plugin_proc_get_var(ctx, user_data, + "drilldown_filter", -1), + NULL); + return GRN_TRUE; + } else { + grn_bool succeeded = GRN_TRUE; + + if (!grn_select_data_fill_drilldown_labels(ctx, user_data, data, + "drilldowns[")) { + return GRN_FALSE; + } + + /* For backward compatibility */ + if (!grn_select_data_fill_drilldown_labels(ctx, user_data, data, + "drilldown[")) { + return GRN_FALSE; + } + + GRN_HASH_EACH_BEGIN(ctx, data->drilldowns, cursor, id) { + grn_drilldown_data *drilldown; + grn_obj *keys = NULL; + grn_obj *sort_keys = NULL; + grn_obj *output_columns = NULL; + grn_obj *offset = NULL; + grn_obj *limit = NULL; + grn_obj *calc_types = NULL; + grn_obj *calc_target = NULL; + grn_obj *filter = NULL; + grn_obj *table = NULL; + + grn_hash_cursor_get_value(ctx, cursor, (void **)&drilldown); + + succeeded = grn_select_data_fill_drilldown_columns(ctx, + user_data, + drilldown, + "drilldowns"); + if (!succeeded) { + break; + } + + /* For backward compatibility */ + succeeded = grn_select_data_fill_drilldown_columns(ctx, + user_data, + drilldown, + "drilldown"); + if (!succeeded) { + break; + } + +#define GET_VAR_RAW(parameter_key, name) do { \ + if (!name) { \ + char key_name[GRN_TABLE_MAX_KEY_SIZE]; \ + grn_snprintf(key_name, \ + GRN_TABLE_MAX_KEY_SIZE, \ + GRN_TABLE_MAX_KEY_SIZE, \ + "%s[%.*s].%s", \ + (parameter_key), \ + (int)(drilldown->label.length), \ + drilldown->label.value, \ + #name); \ + name = grn_plugin_proc_get_var(ctx, user_data, key_name, -1); \ + } \ + } while (GRN_FALSE) + +#define GET_VAR(name) do { \ + GET_VAR_RAW("drilldowns", name); \ + /* For backward compatibility */ \ + GET_VAR_RAW("drilldown", name); \ + } while (GRN_FALSE) + + GET_VAR(keys); + GET_VAR(sort_keys); + if (!sort_keys) { + grn_obj *sortby = NULL; + GET_VAR(sortby); + sort_keys = sortby; + } + GET_VAR(output_columns); + GET_VAR(offset); + GET_VAR(limit); + GET_VAR(calc_types); + GET_VAR(calc_target); + GET_VAR(filter); + GET_VAR(table); + +#undef GET_VAR + +#undef GET_VAR_RAW + + grn_drilldown_data_fill(ctx, + drilldown, + keys, + sort_keys, + output_columns, + offset, + limit, + calc_types, + calc_target, + filter, + table); + } GRN_HASH_EACH_END(ctx, cursor); + + return succeeded; + } +} + +static grn_obj * +command_select(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_select_data data; + + grn_columns_init(ctx, &(data.columns)); + grn_filter_data_init(ctx, &(data.filter)); + + data.tables.target = NULL; + data.tables.initial = NULL; + data.tables.result = NULL; + data.tables.sorted = NULL; + + data.slices = NULL; + grn_drilldown_data_init(ctx, &(data.drilldown), NULL, 0); + data.drilldowns = NULL; + + data.table.value = grn_plugin_proc_get_var_string(ctx, user_data, + "table", -1, + &(data.table.length)); +#define GET_VAR(name) \ + grn_plugin_proc_get_var(ctx, user_data, name, strlen(name)) + + { + grn_obj *query_expander; + + query_expander = GET_VAR("query_expander"); + if (GRN_TEXT_LEN(query_expander) == 0) { + query_expander = GET_VAR("query_expansion"); + } + + grn_filter_data_fill(ctx, + &(data.filter), + GET_VAR("match_columns"), + GET_VAR("query"), + query_expander, + GET_VAR("query_flags"), + GET_VAR("filter")); + } +#undef GET_VAR + + data.scorer.value = + grn_plugin_proc_get_var_string(ctx, user_data, + "scorer", -1, + &(data.scorer.length)); + data.sort_keys.value = + grn_plugin_proc_get_var_string(ctx, user_data, + "sort_keys", -1, + &(data.sort_keys.length)); + if (data.sort_keys.length == 0) { + /* For backward compatibility */ + data.sort_keys.value = + grn_plugin_proc_get_var_string(ctx, user_data, + "sortby", -1, + &(data.sort_keys.length)); + } + data.output_columns.value = + grn_plugin_proc_get_var_string(ctx, user_data, + "output_columns", -1, + &(data.output_columns.length)); + if (!data.output_columns.value) { + data.output_columns.value = GRN_SELECT_DEFAULT_OUTPUT_COLUMNS; + data.output_columns.length = strlen(GRN_SELECT_DEFAULT_OUTPUT_COLUMNS); + } + data.offset = grn_plugin_proc_get_var_int32(ctx, user_data, + "offset", -1, + 0); + data.limit = grn_plugin_proc_get_var_int32(ctx, user_data, + "limit", -1, + GRN_SELECT_DEFAULT_LIMIT); + + data.cache.value = grn_plugin_proc_get_var_string(ctx, user_data, + "cache", -1, + &(data.cache.length)); + data.match_escalation_threshold.value = + grn_plugin_proc_get_var_string(ctx, user_data, + "match_escalation_threshold", -1, + &(data.match_escalation_threshold.length)); + + data.adjuster.value = + grn_plugin_proc_get_var_string(ctx, user_data, + "adjuster", -1, + &(data.adjuster.length)); + + if (!grn_select_data_fill_slices(ctx, user_data, &data)) { + goto exit; + } + + if (!grn_select_data_fill_drilldowns(ctx, user_data, &data)) { + goto exit; + } + + if (!grn_columns_fill(ctx, user_data, &(data.columns), NULL, 0)) { + goto exit; + } + + grn_select(ctx, &data); + +exit : + if (data.drilldowns) { + GRN_HASH_EACH_BEGIN(ctx, data.drilldowns, cursor, id) { + grn_drilldown_data *drilldown; + grn_hash_cursor_get_value(ctx, cursor, (void **)&drilldown); + grn_drilldown_data_fin(ctx, drilldown); + } GRN_HASH_EACH_END(ctx, cursor); + grn_hash_close(ctx, data.drilldowns); + } + + if (data.drilldown.parsed_keys) { + grn_table_sort_key_close(ctx, + data.drilldown.parsed_keys, + data.drilldown.n_parsed_keys); + } + grn_drilldown_data_fin(ctx, &(data.drilldown)); + + if (data.slices) { + GRN_HASH_EACH_BEGIN(ctx, data.slices, cursor, id) { + grn_slice_data *slice; + grn_hash_cursor_get_value(ctx, cursor, (void **)&slice); + grn_slice_data_fin(ctx, slice); + } GRN_HASH_EACH_END(ctx, cursor); + grn_hash_close(ctx, data.slices); + } + + if (data.tables.sorted) { + grn_obj_unlink(ctx, data.tables.sorted); + } + + if (data.tables.result == data.filter.filtered) { + data.tables.result = NULL; + } + grn_filter_data_fin(ctx, &(data.filter)); + + if (data.tables.result && + data.tables.result != data.tables.initial && + data.tables.result != data.tables.target) { + grn_obj_unlink(ctx, data.tables.result); + } + + if (data.tables.initial && data.tables.initial != data.tables.target) { + grn_obj_unlink(ctx, data.tables.initial); + } + + if (data.tables.target) { + grn_obj_unlink(ctx, data.tables.target); + } + + grn_columns_fin(ctx, &(data.columns)); + + return NULL; +} + +#define N_VARS 26 +#define DEFINE_VARS grn_expr_var vars[N_VARS] + +static void +init_vars(grn_ctx *ctx, grn_expr_var *vars) +{ + grn_plugin_expr_var_init(ctx, &(vars[0]), "name", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "table", -1); + grn_plugin_expr_var_init(ctx, &(vars[2]), "match_columns", -1); + grn_plugin_expr_var_init(ctx, &(vars[3]), "query", -1); + grn_plugin_expr_var_init(ctx, &(vars[4]), "filter", -1); + grn_plugin_expr_var_init(ctx, &(vars[5]), "scorer", -1); + /* Deprecated since 6.0.3. Use sort_keys instead. */ + grn_plugin_expr_var_init(ctx, &(vars[6]), "sortby", -1); + grn_plugin_expr_var_init(ctx, &(vars[7]), "output_columns", -1); + grn_plugin_expr_var_init(ctx, &(vars[8]), "offset", -1); + grn_plugin_expr_var_init(ctx, &(vars[9]), "limit", -1); + grn_plugin_expr_var_init(ctx, &(vars[10]), "drilldown", -1); + /* Deprecated since 6.0.3. Use drilldown_sort_keys instead. */ + grn_plugin_expr_var_init(ctx, &(vars[11]), "drilldown_sortby", -1); + grn_plugin_expr_var_init(ctx, &(vars[12]), "drilldown_output_columns", -1); + grn_plugin_expr_var_init(ctx, &(vars[13]), "drilldown_offset", -1); + grn_plugin_expr_var_init(ctx, &(vars[14]), "drilldown_limit", -1); + grn_plugin_expr_var_init(ctx, &(vars[15]), "cache", -1); + grn_plugin_expr_var_init(ctx, &(vars[16]), "match_escalation_threshold", -1); + /* Deprecated. Use query_expander instead. */ + grn_plugin_expr_var_init(ctx, &(vars[17]), "query_expansion", -1); + grn_plugin_expr_var_init(ctx, &(vars[18]), "query_flags", -1); + grn_plugin_expr_var_init(ctx, &(vars[19]), "query_expander", -1); + grn_plugin_expr_var_init(ctx, &(vars[20]), "adjuster", -1); + grn_plugin_expr_var_init(ctx, &(vars[21]), "drilldown_calc_types", -1); + grn_plugin_expr_var_init(ctx, &(vars[22]), "drilldown_calc_target", -1); + grn_plugin_expr_var_init(ctx, &(vars[23]), "drilldown_filter", -1); + grn_plugin_expr_var_init(ctx, &(vars[24]), "sort_keys", -1); + grn_plugin_expr_var_init(ctx, &(vars[25]), "drilldown_sort_keys", -1); +} + +void +grn_proc_init_select(grn_ctx *ctx) +{ + DEFINE_VARS; + + init_vars(ctx, vars); + grn_plugin_command_create(ctx, + "select", -1, + command_select, + N_VARS - 1, + vars + 1); +} + +static grn_obj * +command_define_selector(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + uint32_t i, nvars; + grn_expr_var *vars; + + grn_proc_get_info(ctx, user_data, &vars, &nvars, NULL); + for (i = 1; i < nvars; i++) { + grn_obj *var; + var = grn_plugin_proc_get_var_by_offset(ctx, user_data, i); + GRN_TEXT_SET(ctx, &((vars + i)->value), + GRN_TEXT_VALUE(var), + GRN_TEXT_LEN(var)); + } + { + grn_obj *name; + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + grn_plugin_command_create(ctx, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name), + command_select, + nvars - 1, + vars + 1); + } + GRN_OUTPUT_BOOL(!ctx->rc); + + return NULL; +} + +void +grn_proc_init_define_selector(grn_ctx *ctx) +{ + DEFINE_VARS; + + init_vars(ctx, vars); + grn_plugin_command_create(ctx, + "define_selector", -1, + command_define_selector, + N_VARS, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_snippet.c b/storage/mroonga/vendor/groonga/lib/proc/proc_snippet.c new file mode 100644 index 00000000..0c6ea681 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_snippet.c @@ -0,0 +1,319 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" +#include "../grn_expr.h" + +#include +#include + +#define GRN_FUNC_SNIPPET_HTML_CACHE_NAME "$snippet_html" + +static grn_obj * +snippet_exec(grn_ctx *ctx, grn_obj *snip, grn_obj *text, + grn_user_data *user_data, + const char *prefix, int prefix_length, + const char *suffix, int suffix_length) +{ + grn_rc rc; + unsigned int i, n_results, max_tagged_length; + grn_obj snippet_buffer; + grn_obj *snippets; + + if (GRN_TEXT_LEN(text) == 0) { + return NULL; + } + + rc = grn_snip_exec(ctx, snip, + GRN_TEXT_VALUE(text), GRN_TEXT_LEN(text), + &n_results, &max_tagged_length); + if (rc != GRN_SUCCESS) { + return NULL; + } + + if (n_results == 0) { + return grn_plugin_proc_alloc(ctx, user_data, GRN_DB_VOID, 0); + } + + snippets = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_SHORT_TEXT, GRN_OBJ_VECTOR); + if (!snippets) { + return NULL; + } + + GRN_TEXT_INIT(&snippet_buffer, 0); + grn_bulk_space(ctx, &snippet_buffer, + prefix_length + max_tagged_length + suffix_length); + for (i = 0; i < n_results; i++) { + unsigned int snippet_length; + + GRN_BULK_REWIND(&snippet_buffer); + if (prefix_length) { + GRN_TEXT_PUT(ctx, &snippet_buffer, prefix, prefix_length); + } + rc = grn_snip_get_result(ctx, snip, i, + GRN_TEXT_VALUE(&snippet_buffer) + prefix_length, + &snippet_length); + if (rc == GRN_SUCCESS) { + grn_strncat(GRN_TEXT_VALUE(&snippet_buffer), + GRN_BULK_WSIZE(&snippet_buffer), + suffix, + suffix_length); + grn_vector_add_element(ctx, snippets, + GRN_TEXT_VALUE(&snippet_buffer), + prefix_length + snippet_length + suffix_length, + 0, GRN_DB_SHORT_TEXT); + } + } + GRN_OBJ_FIN(ctx, &snippet_buffer); + + return snippets; +} + +/* TODO: support caching for the same parameter. */ +static grn_obj * +func_snippet(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *snippets = NULL; + +#define N_REQUIRED_ARGS 1 +#define KEYWORD_SET_SIZE 3 + if (nargs > N_REQUIRED_ARGS) { + grn_obj *text = args[0]; + grn_obj *end_arg = args[nargs - 1]; + grn_obj *snip = NULL; + unsigned int width = 200; + unsigned int max_n_results = 3; + grn_snip_mapping *mapping = NULL; + int flags = GRN_SNIP_SKIP_LEADING_SPACES; + const char *prefix = NULL; + int prefix_length = 0; + const char *suffix = NULL; + int suffix_length = 0; + const char *normalizer_name = NULL; + int normalizer_name_length = 0; + const char *default_open_tag = NULL; + int default_open_tag_length = 0; + const char *default_close_tag = NULL; + int default_close_tag_length = 0; + int n_args_without_option = nargs; + + if (end_arg->header.type == GRN_TABLE_HASH_KEY) { + grn_obj *options = end_arg; + grn_hash_cursor *cursor; + void *key; + int key_size; + grn_obj *value; + + n_args_without_option--; + cursor = grn_hash_cursor_open(ctx, (grn_hash *)options, + NULL, 0, NULL, 0, + 0, -1, 0); + if (!cursor) { + GRN_PLUGIN_ERROR(ctx, GRN_NO_MEMORY_AVAILABLE, + "snippet(): couldn't open cursor"); + goto exit; + } + while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { + grn_hash_cursor_get_key_value(ctx, cursor, + &key, &key_size, + (void **)&value); + if (key_size == 5 && !memcmp(key, "width", 5)) { + width = GRN_UINT32_VALUE(value); + } else if (key_size == 13 && !memcmp(key, "max_n_results", 13)) { + max_n_results = GRN_UINT32_VALUE(value); + } else if (key_size == 19 && !memcmp(key, "skip_leading_spaces", 19)) { + if (GRN_BOOL_VALUE(value) == GRN_FALSE) { + flags &= ~GRN_SNIP_SKIP_LEADING_SPACES; + } + } else if (key_size == 11 && !memcmp(key, "html_escape", 11)) { + if (GRN_BOOL_VALUE(value)) { + mapping = GRN_SNIP_MAPPING_HTML_ESCAPE; + } + } else if (key_size == 6 && !memcmp(key, "prefix", 6)) { + prefix = GRN_TEXT_VALUE(value); + prefix_length = GRN_TEXT_LEN(value); + } else if (key_size == 6 && !memcmp(key, "suffix", 6)) { + suffix = GRN_TEXT_VALUE(value); + suffix_length = GRN_TEXT_LEN(value); + } else if (key_size == 10 && !memcmp(key, "normalizer", 10)) { + normalizer_name = GRN_TEXT_VALUE(value); + normalizer_name_length = GRN_TEXT_LEN(value); + } else if (key_size == 16 && !memcmp(key, "default_open_tag", 16)) { + default_open_tag = GRN_TEXT_VALUE(value); + default_open_tag_length = GRN_TEXT_LEN(value); + } else if (key_size == 17 && !memcmp(key, "default_close_tag", 17)) { + default_close_tag = GRN_TEXT_VALUE(value); + default_close_tag_length = GRN_TEXT_LEN(value); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "invalid option name: <%.*s>", + key_size, (char *)key); + grn_hash_cursor_close(ctx, cursor); + goto exit; + } + } + grn_hash_cursor_close(ctx, cursor); + } + + snip = grn_snip_open(ctx, flags, width, max_n_results, + default_open_tag, default_open_tag_length, + default_close_tag, default_close_tag_length, mapping); + if (snip) { + grn_rc rc; + unsigned int i; + if (!normalizer_name) { + grn_snip_set_normalizer(ctx, snip, GRN_NORMALIZER_AUTO); + } else if (normalizer_name_length > 0) { + grn_obj *normalizer; + normalizer = grn_ctx_get(ctx, normalizer_name, normalizer_name_length); + if (!grn_obj_is_normalizer_proc(ctx, normalizer)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, normalizer); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "snippet(): not normalizer: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + grn_obj_unlink(ctx, normalizer); + goto exit; + } + grn_snip_set_normalizer(ctx, snip, normalizer); + grn_obj_unlink(ctx, normalizer); + } + if (default_open_tag_length == 0 && default_close_tag_length == 0) { + unsigned int n_keyword_sets = + (n_args_without_option - N_REQUIRED_ARGS) / KEYWORD_SET_SIZE; + grn_obj **keyword_set_args = args + N_REQUIRED_ARGS; + for (i = 0; i < n_keyword_sets; i++) { + rc = grn_snip_add_cond(ctx, snip, + GRN_TEXT_VALUE(keyword_set_args[i * KEYWORD_SET_SIZE]), + GRN_TEXT_LEN(keyword_set_args[i * KEYWORD_SET_SIZE]), + GRN_TEXT_VALUE(keyword_set_args[i * KEYWORD_SET_SIZE + 1]), + GRN_TEXT_LEN(keyword_set_args[i * KEYWORD_SET_SIZE + 1]), + GRN_TEXT_VALUE(keyword_set_args[i * KEYWORD_SET_SIZE + 2]), + GRN_TEXT_LEN(keyword_set_args[i * KEYWORD_SET_SIZE + 2])); + } + } else { + unsigned int n_keywords = n_args_without_option - N_REQUIRED_ARGS; + grn_obj **keyword_args = args + N_REQUIRED_ARGS; + for (i = 0; i < n_keywords; i++) { + rc = grn_snip_add_cond(ctx, snip, + GRN_TEXT_VALUE(keyword_args[i]), + GRN_TEXT_LEN(keyword_args[i]), + NULL, 0, + NULL, 0); + } + } + snippets = snippet_exec(ctx, snip, text, user_data, + prefix, prefix_length, + suffix, suffix_length); + } + } +#undef KEYWORD_SET_SIZE +#undef N_REQUIRED_ARGS + +exit : + if (!snippets) { + snippets = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_VOID, 0); + } + + return snippets; +} + +void +grn_proc_init_snippet(grn_ctx *ctx) +{ + grn_proc_create(ctx, "snippet", -1, GRN_PROC_FUNCTION, + func_snippet, NULL, NULL, 0, NULL); +} + +static grn_obj * +func_snippet_html(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *snippets = NULL; + + /* TODO: support parameters */ + if (nargs == 1) { + grn_obj *text = args[0]; + grn_obj *expression = NULL; + grn_obj *condition_ptr = NULL; + grn_obj *condition = NULL; + grn_obj *snip = NULL; + int flags = GRN_SNIP_SKIP_LEADING_SPACES; + unsigned int width = 200; + unsigned int max_n_results = 3; + const char *open_tag = ""; + const char *close_tag = ""; + grn_snip_mapping *mapping = GRN_SNIP_MAPPING_HTML_ESCAPE; + + grn_proc_get_info(ctx, user_data, NULL, NULL, &expression); + condition_ptr = grn_expr_get_var(ctx, expression, + GRN_SELECT_INTERNAL_VAR_CONDITION, + strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); + if (condition_ptr) { + condition = GRN_PTR_VALUE(condition_ptr); + } + + if (condition) { + grn_obj *snip_ptr; + snip_ptr = grn_expr_get_var(ctx, expression, + GRN_FUNC_SNIPPET_HTML_CACHE_NAME, + strlen(GRN_FUNC_SNIPPET_HTML_CACHE_NAME)); + if (snip_ptr) { + snip = GRN_PTR_VALUE(snip_ptr); + } else { + snip_ptr = + grn_expr_get_or_add_var(ctx, expression, + GRN_FUNC_SNIPPET_HTML_CACHE_NAME, + strlen(GRN_FUNC_SNIPPET_HTML_CACHE_NAME)); + GRN_OBJ_FIN(ctx, snip_ptr); + GRN_PTR_INIT(snip_ptr, GRN_OBJ_OWN, GRN_DB_OBJECT); + + snip = grn_snip_open(ctx, flags, width, max_n_results, + open_tag, strlen(open_tag), + close_tag, strlen(close_tag), + mapping); + if (snip) { + grn_snip_set_normalizer(ctx, snip, GRN_NORMALIZER_AUTO); + grn_expr_snip_add_conditions(ctx, condition, snip, + 0, NULL, NULL, NULL, NULL); + GRN_PTR_SET(ctx, snip_ptr, snip); + } + } + } + + if (snip) { + snippets = snippet_exec(ctx, snip, text, user_data, NULL, 0, NULL, 0); + } + } + + if (!snippets) { + snippets = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_VOID, 0); + } + + return snippets; +} + +void +grn_proc_init_snippet_html(grn_ctx *ctx) +{ + grn_proc_create(ctx, "snippet_html", -1, GRN_PROC_FUNCTION, + func_snippet_html, NULL, NULL, 0, NULL); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_table.c b/storage/mroonga/vendor/groonga/lib/proc/proc_table.c new file mode 100644 index 00000000..3c40992d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_table.c @@ -0,0 +1,910 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" + +#include "../grn_ctx.h" +#include "../grn_str.h" +#include "../grn_db.h" + +#include + +static grn_table_flags +command_table_create_parse_flags(grn_ctx *ctx, + const char *nptr, + const char *end) +{ + grn_table_flags flags = 0; + while (nptr < end) { + size_t name_size; + + if (*nptr == '|' || *nptr == ' ') { + nptr += 1; + continue; + } + +#define CHECK_FLAG(name) \ + name_size = strlen(#name); \ + if ((unsigned long) (end - nptr) >= (unsigned long) name_size && \ + memcmp(nptr, #name, name_size) == 0) { \ + flags |= GRN_OBJ_ ## name; \ + nptr += name_size; \ + continue; \ + } + + CHECK_FLAG(TABLE_HASH_KEY); + CHECK_FLAG(TABLE_PAT_KEY); + CHECK_FLAG(TABLE_DAT_KEY); + CHECK_FLAG(TABLE_NO_KEY); + CHECK_FLAG(KEY_NORMALIZE); + CHECK_FLAG(KEY_WITH_SIS); + CHECK_FLAG(KEY_LARGE); + +#undef CHECK_FLAG + + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][create][flags] unknown flag: <%.*s>", + (int)(end - nptr), nptr); + return 0; + } + return flags; +} + +static grn_bool +grn_proc_table_set_token_filters_put(grn_ctx *ctx, + grn_obj *token_filters, + const char *token_filter_name, + int token_filter_name_length) +{ + grn_obj *token_filter; + + token_filter = grn_ctx_get(ctx, + token_filter_name, + token_filter_name_length); + if (token_filter) { + GRN_PTR_PUT(ctx, token_filters, token_filter); + return GRN_TRUE; + } else { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][create][token-filter] " + "nonexistent token filter: <%.*s>", + token_filter_name_length, token_filter_name); + return GRN_FALSE; + } +} + +static grn_bool +grn_proc_table_set_token_filters_fill(grn_ctx *ctx, + grn_obj *token_filters, + grn_obj *token_filter_names) +{ + const char *start, *current, *end; + const char *name_start, *name_end; + const char *last_name_end; + + start = GRN_TEXT_VALUE(token_filter_names); + end = start + GRN_TEXT_LEN(token_filter_names); + current = start; + name_start = NULL; + name_end = NULL; + last_name_end = start; + while (current < end) { + switch (current[0]) { + case ' ' : + if (name_start && !name_end) { + name_end = current; + } + break; + case ',' : + if (!name_start) { + goto break_loop; + } + if (!name_end) { + name_end = current; + } + if (!grn_proc_table_set_token_filters_put(ctx, + token_filters, + name_start, + name_end - name_start)) { + return GRN_FALSE; + } + last_name_end = name_end + 1; + name_start = NULL; + name_end = NULL; + break; + default : + if (!name_start) { + name_start = current; + } + break; + } + current++; + } + +break_loop: + if (!name_start) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][create][token-filter] empty token filter name: " + "<%.*s|%.*s|%.*s>", + (int)(last_name_end - start), start, + (int)(current - last_name_end), last_name_end, + (int)(end - current), current); + return GRN_FALSE; + } + + if (!name_end) { + name_end = current; + } + grn_proc_table_set_token_filters_put(ctx, + token_filters, + name_start, + name_end - name_start); + + return GRN_TRUE; +} + +grn_bool +grn_proc_table_set_token_filters(grn_ctx *ctx, + grn_obj *table, + grn_obj *token_filter_names) +{ + grn_bool succeeded = GRN_FALSE; + grn_obj token_filters; + + if (GRN_TEXT_LEN(token_filter_names) == 0) { + return GRN_TRUE; + } + + GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, 0); + succeeded = grn_proc_table_set_token_filters_fill(ctx, + &token_filters, + token_filter_names); + if (succeeded) { + grn_obj_set_info(ctx, table, GRN_INFO_TOKEN_FILTERS, &token_filters); + } + grn_obj_unlink(ctx, &token_filters); + + return succeeded; +} + +static grn_obj * +command_table_create(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *name; + grn_obj *flags_raw; + grn_obj *key_type_name; + grn_obj *value_type_name; + grn_obj *default_tokenizer_name; + grn_obj *normalizer_name; + grn_obj *token_filters_name; + grn_obj *table; + const char *rest; + grn_table_flags flags; + + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + flags_raw = grn_plugin_proc_get_var(ctx, user_data, "flags", -1); + key_type_name = grn_plugin_proc_get_var(ctx, user_data, "key_type", -1); + value_type_name = grn_plugin_proc_get_var(ctx, user_data, "value_type", -1); + default_tokenizer_name = + grn_plugin_proc_get_var(ctx, user_data, "default_tokenizer", -1); + normalizer_name = + grn_plugin_proc_get_var(ctx, user_data, "normalizer", -1); + token_filters_name = + grn_plugin_proc_get_var(ctx, user_data, "token_filters", -1); + + flags = grn_atoi(GRN_TEXT_VALUE(flags_raw), + GRN_BULK_CURR(flags_raw), + &rest); + + if (GRN_TEXT_VALUE(flags_raw) == rest) { + flags = command_table_create_parse_flags(ctx, + GRN_TEXT_VALUE(flags_raw), + GRN_BULK_CURR(flags_raw)); + if (ctx->rc) { goto exit; } + } + + if (GRN_TEXT_LEN(name) == 0) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][create] should not create anonymous table"); + goto exit; + } + + { + grn_obj *key_type = NULL; + grn_obj *value_type = NULL; + + if (GRN_TEXT_LEN(key_type_name) > 0) { + key_type = grn_ctx_get(ctx, + GRN_TEXT_VALUE(key_type_name), + GRN_TEXT_LEN(key_type_name)); + if (!key_type) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][create] " + "key type doesn't exist: <%.*s> (%.*s)", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name), + (int)GRN_TEXT_LEN(key_type_name), + GRN_TEXT_VALUE(key_type_name)); + goto exit; + } + } + + if (GRN_TEXT_LEN(value_type_name) > 0) { + value_type = grn_ctx_get(ctx, + GRN_TEXT_VALUE(value_type_name), + GRN_TEXT_LEN(value_type_name)); + if (!value_type) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][create] " + "value type doesn't exist: <%.*s> (%.*s)", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name), + (int)GRN_TEXT_LEN(value_type_name), + GRN_TEXT_VALUE(value_type_name)); + goto exit; + } + } + + flags |= GRN_OBJ_PERSISTENT; + table = grn_table_create(ctx, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name), + NULL, flags, + key_type, + value_type); + if (!table) { + goto exit; + } + + if (GRN_TEXT_LEN(default_tokenizer_name) > 0) { + grn_obj *default_tokenizer; + + default_tokenizer = + grn_ctx_get(ctx, + GRN_TEXT_VALUE(default_tokenizer_name), + GRN_TEXT_LEN(default_tokenizer_name)); + if (!default_tokenizer) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][create][%.*s] unknown tokenizer: <%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name), + (int)GRN_TEXT_LEN(default_tokenizer_name), + GRN_TEXT_VALUE(default_tokenizer_name)); + grn_obj_remove(ctx, table); + goto exit; + } + grn_obj_set_info(ctx, table, + GRN_INFO_DEFAULT_TOKENIZER, + default_tokenizer); + } + + if (GRN_TEXT_LEN(normalizer_name) > 0) { + grn_obj *normalizer; + + normalizer = + grn_ctx_get(ctx, + GRN_TEXT_VALUE(normalizer_name), + GRN_TEXT_LEN(normalizer_name)); + if (!normalizer) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][create][%.*s] unknown normalizer: <%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name), + (int)GRN_TEXT_LEN(normalizer_name), + GRN_TEXT_VALUE(normalizer_name)); + grn_obj_remove(ctx, table); + goto exit; + } + grn_obj_set_info(ctx, table, GRN_INFO_NORMALIZER, normalizer); + } + + if (!grn_proc_table_set_token_filters(ctx, table, token_filters_name)) { + grn_obj_remove(ctx, table); + goto exit; + } + + grn_obj_unlink(ctx, table); + } + +exit : + grn_ctx_output_bool(ctx, ctx->rc == GRN_SUCCESS); + return NULL; +} + +void +grn_proc_init_table_create(grn_ctx *ctx) +{ + grn_expr_var vars[7]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "name", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "flags", -1); + grn_plugin_expr_var_init(ctx, &(vars[2]), "key_type", -1); + grn_plugin_expr_var_init(ctx, &(vars[3]), "value_type", -1); + grn_plugin_expr_var_init(ctx, &(vars[4]), "default_tokenizer", -1); + grn_plugin_expr_var_init(ctx, &(vars[5]), "normalizer", -1); + grn_plugin_expr_var_init(ctx, &(vars[6]), "token_filters", -1); + grn_plugin_command_create(ctx, + "table_create", -1, + command_table_create, + 7, + vars); +} + +static int +output_table_info(grn_ctx *ctx, grn_obj *table) +{ + grn_id id; + grn_obj o; + const char *path; + grn_table_flags flags; + grn_obj *default_tokenizer; + grn_obj *normalizer; + grn_obj *token_filters; + + id = grn_obj_id(ctx, table); + path = grn_obj_path(ctx, table); + GRN_TEXT_INIT(&o, 0); + grn_ctx_output_array_open(ctx, "TABLE", 8); + grn_ctx_output_int64(ctx, id); + grn_proc_output_object_id_name(ctx, id); + grn_ctx_output_cstr(ctx, path); + GRN_BULK_REWIND(&o); + + grn_table_get_info(ctx, table, + &flags, + NULL, + &default_tokenizer, + &normalizer, + &token_filters); + grn_dump_table_create_flags(ctx, flags, &o); + grn_ctx_output_obj(ctx, &o, NULL); + grn_proc_output_object_id_name(ctx, table->header.domain); + grn_proc_output_object_id_name(ctx, grn_obj_get_range(ctx, table)); + grn_proc_output_object_name(ctx, default_tokenizer); + grn_proc_output_object_name(ctx, normalizer); + grn_ctx_output_array_close(ctx); + GRN_OBJ_FIN(ctx, &o); + return 1; +} + +static grn_obj * +command_table_list(grn_ctx *ctx, int nargs, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *db; + grn_obj tables; + int n_top_level_elements; + int n_elements_for_header = 1; + int n_tables; + int i; + + db = grn_ctx_db(ctx); + + { + grn_table_cursor *cursor; + grn_id id; + grn_obj *prefix; + const void *min = NULL; + unsigned int min_size = 0; + int flags = 0; + + prefix = grn_plugin_proc_get_var(ctx, user_data, "prefix", -1); + if (GRN_TEXT_LEN(prefix) > 0) { + min = GRN_TEXT_VALUE(prefix); + min_size = GRN_TEXT_LEN(prefix); + flags |= GRN_CURSOR_PREFIX; + } + cursor = grn_table_cursor_open(ctx, db, + min, min_size, + NULL, 0, + 0, -1, flags); + if (!cursor) { + return NULL; + } + + GRN_PTR_INIT(&tables, GRN_OBJ_VECTOR, GRN_ID_NIL); + while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { + grn_obj *object; + const char *name; + void *key; + int i, key_size; + grn_bool have_period = GRN_FALSE; + + key_size = grn_table_cursor_get_key(ctx, cursor, &key); + name = key; + for (i = 0; i < key_size; i++) { + if (name[i] == '.') { + have_period = GRN_TRUE; + break; + } + } + if (have_period) { + continue; + } + + object = grn_ctx_at(ctx, id); + if (object) { + if (grn_obj_is_table(ctx, object)) { + GRN_PTR_PUT(ctx, &tables, object); + } else { + grn_obj_unlink(ctx, object); + } + } else { + if (ctx->rc != GRN_SUCCESS) { + ERRCLR(ctx); + } + } + } + grn_table_cursor_close(ctx, cursor); + } + n_tables = GRN_BULK_VSIZE(&tables) / sizeof(grn_obj *); + n_top_level_elements = n_elements_for_header + n_tables; + grn_ctx_output_array_open(ctx, "TABLE_LIST", n_top_level_elements); + + grn_ctx_output_array_open(ctx, "HEADER", 8); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "id"); + grn_ctx_output_cstr(ctx, "UInt32"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "name"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "path"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "flags"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "domain"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "range"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "default_tokenizer"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_open(ctx, "PROPERTY", 2); + grn_ctx_output_cstr(ctx, "normalizer"); + grn_ctx_output_cstr(ctx, "ShortText"); + grn_ctx_output_array_close(ctx); + grn_ctx_output_array_close(ctx); + + for (i = 0; i < n_tables; i++) { + grn_obj *table = GRN_PTR_VALUE_AT(&tables, i); + output_table_info(ctx, table); + grn_obj_unlink(ctx, table); + } + GRN_OBJ_FIN(ctx, &tables); + + grn_ctx_output_array_close(ctx); + + return NULL; +} + +void +grn_proc_init_table_list(grn_ctx *ctx) +{ + grn_expr_var vars[1]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "prefix", -1); + grn_plugin_command_create(ctx, + "table_list", -1, + command_table_list, + 1, + vars); +} + +static grn_obj * +command_table_remove(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *name; + grn_obj *table; + grn_bool dependent; + + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + dependent = grn_plugin_proc_get_var_bool(ctx, user_data, "dependent", -1, + GRN_FALSE); + table = grn_ctx_get(ctx, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name)); + if (!table) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][remove] table isn't found: <%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + grn_ctx_output_bool(ctx, GRN_FALSE); + return NULL; + } + + if (!grn_obj_is_table(ctx, table)) { + const char *type_name; + type_name = grn_obj_type_to_string(table->header.type); + grn_obj_unlink(ctx, table); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][remove] not table: <%.*s>: <%s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name), + type_name); + grn_ctx_output_bool(ctx, GRN_FALSE); + return NULL; + } + + if (dependent) { + grn_obj_remove_dependent(ctx, table); + } else { + grn_obj_remove(ctx, table); + } + grn_ctx_output_bool(ctx, !ctx->rc); + return NULL; +} + +void +grn_proc_init_table_remove(grn_ctx *ctx) +{ + grn_expr_var vars[2]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "name", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "dependent", -1); + grn_plugin_command_create(ctx, + "table_remove", -1, + command_table_remove, + 2, + vars); +} + +static grn_obj * +command_table_rename(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *name; + grn_obj *new_name; + grn_obj *table = NULL; + + name = grn_plugin_proc_get_var(ctx, user_data, "name", -1); + new_name = grn_plugin_proc_get_var(ctx, user_data, "new_name", -1); + if (GRN_TEXT_LEN(name) == 0) { + rc = GRN_INVALID_ARGUMENT; + GRN_PLUGIN_ERROR(ctx, rc, "[table][rename] table name isn't specified"); + goto exit; + } + table = grn_ctx_get(ctx, GRN_TEXT_VALUE(name), GRN_TEXT_LEN(name)); + if (!table) { + rc = GRN_INVALID_ARGUMENT; + GRN_PLUGIN_ERROR(ctx, + rc, + "[table][rename] table isn't found: <%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + goto exit; + } + if (GRN_TEXT_LEN(new_name) == 0) { + rc = GRN_INVALID_ARGUMENT; + GRN_PLUGIN_ERROR(ctx, + rc, + "[table][rename] new table name isn't specified: <%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + goto exit; + } + rc = grn_table_rename(ctx, table, + GRN_TEXT_VALUE(new_name), + GRN_TEXT_LEN(new_name)); + if (rc != GRN_SUCCESS && ctx->rc == GRN_SUCCESS) { + GRN_PLUGIN_ERROR(ctx, + rc, + "[table][rename] failed to rename: <%.*s> -> <%.*s>", + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name), + (int)GRN_TEXT_LEN(new_name), + GRN_TEXT_VALUE(new_name)); + } +exit : + grn_ctx_output_bool(ctx, !rc); + if (table) { grn_obj_unlink(ctx, table); } + return NULL; +} + +void +grn_proc_init_table_rename(grn_ctx *ctx) +{ + grn_expr_var vars[2]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "name", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "new_name", -1); + grn_plugin_command_create(ctx, + "table_rename", -1, + command_table_rename, + 2, + vars); +} + +static grn_rc +command_table_copy_resolve_target(grn_ctx *ctx, + const char *label, + grn_obj *name, + grn_obj **table) +{ + if (GRN_TEXT_LEN(name) == 0) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][copy] %s name isn't specified", + label); + return ctx->rc; + } + *table = grn_ctx_get(ctx, + GRN_TEXT_VALUE(name), + GRN_TEXT_LEN(name)); + if (!*table) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][copy] %s table isn't found: <%.*s>", + label, + (int)GRN_TEXT_LEN(name), + GRN_TEXT_VALUE(name)); + return ctx->rc; + } + + return ctx->rc; +} + +static void +command_table_copy_same_key_type(grn_ctx *ctx, + grn_obj *from_table, + grn_obj *to_table, + grn_obj *from_name, + grn_obj *to_name) +{ + GRN_TABLE_EACH_BEGIN_FLAGS(ctx, from_table, cursor, from_id, + GRN_CURSOR_BY_KEY | GRN_CURSOR_ASCENDING) { + void *key; + int key_size; + grn_id to_id; + + key_size = grn_table_cursor_get_key(ctx, cursor, &key); + to_id = grn_table_add(ctx, to_table, key, key_size, NULL); + if (to_id == GRN_ID_NIL) { + grn_obj key_buffer; + grn_obj inspected_key; + if (from_table->header.domain == GRN_DB_SHORT_TEXT) { + GRN_SHORT_TEXT_INIT(&key_buffer, 0); + } else { + GRN_VALUE_FIX_SIZE_INIT(&key_buffer, 0, from_table->header.domain); + } + grn_bulk_write(ctx, &key_buffer, key, key_size); + GRN_TEXT_INIT(&inspected_key, 0); + grn_inspect(ctx, &inspected_key, &key_buffer); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][copy] failed to copy key: <%.*s>: " + "<%.*s> -> <%.*s>", + (int)GRN_TEXT_LEN(&inspected_key), + GRN_TEXT_VALUE(&inspected_key), + (int)GRN_TEXT_LEN(from_name), + GRN_TEXT_VALUE(from_name), + (int)GRN_TEXT_LEN(to_name), + GRN_TEXT_VALUE(to_name)); + GRN_OBJ_FIN(ctx, &inspected_key); + GRN_OBJ_FIN(ctx, &key_buffer); + break; + } + } GRN_TABLE_EACH_END(ctx, cursor); +} + +static void +command_table_copy_different(grn_ctx *ctx, + grn_obj *from_table, + grn_obj *to_table, + grn_obj *from_name, + grn_obj *to_name) +{ + grn_obj from_key_buffer; + grn_obj to_key_buffer; + + if (from_table->header.domain == GRN_DB_SHORT_TEXT) { + GRN_SHORT_TEXT_INIT(&from_key_buffer, 0); + } else { + GRN_VALUE_FIX_SIZE_INIT(&from_key_buffer, 0, from_table->header.domain); + } + if (to_table->header.domain == GRN_DB_SHORT_TEXT) { + GRN_SHORT_TEXT_INIT(&to_key_buffer, 0); + } else { + GRN_VALUE_FIX_SIZE_INIT(&to_key_buffer, 0, to_table->header.domain); + } + + GRN_TABLE_EACH_BEGIN_FLAGS(ctx, from_table, cursor, from_id, + GRN_CURSOR_BY_KEY | GRN_CURSOR_ASCENDING) { + void *key; + int key_size; + grn_rc cast_rc; + grn_id to_id; + + GRN_BULK_REWIND(&from_key_buffer); + GRN_BULK_REWIND(&to_key_buffer); + + key_size = grn_table_cursor_get_key(ctx, cursor, &key); + grn_bulk_write(ctx, &from_key_buffer, key, key_size); + cast_rc = grn_obj_cast(ctx, &from_key_buffer, &to_key_buffer, GRN_FALSE); + if (cast_rc != GRN_SUCCESS) { + grn_obj *to_key_type; + grn_obj inspected_key; + grn_obj inspected_to_key_type; + + to_key_type = grn_ctx_at(ctx, to_table->header.domain); + GRN_TEXT_INIT(&inspected_key, 0); + GRN_TEXT_INIT(&inspected_to_key_type, 0); + grn_inspect(ctx, &inspected_key, &from_key_buffer); + grn_inspect(ctx, &inspected_to_key_type, to_key_type); + ERR(cast_rc, + "[table][copy] failed to cast key: <%.*s> -> %.*s: " + "<%.*s> -> <%.*s>", + (int)GRN_TEXT_LEN(&inspected_key), + GRN_TEXT_VALUE(&inspected_key), + (int)GRN_TEXT_LEN(&inspected_to_key_type), + GRN_TEXT_VALUE(&inspected_to_key_type), + (int)GRN_TEXT_LEN(from_name), + GRN_TEXT_VALUE(from_name), + (int)GRN_TEXT_LEN(to_name), + GRN_TEXT_VALUE(to_name)); + GRN_OBJ_FIN(ctx, &inspected_key); + GRN_OBJ_FIN(ctx, &inspected_to_key_type); + break; + } + + to_id = grn_table_add(ctx, to_table, + GRN_BULK_HEAD(&to_key_buffer), + GRN_BULK_VSIZE(&to_key_buffer), + NULL); + if (to_id == GRN_ID_NIL) { + grn_obj inspected_from_key; + grn_obj inspected_to_key; + GRN_TEXT_INIT(&inspected_from_key, 0); + GRN_TEXT_INIT(&inspected_to_key, 0); + grn_inspect(ctx, &inspected_from_key, &from_key_buffer); + grn_inspect(ctx, &inspected_to_key, &to_key_buffer); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "[table][copy] failed to copy key: <%.*s> -> <%.*s>: " + "<%.*s> -> <%.*s>", + (int)GRN_TEXT_LEN(&inspected_from_key), + GRN_TEXT_VALUE(&inspected_from_key), + (int)GRN_TEXT_LEN(&inspected_to_key), + GRN_TEXT_VALUE(&inspected_to_key), + (int)GRN_TEXT_LEN(from_name), + GRN_TEXT_VALUE(from_name), + (int)GRN_TEXT_LEN(to_name), + GRN_TEXT_VALUE(to_name)); + GRN_OBJ_FIN(ctx, &inspected_from_key); + GRN_OBJ_FIN(ctx, &inspected_to_key); + break; + } + } GRN_TABLE_EACH_END(ctx, cursor); + GRN_OBJ_FIN(ctx, &from_key_buffer); + GRN_OBJ_FIN(ctx, &to_key_buffer); +} + +static grn_obj * +command_table_copy(grn_ctx *ctx, + int nargs, + grn_obj **args, + grn_user_data *user_data) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *from_table = NULL; + grn_obj *to_table = NULL; + grn_obj *from_name; + grn_obj *to_name; + + from_name = grn_plugin_proc_get_var(ctx, user_data, "from_name", -1); + to_name = grn_plugin_proc_get_var(ctx, user_data, "to_name", -1); + + rc = command_table_copy_resolve_target(ctx, "from", from_name, &from_table); + if (rc != GRN_SUCCESS) { + goto exit; + } + rc = command_table_copy_resolve_target(ctx, "to", to_name, &to_table); + if (rc != GRN_SUCCESS) { + goto exit; + } + + if (from_table->header.type == GRN_TABLE_NO_KEY || + to_table->header.type == GRN_TABLE_NO_KEY) { + GRN_PLUGIN_ERROR(ctx, + GRN_OPERATION_NOT_SUPPORTED, + "[table][copy] copy from/to TABLE_NO_KEY isn't supported: " + "<%.*s> -> <%.*s>", + (int)GRN_TEXT_LEN(from_name), + GRN_TEXT_VALUE(from_name), + (int)GRN_TEXT_LEN(to_name), + GRN_TEXT_VALUE(to_name)); + rc = ctx->rc; + goto exit; + } + + if (from_table == to_table) { + GRN_PLUGIN_ERROR(ctx, + GRN_OPERATION_NOT_SUPPORTED, + "[table][copy] from table and to table is the same: " + "<%.*s>", + (int)GRN_TEXT_LEN(from_name), + GRN_TEXT_VALUE(from_name)); + rc = ctx->rc; + goto exit; + } + + if (from_table->header.domain == to_table->header.domain) { + command_table_copy_same_key_type(ctx, + from_table, to_table, + from_name, to_name); + } else { + command_table_copy_different(ctx, + from_table, to_table, + from_name, to_name); + } + +exit : + grn_ctx_output_bool(ctx, rc == GRN_SUCCESS); + + if (to_table) { + grn_obj_unlink(ctx, to_table); + } + if (from_table) { + grn_obj_unlink(ctx, from_table); + } + + return NULL; +} + +void +grn_proc_init_table_copy(grn_ctx *ctx) +{ + grn_expr_var vars[2]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "from_name", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "to_name", -1); + grn_plugin_command_create(ctx, + "table_copy", -1, + command_table_copy, + 2, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/proc_tokenize.c b/storage/mroonga/vendor/groonga/lib/proc/proc_tokenize.c new file mode 100644 index 00000000..206ebf58 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/proc_tokenize.c @@ -0,0 +1,433 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "../grn_proc.h" +#include "../grn_ctx.h" +#include "../grn_token_cursor.h" + +#include + +static unsigned int +parse_tokenize_flags(grn_ctx *ctx, grn_obj *flag_names) +{ + unsigned int flags = 0; + const char *names, *names_end; + int length; + + names = GRN_TEXT_VALUE(flag_names); + length = GRN_TEXT_LEN(flag_names); + names_end = names + length; + while (names < names_end) { + if (*names == '|' || *names == ' ') { + names += 1; + continue; + } + +#define CHECK_FLAG(name)\ + if (((unsigned long) (names_end - names) >= (unsigned long) (sizeof(#name) - 1)) &&\ + (!memcmp(names, #name, sizeof(#name) - 1))) {\ + flags |= GRN_TOKEN_CURSOR_ ## name;\ + names += sizeof(#name) - 1;\ + continue;\ + } + + CHECK_FLAG(ENABLE_TOKENIZED_DELIMITER); + +#define GRN_TOKEN_CURSOR_NONE 0 + CHECK_FLAG(NONE); +#undef GRN_TOKEN_CURSOR_NONE + + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[tokenize] invalid flag: <%.*s>", + (int)(names_end - names), names); + return 0; +#undef CHECK_FLAG + } + + return flags; +} + +typedef struct { + grn_id id; + int32_t position; + grn_bool force_prefix; +} tokenize_token; + +static void +output_tokens(grn_ctx *ctx, grn_obj *tokens, grn_obj *lexicon, grn_obj *index_column) +{ + int i, n_tokens, n_elements; + grn_obj estimated_size; + + n_tokens = GRN_BULK_VSIZE(tokens) / sizeof(tokenize_token); + n_elements = 3; + if (index_column) { + n_elements++; + GRN_UINT32_INIT(&estimated_size, 0); + } + + grn_ctx_output_array_open(ctx, "TOKENS", n_tokens); + for (i = 0; i < n_tokens; i++) { + tokenize_token *token; + char value[GRN_TABLE_MAX_KEY_SIZE]; + unsigned int value_size; + + token = ((tokenize_token *)(GRN_BULK_HEAD(tokens))) + i; + + grn_ctx_output_map_open(ctx, "TOKEN", n_elements); + + grn_ctx_output_cstr(ctx, "value"); + value_size = grn_table_get_key(ctx, lexicon, token->id, + value, GRN_TABLE_MAX_KEY_SIZE); + grn_ctx_output_str(ctx, value, value_size); + + grn_ctx_output_cstr(ctx, "position"); + grn_ctx_output_int32(ctx, token->position); + + grn_ctx_output_cstr(ctx, "force_prefix"); + grn_ctx_output_bool(ctx, token->force_prefix); + + if (index_column) { + GRN_BULK_REWIND(&estimated_size); + grn_obj_get_value(ctx, index_column, token->id, &estimated_size); + grn_ctx_output_cstr(ctx, "estimated_size"); + grn_ctx_output_int64(ctx, GRN_UINT32_VALUE(&estimated_size)); + } + + grn_ctx_output_map_close(ctx); + } + + if (index_column) { + GRN_OBJ_FIN(ctx, &estimated_size); + } + + grn_ctx_output_array_close(ctx); +} + +static grn_obj * +create_lexicon_for_tokenize(grn_ctx *ctx, + grn_obj *tokenizer_name, + grn_obj *normalizer_name, + grn_obj *token_filter_names) +{ + grn_obj *lexicon; + grn_obj *tokenizer; + grn_obj *normalizer = NULL; + + tokenizer = grn_ctx_get(ctx, + GRN_TEXT_VALUE(tokenizer_name), + GRN_TEXT_LEN(tokenizer_name)); + if (!tokenizer) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[tokenize] nonexistent tokenizer: <%.*s>", + (int)GRN_TEXT_LEN(tokenizer_name), + GRN_TEXT_VALUE(tokenizer_name)); + return NULL; + } + + if (!grn_obj_is_tokenizer_proc(ctx, tokenizer)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, tokenizer); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[tokenize] not tokenizer: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + grn_obj_unlink(ctx, tokenizer); + return NULL; + } + + if (GRN_TEXT_LEN(normalizer_name) > 0) { + normalizer = grn_ctx_get(ctx, + GRN_TEXT_VALUE(normalizer_name), + GRN_TEXT_LEN(normalizer_name)); + if (!normalizer) { + grn_obj_unlink(ctx, tokenizer); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[tokenize] nonexistent normalizer: <%.*s>", + (int)GRN_TEXT_LEN(normalizer_name), + GRN_TEXT_VALUE(normalizer_name)); + return NULL; + } + + if (!grn_obj_is_normalizer_proc(ctx, normalizer)) { + grn_obj inspected; + grn_obj_unlink(ctx, tokenizer); + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, normalizer); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[tokenize] not normalizer: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + grn_obj_unlink(ctx, normalizer); + return NULL; + } + } + + lexicon = grn_table_create(ctx, NULL, 0, + NULL, + GRN_OBJ_TABLE_HASH_KEY, + grn_ctx_at(ctx, GRN_DB_SHORT_TEXT), + NULL); + grn_obj_set_info(ctx, lexicon, + GRN_INFO_DEFAULT_TOKENIZER, tokenizer); + grn_obj_unlink(ctx, tokenizer); + if (normalizer) { + grn_obj_set_info(ctx, lexicon, + GRN_INFO_NORMALIZER, normalizer); + grn_obj_unlink(ctx, normalizer); + } + grn_proc_table_set_token_filters(ctx, lexicon, token_filter_names); + + return lexicon; +} + +static void +tokenize(grn_ctx *ctx, grn_obj *lexicon, grn_obj *string, grn_tokenize_mode mode, + unsigned int flags, grn_obj *tokens) +{ + grn_token_cursor *token_cursor; + + token_cursor = + grn_token_cursor_open(ctx, lexicon, + GRN_TEXT_VALUE(string), GRN_TEXT_LEN(string), + mode, flags); + if (!token_cursor) { + return; + } + + while (token_cursor->status == GRN_TOKEN_CURSOR_DOING) { + grn_id token_id = grn_token_cursor_next(ctx, token_cursor); + tokenize_token *current_token; + if (token_id == GRN_ID_NIL) { + continue; + } + grn_bulk_space(ctx, tokens, sizeof(tokenize_token)); + current_token = ((tokenize_token *)(GRN_BULK_CURR(tokens))) - 1; + current_token->id = token_id; + current_token->position = token_cursor->pos; + current_token->force_prefix = token_cursor->force_prefix; + } + grn_token_cursor_close(ctx, token_cursor); +} + +static grn_obj * +command_table_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *table_name; + grn_obj *string; + grn_obj *flag_names; + grn_obj *mode_name; + grn_obj *index_column_name; + + table_name = grn_plugin_proc_get_var(ctx, user_data, "table", -1); + string = grn_plugin_proc_get_var(ctx, user_data, "string", -1); + flag_names = grn_plugin_proc_get_var(ctx, user_data, "flags", -1); + mode_name = grn_plugin_proc_get_var(ctx, user_data, "mode", -1); + index_column_name = grn_plugin_proc_get_var(ctx, user_data, "index_column", -1); + + if (GRN_TEXT_LEN(table_name) == 0) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "[table_tokenize] table name is missing"); + return NULL; + } + + if (GRN_TEXT_LEN(string) == 0) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "[table_tokenize] string is missing"); + return NULL; + } + + { + unsigned int flags; + grn_obj *lexicon; + grn_obj *index_column = NULL; + + flags = parse_tokenize_flags(ctx, flag_names); + if (ctx->rc != GRN_SUCCESS) { + return NULL; + } + + lexicon = grn_ctx_get(ctx, GRN_TEXT_VALUE(table_name), GRN_TEXT_LEN(table_name)); + if (!lexicon) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[table_tokenize] nonexistent lexicon: <%.*s>", + (int)GRN_TEXT_LEN(table_name), + GRN_TEXT_VALUE(table_name)); + return NULL; + } + +#define MODE_NAME_EQUAL(name)\ + (GRN_TEXT_LEN(mode_name) == strlen(name) &&\ + memcmp(GRN_TEXT_VALUE(mode_name), name, strlen(name)) == 0) + + if (GRN_TEXT_LEN(index_column_name) > 0) { + index_column = grn_obj_column(ctx, lexicon, + GRN_TEXT_VALUE(index_column_name), + GRN_TEXT_LEN(index_column_name)); + if (!index_column) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[table_tokenize] nonexistent index column: <%.*s>", + (int)GRN_TEXT_LEN(index_column_name), + GRN_TEXT_VALUE(index_column_name)); + goto exit; + } + if (index_column->header.type != GRN_COLUMN_INDEX) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[table_tokenize] index column must be COLUMN_INDEX: <%.*s>", + (int)GRN_TEXT_LEN(index_column_name), + GRN_TEXT_VALUE(index_column_name)); + goto exit; + } + } + + { + grn_obj tokens; + GRN_VALUE_FIX_SIZE_INIT(&tokens, GRN_OBJ_VECTOR, GRN_ID_NIL); + if (GRN_TEXT_LEN(mode_name) == 0 || MODE_NAME_EQUAL("GET")) { + tokenize(ctx, lexicon, string, GRN_TOKEN_GET, flags, &tokens); + output_tokens(ctx, &tokens, lexicon, index_column); + } else if (MODE_NAME_EQUAL("ADD")) { + tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens); + output_tokens(ctx, &tokens, lexicon, index_column); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[table_tokenize] invalid mode: <%.*s>", + (int)GRN_TEXT_LEN(mode_name), GRN_TEXT_VALUE(mode_name)); + } + GRN_OBJ_FIN(ctx, &tokens); + } +#undef MODE_NAME_EQUAL + +exit: + grn_obj_unlink(ctx, lexicon); + if (index_column) { + grn_obj_unlink(ctx, index_column); + } + } + + return NULL; +} + +void +grn_proc_init_table_tokenize(grn_ctx *ctx) +{ + grn_expr_var vars[5]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "table", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "string", -1); + grn_plugin_expr_var_init(ctx, &(vars[2]), "flags", -1); + grn_plugin_expr_var_init(ctx, &(vars[3]), "mode", -1); + grn_plugin_expr_var_init(ctx, &(vars[4]), "index_column", -1); + grn_plugin_command_create(ctx, + "table_tokenize", -1, + command_table_tokenize, + 5, + vars); +} + +static grn_obj * +command_tokenize(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *tokenizer_name; + grn_obj *string; + grn_obj *normalizer_name; + grn_obj *flag_names; + grn_obj *mode_name; + grn_obj *token_filter_names; + + tokenizer_name = grn_plugin_proc_get_var(ctx, user_data, "tokenizer", -1); + string = grn_plugin_proc_get_var(ctx, user_data, "string", -1); + normalizer_name = grn_plugin_proc_get_var(ctx, user_data, "normalizer", -1); + flag_names = grn_plugin_proc_get_var(ctx, user_data, "flags", -1); + mode_name = grn_plugin_proc_get_var(ctx, user_data, "mode", -1); + token_filter_names = grn_plugin_proc_get_var(ctx, user_data, "token_filters", -1); + + if (GRN_TEXT_LEN(tokenizer_name) == 0) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "[tokenize] tokenizer name is missing"); + return NULL; + } + + if (GRN_TEXT_LEN(string) == 0) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "[tokenize] string is missing"); + return NULL; + } + + { + unsigned int flags; + grn_obj *lexicon; + + flags = parse_tokenize_flags(ctx, flag_names); + if (ctx->rc != GRN_SUCCESS) { + return NULL; + } + + lexicon = create_lexicon_for_tokenize(ctx, + tokenizer_name, + normalizer_name, + token_filter_names); + if (!lexicon) { + return NULL; + } +#define MODE_NAME_EQUAL(name)\ + (GRN_TEXT_LEN(mode_name) == strlen(name) &&\ + memcmp(GRN_TEXT_VALUE(mode_name), name, strlen(name)) == 0) + + { + grn_obj tokens; + GRN_VALUE_FIX_SIZE_INIT(&tokens, GRN_OBJ_VECTOR, GRN_ID_NIL); + if (GRN_TEXT_LEN(mode_name) == 0 || MODE_NAME_EQUAL("ADD")) { + tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens); + output_tokens(ctx, &tokens, lexicon, NULL); + } else if (MODE_NAME_EQUAL("GET")) { + tokenize(ctx, lexicon, string, GRN_TOKEN_ADD, flags, &tokens); + GRN_BULK_REWIND(&tokens); + tokenize(ctx, lexicon, string, GRN_TOKEN_GET, flags, &tokens); + output_tokens(ctx, &tokens, lexicon, NULL); + } else { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "[tokenize] invalid mode: <%.*s>", + (int)GRN_TEXT_LEN(mode_name), GRN_TEXT_VALUE(mode_name)); + } + GRN_OBJ_FIN(ctx, &tokens); + } +#undef MODE_NAME_EQUAL + + grn_obj_unlink(ctx, lexicon); + } + + return NULL; +} + +void +grn_proc_init_tokenize(grn_ctx *ctx) +{ + grn_expr_var vars[6]; + + grn_plugin_expr_var_init(ctx, &(vars[0]), "tokenizer", -1); + grn_plugin_expr_var_init(ctx, &(vars[1]), "string", -1); + grn_plugin_expr_var_init(ctx, &(vars[2]), "normalizer", -1); + grn_plugin_expr_var_init(ctx, &(vars[3]), "flags", -1); + grn_plugin_expr_var_init(ctx, &(vars[4]), "mode", -1); + grn_plugin_expr_var_init(ctx, &(vars[5]), "token_filters", -1); + grn_plugin_command_create(ctx, + "tokenize", -1, + command_tokenize, + 6, + vars); +} diff --git a/storage/mroonga/vendor/groonga/lib/proc/sources.am b/storage/mroonga/vendor/groonga/lib/proc/sources.am new file mode 100644 index 00000000..a945320f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/proc/sources.am @@ -0,0 +1,18 @@ +libgrnproc_la_SOURCES = \ + proc_column.c \ + proc_config.c \ + proc_dump.c \ + proc_fuzzy_search.c \ + proc_highlight.c \ + proc_in_records.c \ + proc_lock.c \ + proc_object.c \ + proc_object_inspect.c \ + proc_object_list.c \ + proc_query.c \ + proc_query_log_flags.c \ + proc_schema.c \ + proc_select.c \ + proc_snippet.c \ + proc_table.c \ + proc_tokenize.c diff --git a/storage/mroonga/vendor/groonga/lib/raw_string.c b/storage/mroonga/vendor/groonga/lib/raw_string.c new file mode 100644 index 00000000..794450f8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/raw_string.c @@ -0,0 +1,38 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_raw_string.h" +#include "grn_str.h" + +void +grn_raw_string_lstrip(grn_ctx *ctx, + grn_raw_string *string) +{ + const char *end; + int space_len; + + end = string->value + string->length; + while (string->value < end) { + space_len = grn_isspace(string->value, ctx->encoding); + if (space_len == 0) { + break; + } + string->value += space_len; + string->length -= space_len; + } +} diff --git a/storage/mroonga/vendor/groonga/lib/report.c b/storage/mroonga/vendor/groonga/lib/report.c new file mode 100644 index 00000000..c16e6e68 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/report.c @@ -0,0 +1,98 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_report.h" + +const grn_log_level GRN_REPORT_INDEX_LOG_LEVEL = GRN_LOG_INFO; + +void +grn_report_index(grn_ctx *ctx, + const char *action, + const char *tag, + grn_obj *index) +{ + char index_name[GRN_TABLE_MAX_KEY_SIZE]; + int index_name_size; + + if (!grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { + return; + } + + index_name_size = grn_obj_name(ctx, index, index_name, GRN_TABLE_MAX_KEY_SIZE); + GRN_LOG(ctx, GRN_REPORT_INDEX_LOG_LEVEL, + "%s[index]%s <%.*s>", + action, tag, index_name_size, index_name); +} + +void +grn_report_index_not_used(grn_ctx *ctx, + const char *action, + const char *tag, + grn_obj *index, + const char *reason) +{ + char index_name[GRN_TABLE_MAX_KEY_SIZE]; + int index_name_size; + + if (!grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { + return; + } + + index_name_size = grn_obj_name(ctx, index, index_name, GRN_TABLE_MAX_KEY_SIZE); + GRN_LOG(ctx, GRN_REPORT_INDEX_LOG_LEVEL, + "%s[index-not-used]%s <%.*s>: %s", + action, tag, index_name_size, index_name, reason); +} + +void +grn_report_table(grn_ctx *ctx, + const char *action, + const char *tag, + grn_obj *table) +{ + grn_obj description; + grn_obj *target; + + if (!grn_logger_pass(ctx, GRN_REPORT_INDEX_LOG_LEVEL)) { + return; + } + + GRN_TEXT_INIT(&description, 0); + for (target = table; target; target = grn_ctx_at(ctx, target->header.domain)) { + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + name_size = grn_obj_name(ctx, target, name, GRN_TABLE_MAX_KEY_SIZE); + if (GRN_TEXT_LEN(&description) > 0) { + GRN_TEXT_PUTS(ctx, &description, " -> "); + } + if (name_size == 0) { + GRN_TEXT_PUTS(ctx, &description, "(temporary)"); + } else { + GRN_TEXT_PUTS(ctx, &description, "<"); + GRN_TEXT_PUT(ctx, &description, name, name_size); + GRN_TEXT_PUTS(ctx, &description, ">"); + } + } + GRN_LOG(ctx, GRN_REPORT_INDEX_LOG_LEVEL, + "%s[table]%s %.*s", + action, tag, + (int)GRN_TEXT_LEN(&description), + GRN_TEXT_VALUE(&description)); + GRN_OBJ_FIN(ctx, &description); +} diff --git a/storage/mroonga/vendor/groonga/lib/request_canceler.c b/storage/mroonga/vendor/groonga/lib/request_canceler.c new file mode 100644 index 00000000..c5aedf3e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/request_canceler.c @@ -0,0 +1,176 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_ctx.h" +#include "grn_ctx_impl.h" +#include "grn_request_canceler.h" + +typedef struct _grn_request_canceler grn_request_canceler; +struct _grn_request_canceler { + grn_hash *entries; + grn_mutex mutex; +}; + +typedef struct _grn_request_canceler_entry grn_request_canceler_entry; +struct _grn_request_canceler_entry { + grn_ctx *ctx; +}; + +static grn_ctx grn_the_request_canceler_ctx; +static grn_request_canceler *grn_the_request_canceler = NULL; + +grn_bool +grn_request_canceler_init(void) +{ + grn_ctx *ctx = &grn_the_request_canceler_ctx; + + grn_ctx_init(ctx, 0); + + grn_the_request_canceler = GRN_MALLOC(sizeof(grn_request_canceler)); + if (!grn_the_request_canceler) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[request-canceler] failed to allocate the global request canceler"); + return GRN_FALSE; + } + + grn_the_request_canceler->entries = + grn_hash_create(ctx, NULL, GRN_TABLE_MAX_KEY_SIZE, + sizeof(grn_request_canceler_entry), GRN_OBJ_KEY_VAR_SIZE); + if (!grn_the_request_canceler->entries) { + return GRN_FALSE; + } + MUTEX_INIT(grn_the_request_canceler->mutex); + + return GRN_TRUE; +} + +void +grn_request_canceler_register(grn_ctx *ctx, + const char *request_id, unsigned int size) +{ + MUTEX_LOCK(grn_the_request_canceler->mutex); + { + grn_hash *entries = grn_the_request_canceler->entries; + grn_id id; + void *value; + id = grn_hash_add(&grn_the_request_canceler_ctx, + entries, request_id, size, &value, NULL); + if (id) { + grn_request_canceler_entry *entry = value; + entry->ctx = ctx; + } + } + MUTEX_UNLOCK(grn_the_request_canceler->mutex); +} + +void +grn_request_canceler_unregister(grn_ctx *ctx, + const char *request_id, unsigned int size) +{ + MUTEX_LOCK(grn_the_request_canceler->mutex); + { + grn_hash *entries = grn_the_request_canceler->entries; + grn_hash_delete(&grn_the_request_canceler_ctx, + entries, request_id, size, NULL); + } + MUTEX_UNLOCK(grn_the_request_canceler->mutex); + + if (ctx->rc == GRN_CANCEL) { + ERRSET(ctx, GRN_LOG_NOTICE, ctx->rc, + "[request-canceler] a request is canceled: <%.*s>", + size, request_id); + } +} + +static grn_bool +grn_request_canceler_cancel_entry(grn_request_canceler_entry *entry) +{ + if (entry->ctx->rc == GRN_SUCCESS) { + entry->ctx->rc = GRN_CANCEL; + if (entry->ctx->impl->current_request_timer_id) { + void *timer_id = entry->ctx->impl->current_request_timer_id; + entry->ctx->impl->current_request_timer_id = NULL; + grn_request_timer_unregister(timer_id); + } + return GRN_TRUE; + } else { + return GRN_FALSE; + } +} + +grn_bool +grn_request_canceler_cancel(const char *request_id, unsigned int size) +{ + grn_bool canceled = GRN_FALSE; + MUTEX_LOCK(grn_the_request_canceler->mutex); + { + grn_ctx *ctx = &grn_the_request_canceler_ctx; + grn_hash *entries = grn_the_request_canceler->entries; + void *value; + if (grn_hash_get(ctx, entries, request_id, size, &value)) { + grn_request_canceler_entry *entry = value; + if (grn_request_canceler_cancel_entry(entry)) { + canceled = GRN_TRUE; + } + } + } + MUTEX_UNLOCK(grn_the_request_canceler->mutex); + return canceled; +} + +grn_bool +grn_request_canceler_cancel_all(void) +{ + grn_bool canceled = GRN_FALSE; + MUTEX_LOCK(grn_the_request_canceler->mutex); + { + grn_ctx *ctx = &grn_the_request_canceler_ctx; + grn_hash *entries = grn_the_request_canceler->entries; + grn_hash_cursor *cursor; + + cursor = grn_hash_cursor_open(ctx, entries, + NULL, 0, NULL, 0, + 0, -1, 0); + if (cursor) { + while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { + void *value; + if (grn_hash_cursor_get_value(ctx, cursor, &value) > 0) { + grn_request_canceler_entry *entry = value; + if (grn_request_canceler_cancel_entry(entry)) { + canceled = GRN_TRUE; + } + } + } + grn_hash_cursor_close(ctx, cursor); + } + } + MUTEX_UNLOCK(grn_the_request_canceler->mutex); + return canceled; +} + +void +grn_request_canceler_fin(void) +{ + grn_ctx *ctx = &grn_the_request_canceler_ctx; + + grn_hash_close(ctx, grn_the_request_canceler->entries); + MUTEX_FIN(grn_the_request_canceler->mutex); + GRN_FREE(grn_the_request_canceler); + grn_the_request_canceler = NULL; + grn_ctx_fin(ctx); +} diff --git a/storage/mroonga/vendor/groonga/lib/request_timer.c b/storage/mroonga/vendor/groonga/lib/request_timer.c new file mode 100644 index 00000000..23a0c644 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/request_timer.c @@ -0,0 +1,88 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_ctx.h" +#include "grn_request_timer.h" + +static grn_request_timer grn_current_request_timer = { 0 }; +static double grn_request_timer_default_timeout = 0.0; + +grn_bool +grn_request_timer_init(void) +{ + return GRN_TRUE; +} + +void * +grn_request_timer_register(const char *request_id, + unsigned int request_id_size, + double timeout) +{ + void *timer_id = NULL; + + if (grn_current_request_timer.register_func) { + void *user_data = grn_current_request_timer.user_data; + timer_id = grn_current_request_timer.register_func(request_id, + request_id_size, + timeout, + user_data); + } + + return timer_id; +} + +void +grn_request_timer_unregister(void *timer_id) +{ + if (grn_current_request_timer.unregister_func) { + void *user_data = grn_current_request_timer.user_data; + grn_current_request_timer.unregister_func(timer_id, user_data); + } +} + +void +grn_request_timer_set(grn_request_timer *timer) +{ + if (grn_current_request_timer.fin_func) { + void *user_data = grn_current_request_timer.user_data; + grn_current_request_timer.fin_func(user_data); + } + if (timer) { + grn_current_request_timer = *timer; + } else { + memset(&grn_current_request_timer, 0, sizeof(grn_request_timer)); + } +} + +double +grn_get_default_request_timeout(void) +{ + return grn_request_timer_default_timeout; +} + +void +grn_set_default_request_timeout(double timeout) +{ + grn_request_timer_default_timeout = timeout; +} + +void +grn_request_timer_fin(void) +{ + grn_request_timer_set(NULL); +} diff --git a/storage/mroonga/vendor/groonga/lib/rset.c b/storage/mroonga/vendor/groonga/lib/rset.c new file mode 100644 index 00000000..f7b50039 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/rset.c @@ -0,0 +1,324 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2009-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn_db.h" + +uint32_t +grn_rset_recinfo_calc_values_size(grn_ctx *ctx, grn_table_group_flags flags) +{ + uint32_t size = 0; + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + size += GRN_RSET_MAX_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_MIN) { + size += GRN_RSET_MIN_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_SUM) { + size += GRN_RSET_SUM_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_AVG) { + size += GRN_RSET_AVG_SIZE; + } + + return size; +} + +void +grn_rset_recinfo_update_calc_values(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + grn_obj *value) +{ + grn_table_group_flags flags; + byte *values; + grn_obj value_int64; + grn_obj value_float; + + flags = DB_OBJ(table)->flags.group; + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + GRN_INT64_INIT(&value_int64, 0); + GRN_FLOAT_INIT(&value_float, 0); + + if (flags & (GRN_TABLE_GROUP_CALC_MAX | + GRN_TABLE_GROUP_CALC_MIN | + GRN_TABLE_GROUP_CALC_SUM)) { + grn_obj_cast(ctx, value, &value_int64, GRN_FALSE); + } + if (flags & GRN_TABLE_GROUP_CALC_AVG) { + grn_obj_cast(ctx, value, &value_float, GRN_FALSE); + } + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + int64_t current_max = *((int64_t *)values); + int64_t value_raw = GRN_INT64_VALUE(&value_int64); + if (ri->n_subrecs == 1 || value_raw > current_max) { + *((int64_t *)values) = value_raw; + } + values += GRN_RSET_MAX_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_MIN) { + int64_t current_min = *((int64_t *)values); + int64_t value_raw = GRN_INT64_VALUE(&value_int64); + if (ri->n_subrecs == 1 || value_raw < current_min) { + *((int64_t *)values) = value_raw; + } + values += GRN_RSET_MIN_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_SUM) { + int64_t value_raw = GRN_INT64_VALUE(&value_int64); + *((int64_t *)values) += value_raw; + values += GRN_RSET_SUM_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_AVG) { + double current_average = *((double *)values); + double value_raw = GRN_FLOAT_VALUE(&value_float); + *((double *)values) += (value_raw - current_average) / ri->n_subrecs; + values += GRN_RSET_AVG_SIZE; + } + + GRN_OBJ_FIN(ctx, &value_float); + GRN_OBJ_FIN(ctx, &value_int64); +} + +int64_t * +grn_rset_recinfo_get_max_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + grn_table_group_flags flags; + byte *values; + + flags = DB_OBJ(table)->flags.group; + if (!(flags & GRN_TABLE_GROUP_CALC_MAX)) { + return NULL; + } + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + return (int64_t *)values; +} + +int64_t +grn_rset_recinfo_get_max(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + int64_t *max_address; + + max_address = grn_rset_recinfo_get_max_(ctx, ri, table); + if (max_address) { + return *max_address; + } else { + return 0; + } +} + +void +grn_rset_recinfo_set_max(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t max) +{ + int64_t *max_address; + + max_address = grn_rset_recinfo_get_max_(ctx, ri, table); + if (!max_address) { + return; + } + + *max_address = max; +} + +int64_t * +grn_rset_recinfo_get_min_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + grn_table_group_flags flags; + byte *values; + + flags = DB_OBJ(table)->flags.group; + if (!(flags & GRN_TABLE_GROUP_CALC_MIN)) { + return NULL; + } + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + values += GRN_RSET_MAX_SIZE; + } + + return (int64_t *)values; +} + +int64_t +grn_rset_recinfo_get_min(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + int64_t *min_address; + + min_address = grn_rset_recinfo_get_min_(ctx, ri, table); + if (min_address) { + return *min_address; + } else { + return 0; + } +} + +void +grn_rset_recinfo_set_min(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t min) +{ + int64_t *min_address; + + min_address = grn_rset_recinfo_get_min_(ctx, ri, table); + if (!min_address) { + return; + } + + *min_address = min; +} + +int64_t * +grn_rset_recinfo_get_sum_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + grn_table_group_flags flags; + byte *values; + + flags = DB_OBJ(table)->flags.group; + if (!(flags & GRN_TABLE_GROUP_CALC_SUM)) { + return NULL; + } + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + values += GRN_RSET_MAX_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_MIN) { + values += GRN_RSET_MIN_SIZE; + } + + return (int64_t *)values; +} + +int64_t +grn_rset_recinfo_get_sum(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + int64_t *sum_address; + + sum_address = grn_rset_recinfo_get_sum_(ctx, ri, table); + if (sum_address) { + return *sum_address; + } else { + return 0; + } +} + +void +grn_rset_recinfo_set_sum(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + int64_t sum) +{ + int64_t *sum_address; + + sum_address = grn_rset_recinfo_get_sum_(ctx, ri, table); + if (!sum_address) { + return; + } + + *sum_address = sum; +} + +double * +grn_rset_recinfo_get_avg_(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + grn_table_group_flags flags; + byte *values; + + flags = DB_OBJ(table)->flags.group; + if (!(flags & GRN_TABLE_GROUP_CALC_AVG)) { + return NULL; + } + + values = (((byte *)ri->subrecs) + + GRN_RSET_SUBRECS_SIZE(DB_OBJ(table)->subrec_size, + DB_OBJ(table)->max_n_subrecs)); + + if (flags & GRN_TABLE_GROUP_CALC_MAX) { + values += GRN_RSET_MAX_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_MIN) { + values += GRN_RSET_MIN_SIZE; + } + if (flags & GRN_TABLE_GROUP_CALC_SUM) { + values += GRN_RSET_SUM_SIZE; + } + + return (double *)values; +} + +double +grn_rset_recinfo_get_avg(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table) +{ + double *avg_address; + + avg_address = grn_rset_recinfo_get_avg_(ctx, ri, table); + if (avg_address) { + return *avg_address; + } else { + return 0; + } +} + +void +grn_rset_recinfo_set_avg(grn_ctx *ctx, + grn_rset_recinfo *ri, + grn_obj *table, + double avg) +{ + double *avg_address; + + avg_address = grn_rset_recinfo_get_avg_(ctx, ri, table); + if (!avg_address) { + return; + } + + *avg_address = avg; +} diff --git a/storage/mroonga/vendor/groonga/lib/scanner.c b/storage/mroonga/vendor/groonga/lib/scanner.c new file mode 100644 index 00000000..9ac0f164 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/scanner.c @@ -0,0 +1,73 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_scanner.h" + +grn_scanner * +grn_scanner_open(grn_ctx *ctx, + grn_obj *expr, + grn_operator op, + grn_bool record_exist) +{ + grn_scanner *scanner; + + scanner = GRN_MALLOC(sizeof(grn_scanner)); + if (!scanner) { + return NULL; + } + + scanner->source_expr = expr; + scanner->expr = grn_expr_rewrite(ctx, expr); + if (!scanner->expr) { + scanner->expr = expr; + } + + scanner->sis = grn_scan_info_build(ctx, + scanner->expr, + &(scanner->n_sis), + op, + record_exist); + if (!scanner->sis) { + grn_scanner_close(ctx, scanner); + return NULL; + } + + return scanner; +} + +void +grn_scanner_close(grn_ctx *ctx, grn_scanner *scanner) +{ + if (!scanner) { + return; + } + + if (scanner->sis) { + int i; + for (i = 0; i < scanner->n_sis; i++) { + grn_scan_info_close(ctx, scanner->sis[i]); + } + GRN_FREE(scanner->sis); + } + + if (scanner->expr != scanner->source_expr) { + grn_obj_close(ctx, scanner->expr); + } + + GRN_FREE(scanner); +} diff --git a/storage/mroonga/vendor/groonga/lib/scorer.c b/storage/mroonga/vendor/groonga/lib/scorer.c new file mode 100644 index 00000000..5791ad35 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/scorer.c @@ -0,0 +1,189 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include + +#include "grn.h" +#include "grn_db.h" +#include "grn_scorer.h" +#include + +grn_obj * +grn_scorer_matched_record_get_table(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->table; +} + +grn_obj * +grn_scorer_matched_record_get_lexicon(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->lexicon; +} + +grn_id +grn_scorer_matched_record_get_id(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->id; +} + +grn_obj * +grn_scorer_matched_record_get_terms(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return &(record->terms); +} + +grn_obj * +grn_scorer_matched_record_get_term_weights(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return &(record->term_weights); +} + +unsigned int +grn_scorer_matched_record_get_total_term_weights(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->total_term_weights; +} + +long long unsigned int +grn_scorer_matched_record_get_n_documents(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->n_documents; +} + +unsigned int +grn_scorer_matched_record_get_n_occurrences(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->n_occurrences; +} + +long long unsigned int +grn_scorer_matched_record_get_n_candidates(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->n_candidates; +} + +unsigned int +grn_scorer_matched_record_get_n_tokens(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->n_tokens; +} + +int +grn_scorer_matched_record_get_weight(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + return record->weight; +} + +grn_obj * +grn_scorer_matched_record_get_arg(grn_ctx *ctx, + grn_scorer_matched_record *record, + unsigned int i) +{ + grn_expr *expr; + grn_expr_code *codes_original; + uint32_t codes_curr_original; + grn_obj *arg; + + if (!record->args_expr) { + return NULL; + } + + expr = (grn_expr *)(record->args_expr); + /* TODO: support getting column value */ + codes_original = expr->codes; + codes_curr_original = expr->codes_curr; + expr->codes += record->args_expr_offset; + expr->codes_curr = 1; /* TODO: support 1 or more codes */ + arg = grn_expr_exec(ctx, (grn_obj *)expr, 0); + expr->codes_curr = codes_curr_original; + expr->codes = codes_original; + + return arg; +} + +unsigned int +grn_scorer_matched_record_get_n_args(grn_ctx *ctx, + grn_scorer_matched_record *record) +{ + grn_expr *expr; + grn_expr_code *codes; + unsigned int n_args = 0; + + if (!record->args_expr) { + return 0; + } + + expr = (grn_expr *)(record->args_expr); + codes = expr->codes + record->args_expr_offset; + if (codes[0].op == GRN_OP_CALL) { + return 0; + } + + n_args++; + for (; codes[0].op != GRN_OP_CALL; codes++) { + if (codes[0].op == GRN_OP_COMMA) { + n_args++; + } + } + + return n_args; +} + +grn_rc +grn_scorer_register(grn_ctx *ctx, + const char *scorer_name_ptr, + int scorer_name_length, + grn_scorer_score_func *score) +{ + if (scorer_name_length == -1) { + scorer_name_length = strlen(scorer_name_ptr); + } + + { + grn_obj *scorer_object = grn_proc_create(ctx, + scorer_name_ptr, + scorer_name_length, + GRN_PROC_SCORER, + NULL, NULL, NULL, 0, NULL); + if (scorer_object == NULL) { + GRN_PLUGIN_ERROR(ctx, GRN_SCORER_ERROR, + "[scorer][%.*s] failed to grn_proc_create()", + scorer_name_length, scorer_name_ptr); + return ctx->rc; + } + + { + grn_proc *scorer = (grn_proc *)scorer_object; + scorer->callbacks.scorer.score = score; + } + } + + return GRN_SUCCESS; +} + diff --git a/storage/mroonga/vendor/groonga/lib/scorers.c b/storage/mroonga/vendor/groonga/lib/scorers.c new file mode 100644 index 00000000..44a3e9b4 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/scorers.c @@ -0,0 +1,96 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_db.h" + +#include + +#include + +static double +scorer_tf_idf(grn_ctx *ctx, grn_scorer_matched_record *record) +{ + double min_score = 1.0; + double tf; + double n_all_documents; + double n_candidates; + double n_tokens; + double n_estimated_match_documents; + + tf = grn_scorer_matched_record_get_n_occurrences(ctx, record) + + grn_scorer_matched_record_get_total_term_weights(ctx, record); + n_all_documents = grn_scorer_matched_record_get_n_documents(ctx, record); + n_candidates = grn_scorer_matched_record_get_n_candidates(ctx, record); + n_tokens = grn_scorer_matched_record_get_n_tokens(ctx, record); + n_estimated_match_documents = n_candidates / n_tokens; + + if (n_estimated_match_documents >= n_all_documents) { + return min_score; + } else { + double idf; + double tf_idf; + + idf = log(n_all_documents / n_estimated_match_documents); + tf_idf = tf * idf; + return fmax(tf_idf, min_score); + } +} + +static double +scorer_tf_at_most(grn_ctx *ctx, grn_scorer_matched_record *record) +{ + double tf; + double max; + grn_obj *max_raw; + + tf = grn_scorer_matched_record_get_n_occurrences(ctx, record) + + grn_scorer_matched_record_get_total_term_weights(ctx, record); + max_raw = grn_scorer_matched_record_get_arg(ctx, record, 0); + + if (!max_raw) { + return tf; + } + + if (max_raw->header.type != GRN_BULK) { + return tf; + } + + if (max_raw->header.domain == GRN_DB_FLOAT) { + max = GRN_FLOAT_VALUE(max_raw); + } else { + grn_obj casted_max_raw; + GRN_FLOAT_INIT(&casted_max_raw, 0); + if (grn_obj_cast(ctx, max_raw, &casted_max_raw, GRN_FALSE) != GRN_SUCCESS) { + GRN_OBJ_FIN(ctx, &casted_max_raw); + return tf; + } else { + max = GRN_FLOAT_VALUE(&casted_max_raw); + } + GRN_OBJ_FIN(ctx, &casted_max_raw); + } + + return fmin(tf, max); +} + +grn_rc +grn_db_init_builtin_scorers(grn_ctx *ctx) +{ + grn_scorer_register(ctx, "scorer_tf_idf", -1, scorer_tf_idf); + grn_scorer_register(ctx, "scorer_tf_at_most", -1, scorer_tf_at_most); + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/snip.c b/storage/mroonga/vendor/groonga/lib/snip.c new file mode 100644 index 00000000..4693dc2b --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/snip.c @@ -0,0 +1,841 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2009-2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include +#include +#include "grn_snip.h" +#include "grn_ctx.h" + +#if !defined MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#if !defined MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +static int +grn_bm_check_euc(const unsigned char *x, const size_t y) +{ + const unsigned char *p; + for (p = x + y - 1; p >= x && *p >= 0x80U; p--); + return (int) ((x + y - p) & 1); +} + +static int +grn_bm_check_sjis(const unsigned char *x, const size_t y) +{ + const unsigned char *p; + for (p = x + y - 1; p >= x; p--) + if ((*p < 0x81U) || (*p > 0x9fU && *p < 0xe0U) || (*p > 0xfcU)) + break; + return (int) ((x + y - p) & 1); +} + +/* +static void +grn_bm_suffixes(const unsigned char *x, size_t m, size_t *suff) +{ + size_t f, g; + intptr_t i; + f = 0; + suff[m - 1] = m; + g = m - 1; + for (i = m - 2; i >= 0; --i) { + if (i > (intptr_t) g && suff[i + m - 1 - f] < i - g) + suff[i] = suff[i + m - 1 - f]; + else { + if (i < (intptr_t) g) + g = i; + f = i; + while (g > 0 && x[g] == x[g + m - 1 - f]) + --g; + suff[i] = f - g; + } + } +} +*/ + +static void +grn_bm_preBmBc(const unsigned char *x, size_t m, size_t *bmBc) +{ + size_t i; + for (i = 0; i < ASIZE; ++i) { + bmBc[i] = m; + } + for (i = 0; i < m - 1; ++i) { + bmBc[(unsigned int) x[i]] = m - (i + 1); + } +} + +#define GRN_BM_COMPARE do { \ + if (string_checks[found]) { \ + size_t offset = cond->last_offset, found_alpha_head = cond->found_alpha_head; \ + /* calc real offset */\ + for (i = cond->last_found; i < found; i++) { \ + if (string_checks[i] > 0) { \ + found_alpha_head = i; \ + offset += string_checks[i]; \ + } \ + } \ + /* if real offset is in a character, move it the head of the character */ \ + if (string_checks[found] < 0) { \ + offset -= string_checks[found_alpha_head]; \ + cond->last_found = found_alpha_head; \ + } else { \ + cond->last_found = found; \ + } \ + cond->start_offset = cond->last_offset = offset; \ + if (flags & GRN_SNIP_SKIP_LEADING_SPACES) { \ + while (cond->start_offset < string_original_length_in_bytes && \ + (i = grn_isspace(string_original + cond->start_offset, \ + string_encoding))) { cond->start_offset += i; } \ + } \ + for (i = cond->last_found; i < found + m; i++) { \ + if (string_checks[i] > 0) { \ + offset += string_checks[i]; \ + } \ + } \ + cond->end_offset = offset; \ + cond->found = found + shift; \ + cond->found_alpha_head = found_alpha_head; \ + /* printf("bm: cond:%p found:%zd last_found:%zd st_off:%zd ed_off:%zd\n", cond, cond->found,cond->last_found,cond->start_offset,cond->end_offset); */ \ + return; \ + } \ +} while (0) + +#define GRN_BM_BM_COMPARE do { \ + if (p[-2] == ck) { \ + for (i = 3; i <= m && p[-(intptr_t)i] == cp[-(intptr_t)i]; ++i) { \ + } \ + if (i > m) { \ + found = p - y - m; \ + GRN_BM_COMPARE; \ + } \ + } \ +} while (0) + +void +grn_bm_tunedbm(grn_ctx *ctx, snip_cond *cond, grn_obj *string, int flags) +{ + register unsigned char *limit, ck; + register const unsigned char *p, *cp; + register size_t *bmBc, delta1, i; + + const unsigned char *x; + unsigned char *y; + size_t shift, found; + + const char *string_original; + unsigned int string_original_length_in_bytes; + const short *string_checks; + grn_encoding string_encoding; + const char *string_norm, *keyword_norm; + unsigned int n, m; + + grn_string_get_original(ctx, string, + &string_original, &string_original_length_in_bytes); + string_checks = grn_string_get_checks(ctx, string); + string_encoding = grn_string_get_encoding(ctx, string); + grn_string_get_normalized(ctx, string, &string_norm, &n, NULL); + grn_string_get_normalized(ctx, cond->keyword, &keyword_norm, &m, NULL); + + y = (unsigned char *)string_norm; + if (m == 1) { + if (n > cond->found) { + shift = 1; + p = memchr(y + cond->found, keyword_norm[0], n - cond->found); + if (p != NULL) { + found = p - y; + GRN_BM_COMPARE; + } + } + cond->stopflag = SNIPCOND_STOP; + return; + } + + x = (unsigned char *)keyword_norm; + bmBc = cond->bmBc; + shift = cond->shift; + + /* Restart */ + p = y + m + cond->found; + cp = x + m; + ck = cp[-2]; + + /* 12 means 1(initial offset) + 10 (in loop) + 1 (shift) */ + if (n - cond->found > 12 * m) { + limit = y + n - 11 * m; + while (p <= limit) { + p += bmBc[p[-1]]; + if(!(delta1 = bmBc[p[-1]])) { + goto check; + } + p += delta1; + p += bmBc[p[-1]]; + p += bmBc[p[-1]]; + if(!(delta1 = bmBc[p[-1]])) { + goto check; + } + p += delta1; + p += bmBc[p[-1]]; + p += bmBc[p[-1]]; + if(!(delta1 = bmBc[p[-1]])) { + goto check; + } + p += delta1; + p += bmBc[p[-1]]; + p += bmBc[p[-1]]; + continue; + check: + GRN_BM_BM_COMPARE; + p += shift; + } + } + /* limit check + search */ + limit = y + n; + while(p <= limit) { + if (!(delta1 = bmBc[p[-1]])) { + GRN_BM_BM_COMPARE; + p += shift; + } + p += delta1; + } + cond->stopflag = SNIPCOND_STOP; +} + +static size_t +count_mapped_chars(const char *str, const char *end) +{ + const char *p; + size_t dl; + + dl = 0; + for (p = str; p != end; p++) { + switch (*p) { + case '<': + case '>': + dl += 4; /* < or > */ + break; + case '&': + dl += 5; /* & */ + break; + case '"': + dl += 6; /* " */ + break; + default: + dl++; + break; + } + } + return dl; +} + +grn_rc +grn_snip_cond_close(grn_ctx *ctx, snip_cond *cond) +{ + if (!cond) { + return GRN_INVALID_ARGUMENT; + } + if (cond->keyword) { + grn_obj_close(ctx, cond->keyword); + } + return GRN_SUCCESS; +} + +grn_rc +grn_snip_cond_init(grn_ctx *ctx, snip_cond *sc, const char *keyword, unsigned int keyword_len, + grn_encoding enc, grn_obj *normalizer, int flags) +{ + const char *norm; + unsigned int norm_blen; + int f = GRN_STR_REMOVEBLANK; + memset(sc, 0, sizeof(snip_cond)); + if (!(sc->keyword = grn_string_open(ctx, keyword, keyword_len, + normalizer, f))) { + GRN_LOG(ctx, GRN_LOG_ALERT, + "grn_string_open on snip_cond_init failed!"); + return GRN_NO_MEMORY_AVAILABLE; + } + grn_string_get_normalized(ctx, sc->keyword, &norm, &norm_blen, NULL); + if (!norm_blen) { + grn_snip_cond_close(ctx, sc); + return GRN_INVALID_ARGUMENT; + } + if (norm_blen != 1) { + grn_bm_preBmBc((unsigned char *)norm, norm_blen, sc->bmBc); + sc->shift = sc->bmBc[(unsigned char)norm[norm_blen - 1]]; + sc->bmBc[(unsigned char)norm[norm_blen - 1]] = 0; + } + return GRN_SUCCESS; +} + +void +grn_snip_cond_reinit(snip_cond *cond) +{ + cond->found = 0; + cond->last_found = 0; + cond->last_offset = 0; + cond->start_offset = 0; + cond->end_offset = 0; + + cond->count = 0; + cond->stopflag = SNIPCOND_NONSTOP; +} + +inline static char * +grn_snip_strndup(grn_ctx *ctx, const char *string, unsigned int string_len) +{ + char *copied_string; + + copied_string = GRN_MALLOC(string_len + 1); + if (!copied_string) { + return NULL; + } + grn_memcpy(copied_string, string, string_len); + copied_string[string_len]= '\0'; /* not required, but for ql use */ + return copied_string; +} + +inline static grn_rc +grn_snip_cond_set_tag(grn_ctx *ctx, + const char **dest_tag, size_t *dest_tag_len, + const char *tag, unsigned int tag_len, + const char *default_tag, unsigned int default_tag_len, + int copy_tag) +{ + if (tag) { + if (copy_tag) { + char *copied_tag; + copied_tag = grn_snip_strndup(ctx, tag, tag_len); + if (!copied_tag) { + return GRN_NO_MEMORY_AVAILABLE; + } + *dest_tag = copied_tag; + } else { + *dest_tag = tag; + } + *dest_tag_len = tag_len; + } else { + *dest_tag = default_tag; + *dest_tag_len = default_tag_len; + } + return GRN_SUCCESS; +} + +grn_rc +grn_snip_set_normalizer(grn_ctx *ctx, grn_obj *snip, + grn_obj *normalizer) +{ + grn_snip *snip_; + if (!snip) { + return GRN_INVALID_ARGUMENT; + } + + snip_ = (grn_snip *)snip; + snip_->normalizer = normalizer; + return GRN_SUCCESS; +} + +grn_obj * +grn_snip_get_normalizer(grn_ctx *ctx, grn_obj *snip) +{ + grn_snip *snip_; + + if (!snip) { + return NULL; + } + + snip_ = (grn_snip *)snip; + return snip_->normalizer; +} + +grn_rc +grn_snip_add_cond(grn_ctx *ctx, grn_obj *snip, + const char *keyword, unsigned int keyword_len, + const char *opentag, unsigned int opentag_len, + const char *closetag, unsigned int closetag_len) +{ + grn_rc rc; + int copy_tag; + snip_cond *cond; + unsigned int norm_blen; + grn_snip *snip_; + + snip_ = (grn_snip *)snip; + if (!snip_ || !keyword || !keyword_len || snip_->cond_len >= MAX_SNIP_COND_COUNT) { + return GRN_INVALID_ARGUMENT; + } + + cond = snip_->cond + snip_->cond_len; + if ((rc = grn_snip_cond_init(ctx, cond, keyword, keyword_len, + snip_->encoding, snip_->normalizer, snip_->flags))) { + return rc; + } + grn_string_get_normalized(ctx, cond->keyword, NULL, &norm_blen, NULL); + if (norm_blen > snip_->width) { + grn_snip_cond_close(ctx, cond); + return GRN_INVALID_ARGUMENT; + } + + copy_tag = snip_->flags & GRN_SNIP_COPY_TAG; + rc = grn_snip_cond_set_tag(ctx, + &(cond->opentag), &(cond->opentag_len), + opentag, opentag_len, + snip_->defaultopentag, snip_->defaultopentag_len, + copy_tag); + if (rc) { + grn_snip_cond_close(ctx, cond); + return rc; + } + + rc = grn_snip_cond_set_tag(ctx, + &(cond->closetag), &(cond->closetag_len), + closetag, closetag_len, + snip_->defaultclosetag, snip_->defaultclosetag_len, + copy_tag); + if (rc) { + if (opentag && copy_tag) { + GRN_FREE((void *)cond->opentag); + } + grn_snip_cond_close(ctx, cond); + return rc; + } + + snip_->cond_len++; + return GRN_SUCCESS; +} + +static size_t +grn_snip_find_firstbyte(const char *string, grn_encoding encoding, size_t offset, + size_t doffset) +{ + switch (encoding) { + case GRN_ENC_EUC_JP: + while (!(grn_bm_check_euc((unsigned char *) string, offset))) + offset += doffset; + break; + case GRN_ENC_SJIS: + if (!(grn_bm_check_sjis((unsigned char *) string, offset))) + offset += doffset; + break; + case GRN_ENC_UTF8: + while ((signed char)string[offset] <= (signed char)0xc0) + offset += doffset; + break; + default: + break; + } + return offset; +} + +inline static grn_rc +grn_snip_set_default_tag(grn_ctx *ctx, + const char **dest_tag, size_t *dest_tag_len, + const char *tag, unsigned int tag_len, + int copy_tag) +{ + if (copy_tag && tag) { + char *copied_tag; + copied_tag = grn_snip_strndup(ctx, tag, tag_len); + if (!copied_tag) { + return GRN_NO_MEMORY_AVAILABLE; + } + *dest_tag = copied_tag; + } else { + *dest_tag = tag; + } + *dest_tag_len = tag_len; + return GRN_SUCCESS; +} + +grn_obj * +grn_snip_open(grn_ctx *ctx, int flags, unsigned int width, + unsigned int max_results, + const char *defaultopentag, unsigned int defaultopentag_len, + const char *defaultclosetag, unsigned int defaultclosetag_len, + grn_snip_mapping *mapping) +{ + int copy_tag; + grn_snip *ret = NULL; + if (!(ret = GRN_MALLOC(sizeof(grn_snip)))) { + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_snip allocation failed on grn_snip_open"); + return NULL; + } + if (max_results > MAX_SNIP_RESULT_COUNT || max_results == 0) { + GRN_LOG(ctx, GRN_LOG_WARNING, "max_results is invalid on grn_snip_open"); + GRN_FREE(ret); + return NULL; + } + GRN_API_ENTER; + ret->encoding = ctx->encoding; + ret->flags = flags; + ret->width = width; + ret->max_results = max_results; + ret->defaultopentag = NULL; + ret->defaultclosetag = NULL; + + copy_tag = flags & GRN_SNIP_COPY_TAG; + if (grn_snip_set_default_tag(ctx, + &(ret->defaultopentag), + &(ret->defaultopentag_len), + defaultopentag, defaultopentag_len, + copy_tag)) { + GRN_FREE(ret); + GRN_API_RETURN(NULL); + } + + if (grn_snip_set_default_tag(ctx, + &(ret->defaultclosetag), + &(ret->defaultclosetag_len), + defaultclosetag, defaultclosetag_len, + copy_tag)) { + if (copy_tag && ret->defaultopentag) { + GRN_FREE((void *)ret->defaultopentag); + } + GRN_FREE(ret); + GRN_API_RETURN(NULL); + } + + ret->cond_len = 0; + ret->mapping = mapping; + ret->nstr = NULL; + ret->tag_count = 0; + ret->snip_count = 0; + if (ret->flags & GRN_SNIP_NORMALIZE) { + ret->normalizer = GRN_NORMALIZER_AUTO; + } else { + ret->normalizer = NULL; + } + + GRN_DB_OBJ_SET_TYPE(ret, GRN_SNIP); + { + grn_obj *db; + grn_id id; + db = grn_ctx_db(ctx); + id = grn_obj_register(ctx, db, NULL, 0); + DB_OBJ(ret)->header.domain = GRN_ID_NIL; + DB_OBJ(ret)->range = GRN_ID_NIL; + grn_db_obj_init(ctx, db, id, DB_OBJ(ret)); + } + + GRN_API_RETURN((grn_obj *)ret); +} + +static grn_rc +exec_clean(grn_ctx *ctx, grn_snip *snip) +{ + snip_cond *cond, *cond_end; + if (snip->nstr) { + grn_obj_close(ctx, snip->nstr); + snip->nstr = NULL; + } + snip->tag_count = 0; + snip->snip_count = 0; + for (cond = snip->cond, cond_end = cond + snip->cond_len; + cond < cond_end; cond++) { + grn_snip_cond_reinit(cond); + } + return GRN_SUCCESS; +} + +grn_rc +grn_snip_close(grn_ctx *ctx, grn_snip *snip) +{ + snip_cond *cond, *cond_end; + if (!snip) { return GRN_INVALID_ARGUMENT; } + GRN_API_ENTER; + if (snip->flags & GRN_SNIP_COPY_TAG) { + int i; + snip_cond *sc; + const char *dot = snip->defaultopentag, *dct = snip->defaultclosetag; + for (i = snip->cond_len, sc = snip->cond; i; i--, sc++) { + if (sc->opentag != dot) { GRN_FREE((void *)sc->opentag); } + if (sc->closetag != dct) { GRN_FREE((void *)sc->closetag); } + } + if (dot) { GRN_FREE((void *)dot); } + if (dct) { GRN_FREE((void *)dct); } + } + if (snip->nstr) { + grn_obj_close(ctx, snip->nstr); + } + for (cond = snip->cond, cond_end = cond + snip->cond_len; + cond < cond_end; cond++) { + grn_snip_cond_close(ctx, cond); + } + GRN_FREE(snip); + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_rc +grn_snip_exec(grn_ctx *ctx, grn_obj *snip, const char *string, unsigned int string_len, + unsigned int *nresults, unsigned int *max_tagged_len) +{ + size_t i; + grn_snip *snip_; + int f = GRN_STR_WITH_CHECKS|GRN_STR_REMOVEBLANK; + if (!snip || !string || !nresults || !max_tagged_len) { + return GRN_INVALID_ARGUMENT; + } + GRN_API_ENTER; + snip_ = (grn_snip *)snip; + exec_clean(ctx, snip_); + *nresults = 0; + snip_->nstr = grn_string_open(ctx, string, string_len, snip_->normalizer, f); + if (!snip_->nstr) { + exec_clean(ctx, snip_); + GRN_LOG(ctx, GRN_LOG_ALERT, "grn_string_open on grn_snip_exec failed !"); + GRN_API_RETURN(ctx->rc); + } + for (i = 0; i < snip_->cond_len; i++) { + grn_bm_tunedbm(ctx, snip_->cond + i, snip_->nstr, snip_->flags); + } + + { + _snip_tag_result *tag_result = snip_->tag_result; + _snip_result *snip_result = snip_->snip_result; + size_t last_end_offset = 0, last_last_end_offset = 0; + unsigned int unfound_cond_count = snip_->cond_len; + + *max_tagged_len = 0; + while (1) { + size_t tagged_len = 0, last_tag_end = 0; + int_least8_t all_stop = 1, found_cond = 0; + snip_result->tag_count = 0; + + while (1) { + size_t min_start_offset = (size_t) -1; + size_t max_end_offset = 0; + snip_cond *cond = NULL; + + /* get condition which have minimum offset and is not stopped */ + for (i = 0; i < snip_->cond_len; i++) { + if (snip_->cond[i].stopflag == SNIPCOND_NONSTOP && + (min_start_offset > snip_->cond[i].start_offset || + (min_start_offset == snip_->cond[i].start_offset && + max_end_offset < snip_->cond[i].end_offset))) { + min_start_offset = snip_->cond[i].start_offset; + max_end_offset = snip_->cond[i].end_offset; + cond = &snip_->cond[i]; + } + } + if (!cond) { + break; + } + /* check whether condtion is the first condition in snippet */ + if (snip_result->tag_count == 0) { + /* skip condition if the number of rest snippet field is smaller than */ + /* the number of unfound keywords. */ + if (snip_->max_results - *nresults <= unfound_cond_count && cond->count > 0) { + int_least8_t exclude_other_cond = 1; + for (i = 0; i < snip_->cond_len; i++) { + if ((snip_->cond + i) != cond + && snip_->cond[i].end_offset <= cond->start_offset + snip_->width + && snip_->cond[i].count == 0) { + exclude_other_cond = 0; + } + } + if (exclude_other_cond) { + grn_bm_tunedbm(ctx, cond, snip_->nstr, snip_->flags); + continue; + } + } + snip_result->start_offset = cond->start_offset; + snip_result->first_tag_result_idx = snip_->tag_count; + } else { + if (cond->start_offset >= snip_result->start_offset + snip_->width) { + break; + } + /* check nesting to make valid HTML */ + /* ToDo: allow test */ + if (cond->start_offset < last_tag_end) { + grn_bm_tunedbm(ctx, cond, snip_->nstr, snip_->flags); + continue; + } + } + if (cond->end_offset > snip_result->start_offset + snip_->width) { + /* If a keyword gets across a snippet, */ + /* it was skipped and never to be tagged. */ + cond->stopflag = SNIPCOND_ACROSS; + grn_bm_tunedbm(ctx, cond, snip_->nstr, snip_->flags); + } else { + found_cond = 1; + if (cond->count == 0) { + unfound_cond_count--; + } + cond->count++; + last_end_offset = cond->end_offset; + + tag_result->cond = cond; + tag_result->start_offset = cond->start_offset; + tag_result->end_offset = last_tag_end = cond->end_offset; + + snip_result->tag_count++; + tag_result++; + tagged_len += cond->opentag_len + cond->closetag_len; + if (++snip_->tag_count >= MAX_SNIP_TAG_COUNT) { + break; + } + grn_bm_tunedbm(ctx, cond, snip_->nstr, snip_->flags); + } + } + if (!found_cond) { + break; + } + if (snip_result->start_offset + last_end_offset < snip_->width) { + snip_result->start_offset = 0; + } else { + snip_result->start_offset = + MAX(MIN + ((snip_result->start_offset + last_end_offset - snip_->width) / 2, + string_len - snip_->width), last_last_end_offset); + } + snip_result->start_offset = + grn_snip_find_firstbyte(string, snip_->encoding, snip_result->start_offset, 1); + + snip_result->end_offset = snip_result->start_offset + snip_->width; + if (snip_result->end_offset < string_len) { + snip_result->end_offset = + grn_snip_find_firstbyte(string, snip_->encoding, snip_result->end_offset, -1); + } else { + snip_result->end_offset = string_len; + } + last_last_end_offset = snip_result->end_offset; + + if (snip_->mapping == (grn_snip_mapping *) -1) { + tagged_len += + count_mapped_chars(&string[snip_result->start_offset], + &string[snip_result->end_offset]) + 1; + } else { + tagged_len += snip_result->end_offset - snip_result->start_offset + 1; + } + + *max_tagged_len = MAX(*max_tagged_len, tagged_len); + + snip_result->last_tag_result_idx = snip_->tag_count - 1; + (*nresults)++; + snip_result++; + + if (*nresults == snip_->max_results || snip_->tag_count == MAX_SNIP_TAG_COUNT) { + break; + } + for (i = 0; i < snip_->cond_len; i++) { + if (snip_->cond[i].stopflag != SNIPCOND_STOP) { + all_stop = 0; + snip_->cond[i].stopflag = SNIPCOND_NONSTOP; + } + } + if (all_stop) { + break; + } + } + } + snip_->snip_count = *nresults; + snip_->string = string; + + snip_->max_tagged_len = *max_tagged_len; + + GRN_API_RETURN(ctx->rc); +} + +grn_rc +grn_snip_get_result(grn_ctx *ctx, grn_obj *snip, const unsigned int index, char *result, unsigned int *result_len) +{ + char *p; + size_t i, j, k; + _snip_result *sres; + grn_snip *snip_; + + snip_ = (grn_snip *)snip; + if (snip_->snip_count <= index || !snip_->nstr) { + return GRN_INVALID_ARGUMENT; + } + + GRN_ASSERT(snip_->snip_count != 0 && snip_->tag_count != 0); + + GRN_API_ENTER; + sres = &snip_->snip_result[index]; + j = sres->first_tag_result_idx; + for (p = result, i = sres->start_offset; i < sres->end_offset; i++) { + for (; j <= sres->last_tag_result_idx && snip_->tag_result[j].start_offset == i; j++) { + if (snip_->tag_result[j].end_offset > sres->end_offset) { + continue; + } + grn_memcpy(p, + snip_->tag_result[j].cond->opentag, + snip_->tag_result[j].cond->opentag_len); + p += snip_->tag_result[j].cond->opentag_len; + } + + if (snip_->mapping == GRN_SNIP_MAPPING_HTML_ESCAPE) { + switch (snip_->string[i]) { + case '<': + *p++ = '&'; + *p++ = 'l'; + *p++ = 't'; + *p++ = ';'; + break; + case '>': + *p++ = '&'; + *p++ = 'g'; + *p++ = 't'; + *p++ = ';'; + break; + case '&': + *p++ = '&'; + *p++ = 'a'; + *p++ = 'm'; + *p++ = 'p'; + *p++ = ';'; + break; + case '"': + *p++ = '&'; + *p++ = 'q'; + *p++ = 'u'; + *p++ = 'o'; + *p++ = 't'; + *p++ = ';'; + break; + default: + *p++ = snip_->string[i]; + break; + } + } else { + *p++ = snip_->string[i]; + } + + for (k = sres->last_tag_result_idx; + snip_->tag_result[k].end_offset <= sres->end_offset; k--) { + /* TODO: avoid all loop */ + if (snip_->tag_result[k].end_offset == i + 1) { + grn_memcpy(p, + snip_->tag_result[k].cond->closetag, + snip_->tag_result[k].cond->closetag_len); + p += snip_->tag_result[k].cond->closetag_len; + } + if (k <= sres->first_tag_result_idx) { + break; + } + }; + } + *p = '\0'; + + if(result_len) { *result_len = (unsigned int)(p - result); } + GRN_ASSERT((unsigned int)(p - result) <= snip_->max_tagged_len); + + GRN_API_RETURN(ctx->rc); +} diff --git a/storage/mroonga/vendor/groonga/lib/store.c b/storage/mroonga/vendor/groonga/lib/store.c new file mode 100644 index 00000000..f579bc9e --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/store.c @@ -0,0 +1,2864 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include "grn_str.h" +#include "grn_store.h" +#include "grn_ctx_impl.h" +#include "grn_output.h" +#include + +/* rectangular arrays */ + +#define GRN_RA_W_SEGMENT 22 +#define GRN_RA_SEGMENT_SIZE (1 << GRN_RA_W_SEGMENT) + +static grn_ra * +_grn_ra_create(grn_ctx *ctx, grn_ra *ra, const char *path, unsigned int element_size) +{ + grn_io *io; + int max_segments, n_elm, w_elm; + struct grn_ra_header *header; + unsigned int actual_size; + if (element_size > GRN_RA_SEGMENT_SIZE) { + GRN_LOG(ctx, GRN_LOG_ERROR, "element_size too large (%d)", element_size); + return NULL; + } + for (actual_size = 1; actual_size < element_size; actual_size *= 2) ; + max_segments = ((GRN_ID_MAX + 1) / GRN_RA_SEGMENT_SIZE) * actual_size; + io = grn_io_create(ctx, path, sizeof(struct grn_ra_header), + GRN_RA_SEGMENT_SIZE, max_segments, grn_io_auto, + GRN_IO_EXPIRE_SEGMENT); + if (!io) { return NULL; } + header = grn_io_header(io); + grn_io_set_type(io, GRN_COLUMN_FIX_SIZE); + header->element_size = actual_size; + n_elm = GRN_RA_SEGMENT_SIZE / header->element_size; + for (w_elm = GRN_RA_W_SEGMENT; (1 << w_elm) > n_elm; w_elm--); + ra->io = io; + ra->header = header; + ra->element_mask = n_elm - 1; + ra->element_width = w_elm; + return ra; +} + +grn_ra * +grn_ra_create(grn_ctx *ctx, const char *path, unsigned int element_size) +{ + grn_ra *ra = (grn_ra *)GRN_CALLOC(sizeof(grn_ra)); + if (!ra) { + return NULL; + } + GRN_DB_OBJ_SET_TYPE(ra, GRN_COLUMN_FIX_SIZE); + if (!_grn_ra_create(ctx, ra, path, element_size)) { + GRN_FREE(ra); + return NULL; + } + return ra; +} + +grn_ra * +grn_ra_open(grn_ctx *ctx, const char *path) +{ + grn_io *io; + int n_elm, w_elm; + grn_ra *ra = NULL; + struct grn_ra_header *header; + uint32_t io_type; + io = grn_io_open(ctx, path, grn_io_auto); + if (!io) { return NULL; } + header = grn_io_header(io); + io_type = grn_io_get_type(io); + if (io_type != GRN_COLUMN_FIX_SIZE) { + ERR(GRN_INVALID_FORMAT, + "[column][fix-size] file type must be %#04x: <%#04x>", + GRN_COLUMN_FIX_SIZE, io_type); + grn_io_close(ctx, io); + return NULL; + } + ra = GRN_MALLOCN(grn_ra, 1); + if (!ra) { + grn_io_close(ctx, io); + return NULL; + } + n_elm = GRN_RA_SEGMENT_SIZE / header->element_size; + for (w_elm = GRN_RA_W_SEGMENT; (1 << w_elm) > n_elm; w_elm--); + GRN_DB_OBJ_SET_TYPE(ra, GRN_COLUMN_FIX_SIZE); + ra->io = io; + ra->header = header; + ra->element_mask = n_elm - 1; + ra->element_width = w_elm; + return ra; +} + +grn_rc +grn_ra_info(grn_ctx *ctx, grn_ra *ra, unsigned int *element_size) +{ + if (!ra) { return GRN_INVALID_ARGUMENT; } + if (element_size) { *element_size = ra->header->element_size; } + return GRN_SUCCESS; +} + +grn_rc +grn_ra_close(grn_ctx *ctx, grn_ra *ra) +{ + grn_rc rc; + if (!ra) { return GRN_INVALID_ARGUMENT; } + rc = grn_io_close(ctx, ra->io); + GRN_FREE(ra); + return rc; +} + +grn_rc +grn_ra_remove(grn_ctx *ctx, const char *path) +{ + if (!path) { return GRN_INVALID_ARGUMENT; } + return grn_io_remove(ctx, path); +} + +grn_rc +grn_ra_truncate(grn_ctx *ctx, grn_ra *ra) +{ + grn_rc rc; + const char *io_path; + char *path; + unsigned int element_size; + if ((io_path = grn_io_path(ra->io)) && *io_path != '\0') { + if (!(path = GRN_STRDUP(io_path))) { + ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path); + return GRN_NO_MEMORY_AVAILABLE; + } + } else { + path = NULL; + } + element_size = ra->header->element_size; + if ((rc = grn_io_close(ctx, ra->io))) { goto exit; } + ra->io = NULL; + if (path && (rc = grn_io_remove(ctx, path))) { goto exit; } + if (!_grn_ra_create(ctx, ra, path, element_size)) { + rc = GRN_UNKNOWN_ERROR; + } +exit: + if (path) { GRN_FREE(path); } + return rc; +} + +void * +grn_ra_ref(grn_ctx *ctx, grn_ra *ra, grn_id id) +{ + void *p = NULL; + uint16_t seg; + if (id > GRN_ID_MAX) { return NULL; } + seg = id >> ra->element_width; + GRN_IO_SEG_REF(ra->io, seg, p); + if (!p) { return NULL; } + return (void *)(((byte *)p) + ((id & ra->element_mask) * ra->header->element_size)); +} + +grn_rc +grn_ra_unref(grn_ctx *ctx, grn_ra *ra, grn_id id) +{ + uint16_t seg; + if (id > GRN_ID_MAX) { return GRN_INVALID_ARGUMENT; } + seg = id >> ra->element_width; + GRN_IO_SEG_UNREF(ra->io, seg); + return GRN_SUCCESS; +} + +void * +grn_ra_ref_cache(grn_ctx *ctx, grn_ra *ra, grn_id id, grn_ra_cache *cache) +{ + void *p = NULL; + uint16_t seg; + if (id > GRN_ID_MAX) { return NULL; } + seg = id >> ra->element_width; + if (seg == cache->seg) { + p = cache->p; + } else { + if (cache->seg != -1) { GRN_IO_SEG_UNREF(ra->io, cache->seg); } + GRN_IO_SEG_REF(ra->io, seg, p); + cache->seg = seg; + cache->p = p; + } + if (!p) { return NULL; } + return (void *)(((byte *)p) + ((id & ra->element_mask) * ra->header->element_size)); +} + +grn_rc +grn_ra_cache_fin(grn_ctx *ctx, grn_ra *ra, grn_id id) +{ + uint16_t seg; + if (id > GRN_ID_MAX) { return GRN_INVALID_ARGUMENT; } + seg = id >> ra->element_width; + GRN_IO_SEG_UNREF(ra->io, seg); + return GRN_SUCCESS; +} + +/**** jagged arrays ****/ + +#define GRN_JA_W_SEGREGATE_THRESH_V1 7 +#define GRN_JA_W_SEGREGATE_THRESH_V2 16 +#define GRN_JA_W_CAPACITY 38 +#define GRN_JA_W_SEGMENT 22 + +#define JA_ESEG_VOID (0xffffffffU) +#define JA_SEGMENT_SIZE (1U << GRN_JA_W_SEGMENT) +#define JA_W_EINFO 3 +#define JA_W_SEGMENTS_MAX (GRN_JA_W_CAPACITY - GRN_JA_W_SEGMENT) +#define JA_W_EINFO_IN_A_SEGMENT (GRN_JA_W_SEGMENT - JA_W_EINFO) +#define JA_N_EINFO_IN_A_SEGMENT (1U << JA_W_EINFO_IN_A_SEGMENT) +#define JA_M_EINFO_IN_A_SEGMENT (JA_N_EINFO_IN_A_SEGMENT - 1) +#define JA_N_GARBAGES_IN_A_SEGMENT ((1U << (GRN_JA_W_SEGMENT - 3)) - 2) +#define JA_N_ELEMENT_VARIATION_V1 (GRN_JA_W_SEGREGATE_THRESH_V1 - JA_W_EINFO + 1) +#define JA_N_ELEMENT_VARIATION_V2 (GRN_JA_W_SEGREGATE_THRESH_V2 - JA_W_EINFO + 1) +#define JA_N_DSEGMENTS (1U << JA_W_SEGMENTS_MAX) +#define JA_N_ESEGMENTS (1U << (GRN_ID_WIDTH - JA_W_EINFO_IN_A_SEGMENT)) + +typedef struct _grn_ja_einfo grn_ja_einfo; + +struct _grn_ja_einfo { + union { + struct { + uint16_t seg; + uint16_t pos; + uint16_t size; + uint8_t c1; + uint8_t c2; + } n; + struct { + uint32_t size; + uint16_t seg; + uint8_t c1; + uint8_t c2; + } h; + uint8_t c[8]; + } u; +}; + +#define ETINY (0x80) +#define EHUGE (0x40) +#define ETINY_P(e) ((e)->u.c[7] & ETINY) +#define ETINY_ENC(e,_size) ((e)->u.c[7] = (_size) + ETINY) +#define ETINY_DEC(e,_size) ((_size) = (e)->u.c[7] & ~(ETINY|EHUGE)) +#define EHUGE_P(e) ((e)->u.c[7] & EHUGE) +#define EHUGE_ENC(e,_seg,_size) do {\ + (e)->u.h.c1 = 0;\ + (e)->u.h.c2 = EHUGE;\ + (e)->u.h.seg = (_seg);\ + (e)->u.h.size = (_size);\ +} while (0) +#define EHUGE_DEC(e,_seg,_size) do {\ + (_seg) = (e)->u.h.seg;\ + (_size) = (e)->u.h.size;\ +} while (0) +#define EINFO_ENC(e,_seg,_pos,_size) do {\ + (e)->u.n.c1 = (_pos) >> 16;\ + (e)->u.n.c2 = ((_size) >> 16);\ + (e)->u.n.seg = (_seg);\ + (e)->u.n.pos = (_pos);\ + (e)->u.n.size = (_size);\ +} while (0) +#define EINFO_DEC(e,_seg,_pos,_size) do {\ + (_seg) = (e)->u.n.seg;\ + (_pos) = ((e)->u.n.c1 << 16) + (e)->u.n.pos;\ + (_size) = ((e)->u.n.c2 << 16) + (e)->u.n.size;\ +} while (0) + +typedef struct { + uint32_t seg; + uint32_t pos; +} ja_pos; + +typedef struct { + uint32_t head; + uint32_t tail; + uint32_t nrecs; + uint32_t next; + ja_pos recs[JA_N_GARBAGES_IN_A_SEGMENT]; +} grn_ja_ginfo; + +struct grn_ja_header_v1 { + uint32_t flags; + uint32_t curr_seg; + uint32_t curr_pos; + uint32_t max_element_size; + ja_pos free_elements[JA_N_ELEMENT_VARIATION_V1]; + uint32_t garbages[JA_N_ELEMENT_VARIATION_V1]; + uint32_t ngarbages[JA_N_ELEMENT_VARIATION_V1]; + uint32_t dsegs[JA_N_DSEGMENTS]; + uint32_t esegs[JA_N_ESEGMENTS]; +}; + +struct grn_ja_header_v2 { + uint32_t flags; + uint32_t curr_seg; + uint32_t curr_pos; + uint32_t max_element_size; + ja_pos free_elements[JA_N_ELEMENT_VARIATION_V2]; + uint32_t garbages[JA_N_ELEMENT_VARIATION_V2]; + uint32_t ngarbages[JA_N_ELEMENT_VARIATION_V2]; + uint32_t dsegs[JA_N_DSEGMENTS]; + uint32_t esegs[JA_N_ESEGMENTS]; + uint8_t segregate_threshold; + uint8_t n_element_variation; +}; + +struct grn_ja_header { + uint32_t flags; + uint32_t *curr_seg; + uint32_t *curr_pos; + uint32_t max_element_size; + ja_pos *free_elements; + uint32_t *garbages; + uint32_t *ngarbages; + uint32_t *dsegs; + uint32_t *esegs; + uint8_t segregate_threshold; + uint8_t n_element_variation; +}; + +#define SEG_SEQ (0x10000000U) +#define SEG_HUGE (0x20000000U) +#define SEG_EINFO (0x30000000U) +#define SEG_GINFO (0x40000000U) +#define SEG_MASK (0xf0000000U) + +#define SEGMENTS_AT(ja,seg) ((ja)->header->dsegs[seg]) +#define SEGMENTS_SEGRE_ON(ja,seg,width) (SEGMENTS_AT(ja,seg) = width) +#define SEGMENTS_SEQ_ON(ja,seg) (SEGMENTS_AT(ja,seg) = SEG_SEQ) +#define SEGMENTS_HUGE_ON(ja,seg) (SEGMENTS_AT(ja,seg) = SEG_HUGE) +#define SEGMENTS_EINFO_ON(ja,seg,lseg) (SEGMENTS_AT(ja,seg) = SEG_EINFO|(lseg)) +#define SEGMENTS_GINFO_ON(ja,seg,width) (SEGMENTS_AT(ja,seg) = SEG_GINFO|(width)) +#define SEGMENTS_OFF(ja,seg) (SEGMENTS_AT(ja,seg) = 0) + +static grn_ja * +_grn_ja_create(grn_ctx *ctx, grn_ja *ja, const char *path, + unsigned int max_element_size, uint32_t flags) +{ + unsigned int i; + grn_io *io; + struct grn_ja_header *header; + struct grn_ja_header_v2 *header_v2; + io = grn_io_create(ctx, path, sizeof(struct grn_ja_header_v2), + JA_SEGMENT_SIZE, JA_N_DSEGMENTS, grn_io_auto, + GRN_IO_EXPIRE_SEGMENT); + if (!io) { return NULL; } + grn_io_set_type(io, GRN_COLUMN_VAR_SIZE); + + header_v2 = grn_io_header(io); + header_v2->flags = flags; + header_v2->curr_seg = 0; + header_v2->curr_pos = JA_SEGMENT_SIZE; + header_v2->max_element_size = max_element_size; + for (i = 0; i < JA_N_ESEGMENTS; i++) { header_v2->esegs[i] = JA_ESEG_VOID; } + header_v2->segregate_threshold = GRN_JA_W_SEGREGATE_THRESH_V2; + header_v2->n_element_variation = JA_N_ELEMENT_VARIATION_V2; + + header = GRN_MALLOCN(struct grn_ja_header, 1); + if (!header) { + grn_io_close(ctx, io); + return NULL; + } + header->flags = header_v2->flags; + header->curr_seg = &(header_v2->curr_seg); + header->curr_pos = &(header_v2->curr_pos); + header->max_element_size = header_v2->max_element_size; + header->free_elements = header_v2->free_elements; + header->garbages = header_v2->garbages; + header->ngarbages = header_v2->ngarbages; + header->dsegs = header_v2->dsegs; + header->esegs = header_v2->esegs; + header->segregate_threshold = header_v2->segregate_threshold; + header->n_element_variation = header_v2->n_element_variation; + + ja->io = io; + ja->header = header; + SEGMENTS_EINFO_ON(ja, 0, 0); + header->esegs[0] = 0; + return ja; +} + +grn_ja * +grn_ja_create(grn_ctx *ctx, const char *path, unsigned int max_element_size, uint32_t flags) +{ + grn_ja *ja = NULL; + ja = (grn_ja *)GRN_CALLOC(sizeof(grn_ja)); + if (!ja) { + return NULL; + } + GRN_DB_OBJ_SET_TYPE(ja, GRN_COLUMN_VAR_SIZE); + if (!_grn_ja_create(ctx, ja, path, max_element_size, flags)) { + GRN_FREE(ja); + return NULL; + } + return ja; +} + +grn_ja * +grn_ja_open(grn_ctx *ctx, const char *path) +{ + grn_io *io; + grn_ja *ja = NULL; + struct grn_ja_header *header; + struct grn_ja_header_v2 *header_v2; + uint32_t io_type; + io = grn_io_open(ctx, path, grn_io_auto); + if (!io) { return NULL; } + header_v2 = grn_io_header(io); + io_type = grn_io_get_type(io); + if (io_type != GRN_COLUMN_VAR_SIZE) { + ERR(GRN_INVALID_FORMAT, + "[column][var-size] file type must be %#04x: <%#04x>", + GRN_COLUMN_VAR_SIZE, io_type); + grn_io_close(ctx, io); + return NULL; + } + if (header_v2->segregate_threshold == 0) { + header_v2->segregate_threshold = GRN_JA_W_SEGREGATE_THRESH_V1; + } + if (header_v2->n_element_variation == 0) { + header_v2->n_element_variation = JA_N_ELEMENT_VARIATION_V1; + } + ja = GRN_MALLOCN(grn_ja, 1); + if (!ja) { + grn_io_close(ctx, io); + return NULL; + } + GRN_DB_OBJ_SET_TYPE(ja, GRN_COLUMN_VAR_SIZE); + header = GRN_MALLOCN(struct grn_ja_header, 1); + if (!header) { + grn_io_close(ctx, io); + GRN_FREE(ja); + return NULL; + } + + header->flags = header_v2->flags; + header->curr_seg = &(header_v2->curr_seg); + header->curr_pos = &(header_v2->curr_pos); + header->max_element_size = header_v2->max_element_size; + header->segregate_threshold = header_v2->segregate_threshold; + header->n_element_variation = header_v2->n_element_variation; + if (header->segregate_threshold == GRN_JA_W_SEGREGATE_THRESH_V1) { + struct grn_ja_header_v1 *header_v1 = (struct grn_ja_header_v1 *)header_v2; + header->free_elements = header_v1->free_elements; + header->garbages = header_v1->garbages; + header->ngarbages = header_v1->ngarbages; + header->dsegs = header_v1->dsegs; + header->esegs = header_v1->esegs; + } else { + header->free_elements = header_v2->free_elements; + header->garbages = header_v2->garbages; + header->ngarbages = header_v2->ngarbages; + header->dsegs = header_v2->dsegs; + header->esegs = header_v2->esegs; + } + + ja->io = io; + ja->header = header; + + return ja; +} + +grn_rc +grn_ja_info(grn_ctx *ctx, grn_ja *ja, unsigned int *max_element_size) +{ + if (!ja) { return GRN_INVALID_ARGUMENT; } + if (max_element_size) { *max_element_size = ja->header->max_element_size; } + return GRN_SUCCESS; +} + +grn_column_flags +grn_ja_get_flags(grn_ctx *ctx, grn_ja *ja) +{ + if (!ja) { + return 0; + } + + return ja->header->flags; +} + +grn_rc +grn_ja_close(grn_ctx *ctx, grn_ja *ja) +{ + grn_rc rc; + if (!ja) { return GRN_INVALID_ARGUMENT; } + rc = grn_io_close(ctx, ja->io); + GRN_FREE(ja->header); + GRN_FREE(ja); + return rc; +} + +grn_rc +grn_ja_remove(grn_ctx *ctx, const char *path) +{ + if (!path) { return GRN_INVALID_ARGUMENT; } + return grn_io_remove(ctx, path); +} + +grn_rc +grn_ja_truncate(grn_ctx *ctx, grn_ja *ja) +{ + grn_rc rc; + const char *io_path; + char *path; + unsigned int max_element_size; + uint32_t flags; + if ((io_path = grn_io_path(ja->io)) && *io_path != '\0') { + if (!(path = GRN_STRDUP(io_path))) { + ERR(GRN_NO_MEMORY_AVAILABLE, "cannot duplicate path: <%s>", io_path); + return GRN_NO_MEMORY_AVAILABLE; + } + } else { + path = NULL; + } + max_element_size = ja->header->max_element_size; + flags = ja->header->flags; + if ((rc = grn_io_close(ctx, ja->io))) { goto exit; } + ja->io = NULL; + if (path && (rc = grn_io_remove(ctx, path))) { goto exit; } + GRN_FREE(ja->header); + if (!_grn_ja_create(ctx, ja, path, max_element_size, flags)) { + rc = GRN_UNKNOWN_ERROR; + } +exit: + if (path) { GRN_FREE(path); } + return rc; +} + +static void * +grn_ja_ref_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len) +{ + uint32_t pseg = ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT]; + iw->size = 0; + iw->addr = NULL; + iw->pseg = pseg; + iw->uncompressed_value = NULL; + if (pseg != JA_ESEG_VOID) { + grn_ja_einfo *einfo = NULL; + GRN_IO_SEG_REF(ja->io, pseg, einfo); + if (einfo) { + grn_ja_einfo *ei = &einfo[id & JA_M_EINFO_IN_A_SEGMENT]; + if (ETINY_P(ei)) { + iw->tiny_p = 1; + ETINY_DEC(ei, iw->size); + iw->io = ja->io; + iw->ctx = ctx; + iw->addr = (void *)ei; + } else { + uint32_t jag, vpos, vsize; + iw->tiny_p = 0; + if (EHUGE_P(ei)) { + EHUGE_DEC(ei, jag, vsize); + vpos = 0; + } else { + EINFO_DEC(ei, jag, vpos, vsize); + } + grn_io_win_map(ja->io, ctx, iw, jag, vpos, vsize, grn_io_rdonly); + } + if (!iw->addr) { GRN_IO_SEG_UNREF(ja->io, pseg); } + } + } + *value_len = iw->size; + return iw->addr; +} + +grn_rc +grn_ja_unref(grn_ctx *ctx, grn_io_win *iw) +{ + if (iw->uncompressed_value) { + GRN_FREE(iw->uncompressed_value); + iw->uncompressed_value = NULL; + } + if (!iw->addr) { return GRN_INVALID_ARGUMENT; } + GRN_IO_SEG_UNREF(iw->io, iw->pseg); + if (!iw->tiny_p) { grn_io_win_unmap(iw); } + return GRN_SUCCESS; +} + +#define DELETED 0x80000000 + +static grn_rc +grn_ja_free(grn_ctx *ctx, grn_ja *ja, grn_ja_einfo *einfo) +{ + grn_ja_ginfo *ginfo = NULL; + uint32_t seg, pos, element_size, aligned_size, m, *gseg; + if (ETINY_P(einfo)) { return GRN_SUCCESS; } + if (EHUGE_P(einfo)) { + uint32_t n; + EHUGE_DEC(einfo, seg, element_size); + n = ((element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT); + for (; n--; seg++) { SEGMENTS_OFF(ja, seg); } + return GRN_SUCCESS; + } + EINFO_DEC(einfo, seg, pos, element_size); + if (!element_size) { return GRN_SUCCESS; } + { + int es = element_size - 1; + GRN_BIT_SCAN_REV(es, m); + m++; + } + if (m > ja->header->segregate_threshold) { + byte *addr = NULL; + GRN_IO_SEG_REF(ja->io, seg, addr); + if (!addr) { return GRN_NO_MEMORY_AVAILABLE; } + aligned_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1); + *(uint32_t *)(addr + pos - sizeof(grn_id)) = DELETED|aligned_size; + if (SEGMENTS_AT(ja, seg) < (aligned_size + sizeof(grn_id)) + SEG_SEQ) { + GRN_LOG(ctx, GRN_WARN, "inconsistent ja entry detected (%d > %d)", + element_size, SEGMENTS_AT(ja, seg) - SEG_SEQ); + } + SEGMENTS_AT(ja, seg) -= (aligned_size + sizeof(grn_id)); + if (SEGMENTS_AT(ja, seg) == SEG_SEQ) { + /* reuse the segment */ + SEGMENTS_OFF(ja, seg); + if (seg == *(ja->header->curr_seg)) { + *(ja->header->curr_pos) = JA_SEGMENT_SIZE; + } + } + GRN_IO_SEG_UNREF(ja->io, seg); + } else { + uint32_t lseg = 0, lseg_; + gseg = &ja->header->garbages[m - JA_W_EINFO]; + while ((lseg_ = *gseg)) { + if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); } + GRN_IO_SEG_REF(ja->io, lseg_, ginfo); + if (!ginfo) { + return GRN_NO_MEMORY_AVAILABLE; + } + lseg = lseg_; + if (ginfo->nrecs < JA_N_GARBAGES_IN_A_SEGMENT) { break; } + gseg = &ginfo->next; + } + if (!lseg_) { + uint32_t i = 0; + while (SEGMENTS_AT(ja, i)) { + if (++i >= JA_N_DSEGMENTS) { + if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); } + return GRN_NO_MEMORY_AVAILABLE; + } + } + SEGMENTS_GINFO_ON(ja, i, m - JA_W_EINFO); + *gseg = i; + lseg_ = *gseg; + if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); } + GRN_IO_SEG_REF(ja->io, lseg_, ginfo); + lseg = lseg_; + if (!ginfo) { + return GRN_NO_MEMORY_AVAILABLE; + } + ginfo->head = 0; + ginfo->tail = 0; + ginfo->nrecs = 0; + ginfo->next = 0; + } + ginfo->recs[ginfo->head].seg = seg; + ginfo->recs[ginfo->head].pos = pos; + if (++ginfo->head == JA_N_GARBAGES_IN_A_SEGMENT) { ginfo->head = 0; } + ginfo->nrecs++; + ja->header->ngarbages[m - JA_W_EINFO]++; + if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); } + } + return GRN_SUCCESS; +} + +grn_rc +grn_ja_replace(grn_ctx *ctx, grn_ja *ja, grn_id id, + grn_ja_einfo *ei, uint64_t *cas) +{ + grn_rc rc = GRN_SUCCESS; + uint32_t lseg, *pseg, pos; + grn_ja_einfo *einfo = NULL, eback; + lseg = id >> JA_W_EINFO_IN_A_SEGMENT; + pos = id & JA_M_EINFO_IN_A_SEGMENT; + pseg = &ja->header->esegs[lseg]; + if (grn_io_lock(ctx, ja->io, grn_lock_timeout)) { + return ctx->rc; + } + if (*pseg == JA_ESEG_VOID) { + unsigned int i = 0; + while (SEGMENTS_AT(ja, i)) { + if (++i >= JA_N_DSEGMENTS) { + ERR(GRN_NOT_ENOUGH_SPACE, "grn_ja file (%s) is full", ja->io->path); + rc = GRN_NOT_ENOUGH_SPACE; + goto exit; + } + } + SEGMENTS_EINFO_ON(ja, i, lseg); + GRN_IO_SEG_REF(ja->io, i, einfo); + if (einfo) { + *pseg = i; + memset(einfo, 0, JA_SEGMENT_SIZE); + } + } else { + GRN_IO_SEG_REF(ja->io, *pseg, einfo); + } + if (!einfo) { + rc = GRN_NO_MEMORY_AVAILABLE; + goto exit; + } + eback = einfo[pos]; + if (cas && *cas != *((uint64_t *)&eback)) { + ERR(GRN_CAS_ERROR, "cas failed (%d)", id); + GRN_IO_SEG_UNREF(ja->io, *pseg); + rc = GRN_CAS_ERROR; + goto exit; + } + // smb_wmb(); + { + uint64_t *location = (uint64_t *)(einfo + pos); + uint64_t value = *((uint64_t *)ei); + GRN_SET_64BIT(location, value); + } + GRN_IO_SEG_UNREF(ja->io, *pseg); + grn_ja_free(ctx, ja, &eback); +exit : + grn_io_unlock(ja->io); + return rc; +} + +#define JA_N_GARBAGES_TH 10 + +// todo : grn_io_win_map cause verbose copy when nseg > 1, it should be copied directly. +static grn_rc +grn_ja_alloc(grn_ctx *ctx, grn_ja *ja, grn_id id, + uint32_t element_size, grn_ja_einfo *einfo, grn_io_win *iw) +{ + byte *addr = NULL; + iw->io = ja->io; + iw->ctx = ctx; + iw->cached = 1; + if (element_size < 8) { + ETINY_ENC(einfo, element_size); + iw->tiny_p = 1; + iw->addr = (void *)einfo; + return GRN_SUCCESS; + } + iw->tiny_p = 0; + if (grn_io_lock(ctx, ja->io, grn_lock_timeout)) { return ctx->rc; } + if (element_size + sizeof(grn_id) > JA_SEGMENT_SIZE) { + uint i; + int j, n = (element_size + JA_SEGMENT_SIZE - 1) >> GRN_JA_W_SEGMENT; + for (i = 0, j = -1; i < JA_N_DSEGMENTS; i++) { + if (SEGMENTS_AT(ja, i)) { + j = i; + } else { + if (i == j + n) { + j++; + addr = grn_io_win_map(ja->io, ctx, iw, j, 0, element_size, grn_io_wronly); + if (!addr) { + grn_io_unlock(ja->io); + return GRN_NO_MEMORY_AVAILABLE; + } + EHUGE_ENC(einfo, j, element_size); + for (; j <= i; j++) { SEGMENTS_HUGE_ON(ja, j); } + grn_io_unlock(ja->io); + return GRN_SUCCESS; + } + } + } + GRN_LOG(ctx, GRN_LOG_CRIT, "ja full. requested element_size=%d.", element_size); + grn_io_unlock(ja->io); + return GRN_NO_MEMORY_AVAILABLE; + } else { + ja_pos *vp; + int m, aligned_size, es = element_size - 1; + GRN_BIT_SCAN_REV(es, m); + m++; + if (m > ja->header->segregate_threshold) { + uint32_t seg = *(ja->header->curr_seg); + uint32_t pos = *(ja->header->curr_pos); + if (pos + element_size + sizeof(grn_id) > JA_SEGMENT_SIZE) { + seg = 0; + while (SEGMENTS_AT(ja, seg)) { + if (++seg >= JA_N_DSEGMENTS) { + grn_io_unlock(ja->io); + GRN_LOG(ctx, GRN_LOG_CRIT, "ja full. seg=%d.", seg); + return GRN_NOT_ENOUGH_SPACE; + } + } + SEGMENTS_SEQ_ON(ja, seg); + *(ja->header->curr_seg) = seg; + pos = 0; + } + GRN_IO_SEG_REF(ja->io, seg, addr); + if (!addr) { + grn_io_unlock(ja->io); + return GRN_NO_MEMORY_AVAILABLE; + } + *(grn_id *)(addr + pos) = id; + aligned_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1); + if (pos + aligned_size < JA_SEGMENT_SIZE) { + *(grn_id *)(addr + pos + aligned_size) = GRN_ID_NIL; + } + SEGMENTS_AT(ja, seg) += aligned_size + sizeof(grn_id); + pos += sizeof(grn_id); + EINFO_ENC(einfo, seg, pos, element_size); + iw->segment = seg; + iw->addr = addr + pos; + *(ja->header->curr_pos) = pos + aligned_size; + grn_io_unlock(ja->io); + return GRN_SUCCESS; + } else { + uint32_t lseg = 0, lseg_; + aligned_size = 1 << m; + if (ja->header->ngarbages[m - JA_W_EINFO] > JA_N_GARBAGES_TH) { + grn_ja_ginfo *ginfo = NULL; + uint32_t seg, pos, *gseg; + gseg = &ja->header->garbages[m - JA_W_EINFO]; + while ((lseg_ = *gseg)) { + GRN_IO_SEG_REF(ja->io, lseg_, ginfo); + if (!ginfo) { + if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); } + grn_io_unlock(ja->io); + return GRN_NO_MEMORY_AVAILABLE; + } + if (ginfo->next || ginfo->nrecs > JA_N_GARBAGES_TH) { + seg = ginfo->recs[ginfo->tail].seg; + pos = ginfo->recs[ginfo->tail].pos; + GRN_IO_SEG_REF(ja->io, seg, addr); + if (!addr) { + if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); } + GRN_IO_SEG_UNREF(ja->io, lseg_); + grn_io_unlock(ja->io); + return GRN_NO_MEMORY_AVAILABLE; + } + EINFO_ENC(einfo, seg, pos, element_size); + iw->segment = seg; + iw->addr = addr + pos; + if (++ginfo->tail == JA_N_GARBAGES_IN_A_SEGMENT) { ginfo->tail = 0; } + ginfo->nrecs--; + ja->header->ngarbages[m - JA_W_EINFO]--; + if (!ginfo->nrecs) { + SEGMENTS_OFF(ja, *gseg); + *gseg = ginfo->next; + } + if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); } + GRN_IO_SEG_UNREF(ja->io, lseg_); + grn_io_unlock(ja->io); + return GRN_SUCCESS; + } + if (lseg) { GRN_IO_SEG_UNREF(ja->io, lseg); } + if (!ginfo->next) { + GRN_IO_SEG_UNREF(ja->io, lseg_); + break; + } + lseg = lseg_; + gseg = &ginfo->next; + } + } + vp = &ja->header->free_elements[m - JA_W_EINFO]; + if (!vp->seg) { + int i = 0; + while (SEGMENTS_AT(ja, i)) { + if (++i >= JA_N_DSEGMENTS) { + grn_io_unlock(ja->io); + return GRN_NO_MEMORY_AVAILABLE; + } + } + SEGMENTS_SEGRE_ON(ja, i, m); + vp->seg = i; + vp->pos = 0; + } + } + EINFO_ENC(einfo, vp->seg, vp->pos, element_size); + GRN_IO_SEG_REF(ja->io, vp->seg, addr); + if (!addr) { + grn_io_unlock(ja->io); + return GRN_NO_MEMORY_AVAILABLE; + } + iw->segment = vp->seg; + iw->addr = addr + vp->pos; + if ((vp->pos += aligned_size) == JA_SEGMENT_SIZE) { + vp->seg = 0; + vp->pos = 0; + } + iw->uncompressed_value = NULL; + grn_io_unlock(ja->io); + return GRN_SUCCESS; + } +} + +static grn_rc +set_value(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len, + grn_ja_einfo *einfo) +{ + grn_rc rc = GRN_SUCCESS; + grn_io_win iw; + if ((ja->header->flags & GRN_OBJ_RING_BUFFER) && + value_len >= ja->header->max_element_size) { + if ((rc = grn_ja_alloc(ctx, ja, id, value_len + sizeof(uint32_t), einfo, &iw))) { + return rc; + } + grn_memcpy(iw.addr, value, value_len); + memset((byte *)iw.addr + value_len, 0, sizeof(uint32_t)); + grn_io_win_unmap(&iw); + } else { + if ((rc = grn_ja_alloc(ctx, ja, id, value_len, einfo, &iw))) { return rc; } + grn_memcpy(iw.addr, value, value_len); + grn_io_win_unmap(&iw); + } + return rc; +} + +static grn_rc +grn_ja_put_raw(grn_ctx *ctx, grn_ja *ja, grn_id id, + void *value, uint32_t value_len, int flags, uint64_t *cas) +{ + int rc; + int64_t buf; + grn_io_win iw; + grn_ja_einfo einfo; + + if ((flags & GRN_OBJ_SET_MASK) == GRN_OBJ_SET && + value_len > 0) { + grn_io_win jw; + uint32_t old_len; + void *old_value; + grn_bool same_value = GRN_FALSE; + + old_value = grn_ja_ref(ctx, ja, id, &jw, &old_len); + if (value_len == old_len && memcmp(value, old_value, value_len) == 0) { + same_value = GRN_TRUE; + } + grn_ja_unref(ctx, &jw); + if (same_value) { + return GRN_SUCCESS; + } + } + + switch (flags & GRN_OBJ_SET_MASK) { + case GRN_OBJ_APPEND : + if (value_len) { + grn_io_win jw; + uint32_t old_len; + void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len); + if (oldvalue) { + if ((ja->header->flags & GRN_OBJ_RING_BUFFER) && + old_len + value_len >= ja->header->max_element_size) { + if (old_len >= ja->header->max_element_size) { + byte *b = oldvalue; + uint32_t el = old_len - sizeof(uint32_t); + uint32_t pos = *((uint32_t *)(b + el)); + GRN_ASSERT(pos < el); + if (el <= pos + value_len) { + uint32_t rest = el - pos; + grn_memcpy(b + pos, value, rest); + grn_memcpy(b, (byte *)value + rest, value_len - rest); + *((uint32_t *)(b + el)) = value_len - rest; + } else { + grn_memcpy(b + pos, value, value_len); + *((uint32_t *)(b + el)) = pos + value_len; + } + return GRN_SUCCESS; + } else { + if ((rc = grn_ja_alloc(ctx, ja, id, + value_len + old_len + sizeof(uint32_t), + &einfo, &iw))) { + grn_ja_unref(ctx, &jw); + return rc; + } + grn_memcpy(iw.addr, oldvalue, old_len); + grn_memcpy((byte *)iw.addr + old_len, value, value_len); + memset((byte *)iw.addr + old_len + value_len, 0, sizeof(uint32_t)); + grn_io_win_unmap(&iw); + } + } else { + if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) { + grn_ja_unref(ctx, &jw); + return rc; + } + grn_memcpy(iw.addr, oldvalue, old_len); + grn_memcpy((byte *)iw.addr + old_len, value, value_len); + grn_io_win_unmap(&iw); + } + grn_ja_unref(ctx, &jw); + } else { + set_value(ctx, ja, id, value, value_len, &einfo); + } + } + break; + case GRN_OBJ_PREPEND : + if (value_len) { + grn_io_win jw; + uint32_t old_len; + void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len); + if (oldvalue) { + if ((ja->header->flags & GRN_OBJ_RING_BUFFER) && + old_len + value_len >= ja->header->max_element_size) { + if (old_len >= ja->header->max_element_size) { + byte *b = oldvalue; + uint32_t el = old_len - sizeof(uint32_t); + uint32_t pos = *((uint32_t *)(b + el)); + GRN_ASSERT(pos < el); + if (pos < value_len) { + uint32_t rest = value_len - pos; + grn_memcpy(b, (byte *)value + rest, pos); + grn_memcpy(b + el - rest, value, rest); + *((uint32_t *)(b + el)) = el - rest; + } else { + grn_memcpy(b + pos - value_len, value, value_len); + *((uint32_t *)(b + el)) = pos - value_len; + } + return GRN_SUCCESS; + } else { + if ((rc = grn_ja_alloc(ctx, ja, id, + value_len + old_len + sizeof(uint32_t), + &einfo, &iw))) { + grn_ja_unref(ctx, &jw); + return rc; + } + grn_memcpy(iw.addr, value, value_len); + grn_memcpy((byte *)iw.addr + value_len, oldvalue, old_len); + memset((byte *)iw.addr + value_len + old_len, 0, sizeof(uint32_t)); + grn_io_win_unmap(&iw); + } + } else { + if ((rc = grn_ja_alloc(ctx, ja, id, value_len + old_len, &einfo, &iw))) { + grn_ja_unref(ctx, &jw); + return rc; + } + grn_memcpy(iw.addr, value, value_len); + grn_memcpy((byte *)iw.addr + value_len, oldvalue, old_len); + grn_io_win_unmap(&iw); + } + grn_ja_unref(ctx, &jw); + } else { + set_value(ctx, ja, id, value, value_len, &einfo); + } + } + break; + case GRN_OBJ_DECR : + if (value_len == sizeof(int64_t)) { + int64_t *v = (int64_t *)&buf; + *v = -(*(int64_t *)value); + value = v; + } else if (value_len == sizeof(int32_t)) { + int32_t *v = (int32_t *)&buf; + *v = -(*(int32_t *)value); + value = v; + } else { + return GRN_INVALID_ARGUMENT; + } + /* fallthru */ + case GRN_OBJ_INCR : + { + grn_io_win jw; + uint32_t old_len; + void *oldvalue = grn_ja_ref(ctx, ja, id, &jw, &old_len); + if (oldvalue && old_len) { + grn_rc rc = GRN_INVALID_ARGUMENT; + if (old_len == sizeof(int64_t) && value_len == sizeof(int64_t)) { + (*(int64_t *)oldvalue) += (*(int64_t *)value); + rc = GRN_SUCCESS; + } else if (old_len == sizeof(int32_t) && value_len == sizeof(int32_t)) { + (*(int32_t *)oldvalue) += (*(int32_t *)value); + rc = GRN_SUCCESS; + } + grn_ja_unref(ctx, &jw); + return rc; + } + } + /* fallthru */ + case GRN_OBJ_SET : + if (value_len) { + set_value(ctx, ja, id, value, value_len, &einfo); + } else { + memset(&einfo, 0, sizeof(grn_ja_einfo)); + } + break; + default : + ERR(GRN_INVALID_ARGUMENT, "grn_ja_put_raw called with illegal flags value"); + return GRN_INVALID_ARGUMENT; + } + if ((rc = grn_ja_replace(ctx, ja, id, &einfo, cas))) { + if (!grn_io_lock(ctx, ja->io, grn_lock_timeout)) { + grn_ja_free(ctx, ja, &einfo); + grn_io_unlock(ja->io); + } + } + return rc; +} + +grn_rc +grn_ja_putv(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *vector, int flags) +{ + grn_obj header, footer; + grn_rc rc = GRN_SUCCESS; + grn_section *vp; + int i, f = 0, n = grn_vector_size(ctx, vector); + GRN_TEXT_INIT(&header, 0); + GRN_TEXT_INIT(&footer, 0); + grn_text_benc(ctx, &header, n); + for (i = 0, vp = vector->u.v.sections; i < n; i++, vp++) { + grn_text_benc(ctx, &header, vp->length); + if (vp->weight || vp->domain) { f = 1; } + } + if (f) { + for (i = 0, vp = vector->u.v.sections; i < n; i++, vp++) { + grn_text_benc(ctx, &footer, vp->weight); + grn_text_benc(ctx, &footer, vp->domain); + } + } + { + grn_io_win iw; + grn_ja_einfo einfo; + grn_obj *body = vector->u.v.body; + size_t sizeh = GRN_BULK_VSIZE(&header); + size_t sizev = body ? GRN_BULK_VSIZE(body) : 0; + size_t sizef = GRN_BULK_VSIZE(&footer); + if ((rc = grn_ja_alloc(ctx, ja, id, sizeh + sizev + sizef, &einfo, &iw))) { goto exit; } + grn_memcpy(iw.addr, GRN_BULK_HEAD(&header), sizeh); + if (body) { + grn_memcpy((char *)iw.addr + sizeh, GRN_BULK_HEAD(body), sizev); + } + if (f) { + grn_memcpy((char *)iw.addr + sizeh + sizev, GRN_BULK_HEAD(&footer), sizef); + } + grn_io_win_unmap(&iw); + rc = grn_ja_replace(ctx, ja, id, &einfo, NULL); + } +exit : + GRN_OBJ_FIN(ctx, &footer); + GRN_OBJ_FIN(ctx, &header); + return rc; +} + +uint32_t +grn_ja_size(grn_ctx *ctx, grn_ja *ja, grn_id id) +{ + grn_ja_einfo *einfo = NULL, *ei; + uint32_t lseg, *pseg, pos, size; + lseg = id >> JA_W_EINFO_IN_A_SEGMENT; + pos = id & JA_M_EINFO_IN_A_SEGMENT; + pseg = &ja->header->esegs[lseg]; + if (*pseg == JA_ESEG_VOID) { + ctx->rc = GRN_INVALID_ARGUMENT; + return 0; + } + GRN_IO_SEG_REF(ja->io, *pseg, einfo); + if (!einfo) { + ctx->rc = GRN_NO_MEMORY_AVAILABLE; + return 0; + } + ei = &einfo[pos]; + if (ETINY_P(ei)) { + ETINY_DEC(ei, size); + } else { + if (EHUGE_P(ei)) { + size = ei->u.h.size; + } else { + size = (ei->u.n.c2 << 16) + ei->u.n.size; + } + } + GRN_IO_SEG_UNREF(ja->io, *pseg); + return size; +} + +grn_rc +grn_ja_element_info(grn_ctx *ctx, grn_ja *ja, grn_id id, + uint64_t *cas, uint32_t *pos, uint32_t *size) +{ + uint32_t pseg = ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT]; + if (pseg == JA_ESEG_VOID) { + return GRN_INVALID_ARGUMENT; + } else { + grn_ja_einfo *einfo = NULL; + GRN_IO_SEG_REF(ja->io, pseg, einfo); + if (einfo) { + grn_ja_einfo *ei; + *cas = *((uint64_t *)&einfo[id & JA_M_EINFO_IN_A_SEGMENT]); + ei = (grn_ja_einfo *)cas; + if (ETINY_P(ei)) { + ETINY_DEC(ei, *size); + *pos = 0; + } else { + uint32_t jag; + if (EHUGE_P(ei)) { + EHUGE_DEC(ei, jag, *size); + *pos = 0; + } else { + EINFO_DEC(ei, jag, *pos, *size); + } + } + GRN_IO_SEG_UNREF(ja->io, pseg); + } else { + return GRN_INVALID_ARGUMENT; + } + } + return GRN_SUCCESS; +} + +#define COMPRESSED_VALUE_META_FLAG(meta) ((meta) & 0xf000000000000000) +#define COMPRESSED_VALUE_META_FLAG_RAW 0x1000000000000000 +#define COMPRESSED_VALUE_META_UNCOMPRESSED_LEN(meta) \ + ((meta) & 0x0fffffffffffffff) + +#define COMPRESS_THRESHOLD_BYTE 256 +#define COMPRESS_PACKED_VALUE_SIZE_MAX 257 + /* COMPRESS_THRESHOLD_BYTE - 1 + sizeof(uint64_t) = 257 */ + +#if defined(GRN_WITH_ZLIB) || defined(GRN_WITH_LZ4) || defined(GRN_WITH_ZSTD) +# define GRN_WITH_COMPRESSED +#endif + +#ifdef GRN_WITH_COMPRESSED +static void * +grn_ja_ref_packed(grn_ctx *ctx, + grn_io_win *iw, + uint32_t *value_len, + void *raw_value, + uint32_t raw_value_len, + void **compressed_value, + uint32_t *compressed_value_len, + uint32_t *uncompressed_value_len) +{ + uint64_t compressed_value_meta; + + compressed_value_meta = *((uint64_t *)raw_value); + *compressed_value = (void *)(((uint64_t *)raw_value) + 1); + *compressed_value_len = raw_value_len - sizeof(uint64_t); + + *uncompressed_value_len = + COMPRESSED_VALUE_META_UNCOMPRESSED_LEN(compressed_value_meta); + switch (COMPRESSED_VALUE_META_FLAG(compressed_value_meta)) { + case COMPRESSED_VALUE_META_FLAG_RAW : + iw->uncompressed_value = NULL; + *value_len = *uncompressed_value_len; + return *compressed_value; + default : + return NULL; + } +} + +static grn_rc +grn_ja_put_packed(grn_ctx *ctx, + grn_ja *ja, + grn_id id, + void *value, + uint32_t value_len, + int flags, + uint64_t *cas) +{ + char *packed_value[COMPRESS_PACKED_VALUE_SIZE_MAX]; + uint32_t packed_value_len; + uint64_t packed_value_meta; + + packed_value_len = value_len + sizeof(uint64_t); + packed_value_meta = value_len | COMPRESSED_VALUE_META_FLAG_RAW; + *((uint64_t *)packed_value) = packed_value_meta; + memcpy(((uint64_t *)packed_value) + 1, + value, + value_len); + return grn_ja_put_raw(ctx, + ja, + id, + packed_value, + packed_value_len, + flags, + cas); +} + +static void +grn_ja_compress_error(grn_ctx *ctx, + grn_ja *ja, + grn_id id, + grn_rc rc, + const char *message, + const char *detail) +{ + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_len; + + if (ja->obj.id == GRN_ID_NIL) { + name[0] = '\0'; + name_len = 0; + } else { + name_len = grn_obj_name(ctx, (grn_obj *)ja, name, GRN_TABLE_MAX_KEY_SIZE); + } + ERR(GRN_ZSTD_ERROR, + "[ja]%s: %s%.*s%s<%u>%s%s%s", + message, + name_len == 0 ? "" : "<", + name_len, + name, + name_len == 0 ? "" : ">: ", + id, + detail ? " :<" : "", + detail ? detail : "", + detail ? ">" : ""); +} +#endif /* GRN_WITH_COMPRESSED */ + +#ifdef GRN_WITH_ZLIB +#include + +static const char * +grn_zrc_to_string(int zrc) +{ + switch (zrc) { + case Z_OK : + return "OK"; + case Z_STREAM_END : + return "Stream is end"; + case Z_NEED_DICT : + return "Need dictionary"; + case Z_ERRNO : + return "See errno"; + case Z_STREAM_ERROR : + return "Stream error"; + case Z_DATA_ERROR : + return "Data error"; + case Z_MEM_ERROR : + return "Memory error"; + case Z_BUF_ERROR : + return "Buffer error"; + case Z_VERSION_ERROR : + return "Version error"; + default : + return "Unknown"; + } +} + +static void * +grn_ja_ref_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len) +{ + z_stream zstream; + void *raw_value; + uint32_t raw_value_len; + void *zvalue; + uint32_t zvalue_len; + void *unpacked_value; + uint32_t uncompressed_value_len; + int zrc; + + if (!(raw_value = grn_ja_ref_raw(ctx, ja, id, iw, &raw_value_len))) { + iw->uncompressed_value = NULL; + *value_len = 0; + return NULL; + } + + unpacked_value = grn_ja_ref_packed(ctx, + iw, value_len, + raw_value, raw_value_len, + &zvalue, &zvalue_len, + &uncompressed_value_len); + if (unpacked_value) { + return unpacked_value; + } + + zstream.next_in = (Bytef *)zvalue; + zstream.avail_in = zvalue_len; + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zrc = inflateInit2(&zstream, 15 /* windowBits */); + if (zrc != Z_OK) { + iw->uncompressed_value = NULL; + *value_len = 0; + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZLIB_ERROR, + "[zlib] failed to decompress: initialize", + grn_zrc_to_string(zrc)); + return NULL; + } + if (!(iw->uncompressed_value = GRN_MALLOC(uncompressed_value_len))) { + inflateEnd(&zstream); + iw->uncompressed_value = NULL; + *value_len = 0; + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZLIB_ERROR, + "[zlib] failed to decompress: allocate buffer", + NULL); + return NULL; + } + zstream.next_out = (Bytef *)iw->uncompressed_value; + zstream.avail_out = uncompressed_value_len; + zrc = inflate(&zstream, Z_FINISH); + if (zrc != Z_STREAM_END) { + inflateEnd(&zstream); + GRN_FREE(iw->uncompressed_value); + iw->uncompressed_value = NULL; + *value_len = 0; + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZLIB_ERROR, + "[zlib] failed to decompress: finish", + grn_zrc_to_string(zrc)); + return NULL; + } + *value_len = zstream.total_out; + zrc = inflateEnd(&zstream); + if (zrc != Z_OK) { + GRN_FREE(iw->uncompressed_value); + iw->uncompressed_value = NULL; + *value_len = 0; + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZLIB_ERROR, + "[zlib] failed to decompress: end", + grn_zrc_to_string(zrc)); + return NULL; + } + return iw->uncompressed_value; +} +#endif /* GRN_WITH_ZLIB */ + +#ifdef GRN_WITH_LZ4 +#include + +# if (LZ4_VERSION_MAJOR == 1 && LZ4_VERSION_MINOR < 6) +# define LZ4_compress_default(source, dest, source_size, max_dest_size) \ + LZ4_compress((source), (dest), (source_size)) +# endif + +static void * +grn_ja_ref_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len) +{ + void *raw_value; + uint32_t raw_value_len; + void *lz4_value; + uint32_t lz4_value_len; + void *unpacked_value; + uint32_t uncompressed_value_len; + + if (!(raw_value = grn_ja_ref_raw(ctx, ja, id, iw, &raw_value_len))) { + iw->uncompressed_value = NULL; + *value_len = 0; + return NULL; + } + + unpacked_value = grn_ja_ref_packed(ctx, + iw, value_len, + raw_value, raw_value_len, + &lz4_value, &lz4_value_len, + &uncompressed_value_len); + if (unpacked_value) { + return unpacked_value; + } + + if (!(iw->uncompressed_value = GRN_MALLOC(uncompressed_value_len))) { + iw->uncompressed_value = NULL; + *value_len = 0; + return NULL; + } + if (LZ4_decompress_safe((const char *)(lz4_value), + (char *)(iw->uncompressed_value), + lz4_value_len, + uncompressed_value_len) < 0) { + GRN_FREE(iw->uncompressed_value); + iw->uncompressed_value = NULL; + *value_len = 0; + grn_ja_compress_error(ctx, + ja, + id, + GRN_LZ4_ERROR, + "[lz4] failed to decompress", + NULL); + return NULL; + } + *value_len = uncompressed_value_len; + return iw->uncompressed_value; +} +#endif /* GRN_WITH_LZ4 */ + +#ifdef GRN_WITH_ZSTD +#include + +static void * +grn_ja_ref_zstd(grn_ctx *ctx, + grn_ja *ja, + grn_id id, + grn_io_win *iw, + uint32_t *value_len) +{ + void *raw_value; + uint32_t raw_value_len; + void *zstd_value; + uint32_t zstd_value_len; + void *unpacked_value; + uint32_t uncompressed_value_len; + size_t written_len; + + if (!(raw_value = grn_ja_ref_raw(ctx, ja, id, iw, &raw_value_len))) { + iw->uncompressed_value = NULL; + *value_len = 0; + return NULL; + } + + unpacked_value = grn_ja_ref_packed(ctx, + iw, value_len, + raw_value, raw_value_len, + &zstd_value, &zstd_value_len, + &uncompressed_value_len); + if (unpacked_value) { + return unpacked_value; + } + + if (!(iw->uncompressed_value = GRN_MALLOC(uncompressed_value_len))) { + iw->uncompressed_value = NULL; + *value_len = 0; + return NULL; + } + + written_len = ZSTD_decompress((char *)(iw->uncompressed_value), + uncompressed_value_len, + zstd_value, + zstd_value_len); + if (ZSTD_isError(written_len)) { + GRN_FREE(iw->uncompressed_value); + iw->uncompressed_value = NULL; + *value_len = 0; + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZSTD_ERROR, + "[zstd] failed to decompress", + ZSTD_getErrorName(written_len)); + return NULL; + } + *value_len = uncompressed_value_len; + return iw->uncompressed_value; +} +#endif /* GRN_WITH_ZSTD */ + +void * +grn_ja_ref(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_io_win *iw, uint32_t *value_len) +{ + switch (ja->header->flags & GRN_OBJ_COMPRESS_MASK) { +#ifdef GRN_WITH_ZLIB + case GRN_OBJ_COMPRESS_ZLIB : + return grn_ja_ref_zlib(ctx, ja, id, iw, value_len); +#endif /* GRN_WITH_ZLIB */ +#ifdef GRN_WITH_LZ4 + case GRN_OBJ_COMPRESS_LZ4 : + return grn_ja_ref_lz4(ctx, ja, id, iw, value_len); +#endif /* GRN_WITH_LZ4 */ +#ifdef GRN_WITH_ZSTD + case GRN_OBJ_COMPRESS_ZSTD : + return grn_ja_ref_zstd(ctx, ja, id, iw, value_len); +#endif /* GRN_WITH_ZSTD */ + default : + return grn_ja_ref_raw(ctx, ja, id, iw, value_len); + } +} + +grn_obj * +grn_ja_get_value(grn_ctx *ctx, grn_ja *ja, grn_id id, grn_obj *value) +{ + void *v; + uint32_t len; + grn_io_win iw; + if (!value) { + if (!(value = grn_obj_open(ctx, GRN_BULK, 0, 0))) { + ERR(GRN_INVALID_ARGUMENT, "grn_obj_get_value failed"); + goto exit; + } + } + if ((v = grn_ja_ref(ctx, ja, id, &iw, &len))) { + if ((ja->header->flags & GRN_OBJ_RING_BUFFER) && + len > ja->header->max_element_size) { + byte *b = v; + uint32_t el = len - sizeof(uint32_t); + uint32_t pos = *((uint32_t *)(b + el)); + GRN_ASSERT(pos < el); + grn_bulk_write(ctx, value, (char *)(b + pos), el - pos); + grn_bulk_write(ctx, value, (char *)(b), pos); + } else { + grn_bulk_write(ctx, value, v, len); + } + grn_ja_unref(ctx, &iw); + } +exit : + return value; +} + +#ifdef GRN_WITH_ZLIB +inline static grn_rc +grn_ja_put_zlib(grn_ctx *ctx, grn_ja *ja, grn_id id, + void *value, uint32_t value_len, int flags, uint64_t *cas) +{ + grn_rc rc; + z_stream zstream; + void *zvalue; + int zvalue_len; + int zrc; + + if (value_len == 0) { + return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas); + } + + if (value_len < COMPRESS_THRESHOLD_BYTE) { + return grn_ja_put_packed(ctx, ja, id, value, value_len, flags, cas); + } + + zstream.next_in = value; + zstream.avail_in = value_len; + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zrc = deflateInit2(&zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, + 15 /* windowBits */, + 8 /* memLevel */, + Z_DEFAULT_STRATEGY); + if (zrc != Z_OK) { + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZLIB_ERROR, + "[zlib] failed to compress: initialize", + grn_zrc_to_string(zrc)); + return ctx->rc; + } + zvalue_len = deflateBound(&zstream, value_len); + if (!(zvalue = GRN_MALLOC(zvalue_len + sizeof(uint64_t)))) { + deflateEnd(&zstream); + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZLIB_ERROR, + "[zlib] failed to allocate compress buffer", + NULL); + return ctx->rc; + } + zstream.next_out = (Bytef *)(((uint64_t *)zvalue) + 1); + zstream.avail_out = zvalue_len; + zrc = deflate(&zstream, Z_FINISH); + if (zrc != Z_STREAM_END) { + deflateEnd(&zstream); + GRN_FREE(zvalue); + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZLIB_ERROR, + "[zlib] failed to compress: finish", + grn_zrc_to_string(zrc)); + return ctx->rc; + } + zvalue_len = zstream.total_out; + zrc = deflateEnd(&zstream); + if (zrc != Z_OK) { + GRN_FREE(zvalue); + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZLIB_ERROR, + "[zlib] failed to compress: end", + grn_zrc_to_string(zrc)); + return ctx->rc; + } + *(uint64_t *)zvalue = value_len; + rc = grn_ja_put_raw(ctx, ja, id, zvalue, zvalue_len + sizeof(uint64_t), flags, cas); + GRN_FREE(zvalue); + return rc; +} +#endif /* GRN_WITH_ZLIB */ + +#ifdef GRN_WITH_LZ4 +inline static grn_rc +grn_ja_put_lz4(grn_ctx *ctx, grn_ja *ja, grn_id id, + void *value, uint32_t value_len, int flags, uint64_t *cas) +{ + grn_rc rc; + void *packed_value; + int packed_value_len_max; + int packed_value_len_real; + char *lz4_value; + int lz4_value_len_max; + int lz4_value_len_real; + + if (value_len == 0) { + return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas); + } + + if (value_len < COMPRESS_THRESHOLD_BYTE) { + return grn_ja_put_packed(ctx, ja, id, value, value_len, flags, cas); + } + + if (value_len > (uint32_t)LZ4_MAX_INPUT_SIZE) { + uint64_t packed_value_meta; + + packed_value_len_real = value_len + sizeof(uint64_t); + packed_value = GRN_MALLOC(packed_value_len_real); + if (!packed_value) { + grn_ja_compress_error(ctx, + ja, + id, + GRN_LZ4_ERROR, + "[lz4] failed to allocate packed buffer", + NULL); + return ctx->rc; + } + packed_value_meta = value_len | COMPRESSED_VALUE_META_FLAG_RAW; + *((uint64_t *)packed_value) = packed_value_meta; + memcpy(((uint64_t *)packed_value) + 1, + value, + value_len); + rc = grn_ja_put_raw(ctx, + ja, + id, + packed_value, + packed_value_len_real, + flags, + cas); + GRN_FREE(packed_value); + return rc; + } + + lz4_value_len_max = LZ4_compressBound(value_len); + packed_value_len_max = lz4_value_len_max + sizeof(uint64_t); + if (!(packed_value = GRN_MALLOC(packed_value_len_max))) { + grn_ja_compress_error(ctx, + ja, + id, + GRN_LZ4_ERROR, + "[lz4] failed to allocate compress buffer", + NULL); + return ctx->rc; + } + lz4_value = (char *)((uint64_t *)packed_value + 1); + lz4_value_len_real = LZ4_compress_default((const char *)value, + lz4_value, + value_len, + lz4_value_len_max); + if (lz4_value_len_real <= 0) { + GRN_FREE(packed_value); + grn_ja_compress_error(ctx, + ja, + id, + GRN_LZ4_ERROR, + "[lz4] failed to compress", + NULL); + return ctx->rc; + } + *(uint64_t *)packed_value = value_len; + packed_value_len_real = lz4_value_len_real + sizeof(uint64_t); + rc = grn_ja_put_raw(ctx, + ja, + id, + packed_value, + packed_value_len_real, + flags, + cas); + GRN_FREE(packed_value); + return rc; +} +#endif /* GRN_WITH_LZ4 */ + +#ifdef GRN_WITH_ZSTD +inline static grn_rc +grn_ja_put_zstd(grn_ctx *ctx, + grn_ja *ja, + grn_id id, + void *value, + uint32_t value_len, + int flags, + uint64_t *cas) +{ + grn_rc rc; + void *packed_value; + int packed_value_len_max; + int packed_value_len_real; + void *zstd_value; + int zstd_value_len_max; + int zstd_value_len_real; + int zstd_compression_level = 3; + + if (value_len == 0) { + return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas); + } + + if (value_len < COMPRESS_THRESHOLD_BYTE) { + return grn_ja_put_packed(ctx, ja, id, value, value_len, flags, cas); + } + + zstd_value_len_max = ZSTD_compressBound(value_len); + packed_value_len_max = zstd_value_len_max + sizeof(uint64_t); + if (!(packed_value = GRN_MALLOC(packed_value_len_max))) { + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZSTD_ERROR, + "[zstd] failed to allocate compress buffer", + NULL); + return ctx->rc; + } + zstd_value = ((uint64_t *)packed_value) + 1; + zstd_value_len_real = ZSTD_compress(zstd_value, zstd_value_len_max, + value, value_len, + zstd_compression_level); + if (ZSTD_isError(zstd_value_len_real)) { + grn_ja_compress_error(ctx, + ja, + id, + GRN_ZSTD_ERROR, + "[zstd] failed to compress", + ZSTD_getErrorName(zstd_value_len_real)); + return ctx->rc; + } + *(uint64_t *)packed_value = value_len; + packed_value_len_real = zstd_value_len_real + sizeof(uint64_t); + rc = grn_ja_put_raw(ctx, + ja, + id, + packed_value, + packed_value_len_real, + flags, + cas); + GRN_FREE(packed_value); + return rc; +} +#endif /* GRN_WITH_ZSTD */ + +grn_rc +grn_ja_put(grn_ctx *ctx, grn_ja *ja, grn_id id, void *value, uint32_t value_len, + int flags, uint64_t *cas) +{ + switch (ja->header->flags & GRN_OBJ_COMPRESS_MASK) { +#ifdef GRN_WITH_ZLIB + case GRN_OBJ_COMPRESS_ZLIB : + return grn_ja_put_zlib(ctx, ja, id, value, value_len, flags, cas); +#endif /* GRN_WITH_ZLIB */ +#ifdef GRN_WITH_LZ4 + case GRN_OBJ_COMPRESS_LZ4 : + return grn_ja_put_lz4(ctx, ja, id, value, value_len, flags, cas); +#endif /* GRN_WITH_LZ4 */ +#ifdef GRN_WITH_ZSTD + case GRN_OBJ_COMPRESS_ZSTD : + return grn_ja_put_zstd(ctx, ja, id, value, value_len, flags, cas); +#endif /* GRN_WITH_ZSTD */ + default : + return grn_ja_put_raw(ctx, ja, id, value, value_len, flags, cas); + } +} + +static grn_rc +grn_ja_defrag_seg(grn_ctx *ctx, grn_ja *ja, uint32_t seg) +{ + byte *v = NULL, *ve; + uint32_t element_size, cum = 0, *seginfo = &SEGMENTS_AT(ja,seg), sum; + sum = (*seginfo & ~SEG_MASK); + GRN_IO_SEG_REF(ja->io, seg, v); + if (!v) { return GRN_NO_MEMORY_AVAILABLE; } + ve = v + JA_SEGMENT_SIZE; + while (v < ve && cum < sum) { + grn_id id = *((grn_id *)v); + if (!id) { break; } + if (id & DELETED) { + element_size = (id & ~DELETED); + } else { + uint64_t cas; + uint32_t pos; + if (grn_ja_element_info(ctx, ja, id, &cas, &pos, &element_size)) { break; } + if (v + sizeof(uint32_t) != ve - JA_SEGMENT_SIZE + pos) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "dseges[%d] = pos unmatch (%d != %" GRN_FMT_LLD ")", + seg, pos, (long long int)(v + sizeof(uint32_t) + JA_SEGMENT_SIZE - ve)); + break; + } + if (grn_ja_put(ctx, ja, id, v + sizeof(uint32_t), element_size, GRN_OBJ_SET, &cas)) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "dseges[%d] = put failed (%d)", seg, id); + break; + } + element_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1); + cum += sizeof(uint32_t) + element_size; + } + v += sizeof(uint32_t) + element_size; + } + if (*seginfo) { + GRN_LOG(ctx, GRN_LOG_WARNING, "dseges[%d] = %d after defrag", seg, (*seginfo & ~SEG_MASK)); + } + GRN_IO_SEG_UNREF(ja->io, seg); + return GRN_SUCCESS; +} + +int +grn_ja_defrag(grn_ctx *ctx, grn_ja *ja, int threshold) +{ + int nsegs = 0; + uint32_t seg, ts = 1U << (GRN_JA_W_SEGMENT - threshold); + for (seg = 0; seg < JA_N_DSEGMENTS; seg++) { + if (seg == *(ja->header->curr_seg)) { continue; } + if (((SEGMENTS_AT(ja, seg) & SEG_MASK) == SEG_SEQ) && + ((SEGMENTS_AT(ja, seg) & ~SEG_MASK) < ts)) { + if (!grn_ja_defrag_seg(ctx, ja, seg)) { nsegs++; } + } + } + return nsegs; +} + +void +grn_ja_check(grn_ctx *ctx, grn_ja *ja) +{ + char buf[8]; + uint32_t seg; + struct grn_ja_header *h = ja->header; + GRN_OUTPUT_ARRAY_OPEN("RESULT", 8); + GRN_OUTPUT_MAP_OPEN("SUMMARY", 8); + GRN_OUTPUT_CSTR("flags"); + grn_itoh(h->flags, buf, 8); + GRN_OUTPUT_STR(buf, 8); + GRN_OUTPUT_CSTR("curr seg"); + GRN_OUTPUT_INT64(*(h->curr_seg)); + GRN_OUTPUT_CSTR("curr pos"); + GRN_OUTPUT_INT64(*(h->curr_pos)); + GRN_OUTPUT_CSTR("max_element_size"); + GRN_OUTPUT_INT64(h->max_element_size); + GRN_OUTPUT_CSTR("segregate_threshold"); + GRN_OUTPUT_INT64(h->segregate_threshold); + GRN_OUTPUT_CSTR("n_element_variation"); + GRN_OUTPUT_INT64(h->n_element_variation); + GRN_OUTPUT_MAP_CLOSE(); + GRN_OUTPUT_ARRAY_OPEN("DETAIL", -1); + for (seg = 0; seg < JA_N_DSEGMENTS; seg++) { + int dseg = SEGMENTS_AT(ja, seg); + if (dseg) { + GRN_OUTPUT_MAP_OPEN("SEG", -1); + GRN_OUTPUT_CSTR("seg id"); + GRN_OUTPUT_INT64(seg); + GRN_OUTPUT_CSTR("seg type"); + GRN_OUTPUT_INT64((dseg & SEG_MASK)>>28); + GRN_OUTPUT_CSTR("seg value"); + GRN_OUTPUT_INT64(dseg & ~SEG_MASK); + if ((dseg & SEG_MASK) == SEG_SEQ) { + byte *v = NULL, *ve; + uint32_t element_size, cum = 0, sum = dseg & ~SEG_MASK; + uint32_t n_del_elements = 0, n_elements = 0, s_del_elements = 0, s_elements = 0; + GRN_IO_SEG_REF(ja->io, seg, v); + if (v) { + /* + GRN_OUTPUT_CSTR("seg seq"); + GRN_OUTPUT_ARRAY_OPEN("SEQ", -1); + */ + ve = v + JA_SEGMENT_SIZE; + while (v < ve && cum < sum) { + grn_id id = *((grn_id *)v); + /* + GRN_OUTPUT_MAP_OPEN("ENTRY", -1); + GRN_OUTPUT_CSTR("id"); + GRN_OUTPUT_INT64(id); + */ + if (!id) { break; } + if (id & DELETED) { + element_size = (id & ~DELETED); + n_del_elements++; + s_del_elements += element_size; + } else { + element_size = grn_ja_size(ctx, ja, id); + element_size = (element_size + sizeof(grn_id) - 1) & ~(sizeof(grn_id) - 1); + cum += sizeof(uint32_t) + element_size; + n_elements++; + s_elements += sizeof(uint32_t) + element_size; + } + v += sizeof(uint32_t) + element_size; + /* + GRN_OUTPUT_CSTR("size"); + GRN_OUTPUT_INT64(element_size); + GRN_OUTPUT_CSTR("cum"); + GRN_OUTPUT_INT64(cum); + GRN_OUTPUT_MAP_CLOSE(); + */ + } + GRN_IO_SEG_UNREF(ja->io, seg); + /* + GRN_OUTPUT_ARRAY_CLOSE(); + */ + GRN_OUTPUT_CSTR("n_elements"); + GRN_OUTPUT_INT64(n_elements); + GRN_OUTPUT_CSTR("s_elements"); + GRN_OUTPUT_INT64(s_elements); + GRN_OUTPUT_CSTR("n_del_elements"); + GRN_OUTPUT_INT64(n_del_elements); + GRN_OUTPUT_CSTR("s_del_elements"); + GRN_OUTPUT_INT64(s_del_elements); + if (cum != sum) { + GRN_OUTPUT_CSTR("cum gap"); + GRN_OUTPUT_INT64(cum - sum); + } + } + } + GRN_OUTPUT_MAP_CLOSE(); + } + } + GRN_OUTPUT_ARRAY_CLOSE(); + GRN_OUTPUT_ARRAY_CLOSE(); +} + +/* grn_ja_reader */ + +grn_rc +grn_ja_reader_init(grn_ctx *ctx, grn_ja_reader *reader, grn_ja *ja) +{ + reader->ja = ja; + reader->einfo_seg_id = JA_ESEG_VOID; + reader->ref_avail = GRN_FALSE; + reader->ref_seg_id = JA_ESEG_VOID; + reader->ref_seg_ids = NULL; + reader->nref_seg_ids = 0; + reader->ref_seg_ids_size = 0; + reader->body_seg_id = JA_ESEG_VOID; + reader->body_seg_addr = NULL; + reader->packed_buf = NULL; + reader->packed_buf_size = 0; +#ifdef GRN_WITH_ZLIB + if (reader->ja->header->flags & GRN_OBJ_COMPRESS_ZLIB) { + z_stream *new_stream = GRN_MALLOCN(z_stream, 1); + if (!new_stream) { + return GRN_NO_MEMORY_AVAILABLE; + } + new_stream->zalloc = NULL; + new_stream->zfree = NULL; + new_stream->opaque = NULL; + if (inflateInit2(new_stream, 15) != Z_OK) { + GRN_FREE(new_stream); + return GRN_ZLIB_ERROR; + } + reader->stream = new_stream; + } +#endif /* GRN_WITH_ZLIB */ + return GRN_SUCCESS; +} + +grn_rc +grn_ja_reader_fin(grn_ctx *ctx, grn_ja_reader *reader) +{ + grn_rc rc = GRN_SUCCESS; + if (reader->einfo_seg_id != JA_ESEG_VOID) { + GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id); + } + if (reader->ref_seg_ids) { + grn_ja_reader_unref(ctx, reader); + GRN_FREE(reader->ref_seg_ids); + } + if (reader->body_seg_addr) { + GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id); + } + if (reader->packed_buf) { + GRN_FREE(reader->packed_buf); + } +#ifdef GRN_WITH_ZLIB + if (reader->ja->header->flags & GRN_OBJ_COMPRESS_ZLIB) { + if (reader->stream) { + if (inflateEnd((z_stream *)reader->stream) != Z_OK) { + rc = GRN_UNKNOWN_ERROR; + } + GRN_FREE(reader->stream); + } + } +#endif /* GRN_WITH_ZLIB */ + return rc; +} + +grn_rc +grn_ja_reader_open(grn_ctx *ctx, grn_ja *ja, grn_ja_reader **reader) +{ + grn_rc rc; + grn_ja_reader *new_reader = GRN_MALLOCN(grn_ja_reader, 1); + if (!new_reader) { + return GRN_NO_MEMORY_AVAILABLE; + } + rc = grn_ja_reader_init(ctx, new_reader, ja); + if (rc != GRN_SUCCESS) { + GRN_FREE(new_reader); + return rc; + } + *reader = new_reader; + return GRN_SUCCESS; +} + +grn_rc +grn_ja_reader_close(grn_ctx *ctx, grn_ja_reader *reader) +{ + grn_rc rc = grn_ja_reader_fin(ctx, reader); + GRN_FREE(reader); + return rc; +} + +#ifdef GRN_WITH_COMPRESSED +/* grn_ja_reader_seek_compressed() prepares to access a compressed value. */ +static grn_rc +grn_ja_reader_seek_compressed(grn_ctx *ctx, grn_ja_reader *reader, grn_id id) +{ + grn_ja_einfo *einfo; + void *seg_addr; + uint32_t seg_id = reader->ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT]; + if (seg_id == JA_ESEG_VOID) { + return GRN_INVALID_ARGUMENT; + } + if (seg_id != reader->einfo_seg_id) { + GRN_IO_SEG_REF(reader->ja->io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + if (reader->einfo_seg_id != JA_ESEG_VOID) { + GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id); + } + reader->einfo_seg_id = seg_id; + reader->einfo_seg_addr = seg_addr; + } + einfo = (grn_ja_einfo *)reader->einfo_seg_addr; + einfo += id & JA_M_EINFO_IN_A_SEGMENT; + reader->einfo = einfo; + /* ETINY_P(einfo) is always false because the original size needs 8 bytes. */ + if (EHUGE_P(einfo)) { + EHUGE_DEC(einfo, seg_id, reader->packed_size); + reader->body_seg_offset = 0; + } else { + EINFO_DEC(einfo, seg_id, reader->body_seg_offset, reader->packed_size); + } + if (seg_id != reader->body_seg_id) { + GRN_IO_SEG_REF(reader->ja->io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + if (reader->body_seg_addr) { + GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id); + } + reader->body_seg_id = seg_id; + reader->body_seg_addr = seg_addr; + } + seg_addr = (char *)reader->body_seg_addr + reader->body_seg_offset; + reader->value_size = (uint32_t)*(uint64_t *)seg_addr; + return GRN_SUCCESS; +} +#endif /* GRN_WITH_COMPRESSED */ + +/* grn_ja_reader_seek_raw() prepares to access a value. */ +static grn_rc +grn_ja_reader_seek_raw(grn_ctx *ctx, grn_ja_reader *reader, grn_id id) +{ + grn_ja_einfo *einfo; + void *seg_addr; + uint32_t seg_id = reader->ja->header->esegs[id >> JA_W_EINFO_IN_A_SEGMENT]; + if (seg_id == JA_ESEG_VOID) { + return GRN_INVALID_ARGUMENT; + } + if (seg_id != reader->einfo_seg_id) { + GRN_IO_SEG_REF(reader->ja->io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + if (reader->einfo_seg_id != JA_ESEG_VOID) { + GRN_IO_SEG_UNREF(reader->ja->io, reader->einfo_seg_id); + } + reader->einfo_seg_id = seg_id; + reader->einfo_seg_addr = seg_addr; + } + einfo = (grn_ja_einfo *)reader->einfo_seg_addr; + einfo += id & JA_M_EINFO_IN_A_SEGMENT; + reader->einfo = einfo; + if (ETINY_P(einfo)) { + ETINY_DEC(einfo, reader->value_size); + reader->ref_avail = GRN_FALSE; + } else { + if (EHUGE_P(einfo)) { + EHUGE_DEC(einfo, seg_id, reader->value_size); + reader->ref_avail = GRN_FALSE; + } else { + EINFO_DEC(einfo, seg_id, reader->body_seg_offset, reader->value_size); + reader->ref_avail = GRN_TRUE; + } + if (reader->body_seg_addr) { + if (seg_id != reader->body_seg_id) { + GRN_IO_SEG_UNREF(reader->ja->io, reader->body_seg_id); + reader->body_seg_addr = NULL; + } + } + reader->body_seg_id = seg_id; + } + return GRN_SUCCESS; +} + +grn_rc +grn_ja_reader_seek(grn_ctx *ctx, grn_ja_reader *reader, grn_id id) +{ + switch (reader->ja->header->flags & GRN_OBJ_COMPRESS_MASK) { +#ifdef GRN_WITH_ZLIB + case GRN_OBJ_COMPRESS_ZLIB : + return grn_ja_reader_seek_compressed(ctx, reader, id); +#endif /* GRN_WITH_ZLIB */ +#ifdef GRN_WITH_LZ4 + case GRN_OBJ_COMPRESS_LZ4 : + return grn_ja_reader_seek_compressed(ctx, reader, id); +#endif /* GRN_WITH_LZ4 */ +#ifdef GRN_WITH_ZSTD + case GRN_OBJ_COMPRESS_ZSTD : + return grn_ja_reader_seek_compressed(ctx, reader, id); +#endif /* GRN_WITH_ZSTD */ + default : + return grn_ja_reader_seek_raw(ctx, reader, id); + } +} + +grn_rc +grn_ja_reader_ref(grn_ctx *ctx, grn_ja_reader *reader, void **addr) +{ + if (!reader->ref_avail) { + return GRN_INVALID_ARGUMENT; + } + if (reader->body_seg_id != reader->ref_seg_id) { + void *seg_addr; + if (reader->nref_seg_ids == reader->ref_seg_ids_size) { + size_t n_bytes; + uint32_t new_size, *new_seg_ids; + if (reader->ref_seg_ids_size == 0) { + new_size = GRN_JA_READER_INITIAL_REF_SEG_IDS_SIZE; + } else { + new_size = reader->ref_seg_ids_size * 2; + } + n_bytes = sizeof(uint32_t) * new_size; + new_seg_ids = (uint32_t *)GRN_REALLOC(reader->ref_seg_ids, n_bytes); + if (!new_seg_ids) { + return GRN_NO_MEMORY_AVAILABLE; + } + reader->ref_seg_ids = new_seg_ids; + reader->ref_seg_ids_size = new_size; + } + GRN_IO_SEG_REF(reader->ja->io, reader->body_seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + reader->ref_seg_id = reader->body_seg_id; + reader->ref_seg_addr = seg_addr; + reader->ref_seg_ids[reader->nref_seg_ids++] = reader->body_seg_id; + } + *addr = (char *)reader->ref_seg_addr + reader->body_seg_offset; + return GRN_SUCCESS; +} + +grn_rc +grn_ja_reader_unref(grn_ctx *ctx, grn_ja_reader *reader) +{ + uint32_t i; + for (i = 0; i < reader->nref_seg_ids; i++) { + GRN_IO_SEG_UNREF(reader->ja->io, reader->ref_seg_ids[i]); + } + reader->ref_seg_id = JA_ESEG_VOID; + reader->nref_seg_ids = 0; + return GRN_FUNCTION_NOT_IMPLEMENTED; +} + +#ifdef GRN_WITH_ZLIB +/* grn_ja_reader_read_zlib() reads a value compressed with zlib. */ +static grn_rc +grn_ja_reader_read_zlib(grn_ctx *ctx, grn_ja_reader *reader, void *buf) +{ + uLong dest_size = reader->value_size; + z_stream *stream = (z_stream *)reader->stream; + grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo; + if (EHUGE_P(einfo)) { + /* TODO: Use z_stream to avoid copy. */ + grn_io *io = reader->ja->io; + void *seg_addr; + char *packed_ptr; + uint32_t size, seg_id; + if (reader->packed_size > reader->packed_buf_size) { + void *new_buf = GRN_REALLOC(reader->packed_buf, reader->packed_size); + if (!new_buf) { + return GRN_NO_MEMORY_AVAILABLE; + } + reader->packed_buf = new_buf; + reader->packed_buf_size = reader->packed_size; + } + packed_ptr = (char *)reader->packed_buf; + grn_memcpy(packed_ptr, (char *)reader->body_seg_addr + sizeof(uint64_t), + io->header->segment_size - sizeof(uint64_t)); + packed_ptr += io->header->segment_size - sizeof(uint64_t); + size = reader->packed_size - (io->header->segment_size - sizeof(uint64_t)); + seg_id = reader->body_seg_id + 1; + while (size > io->header->segment_size) { + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(packed_ptr, seg_addr, io->header->segment_size); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + size -= io->header->segment_size; + packed_ptr += io->header->segment_size; + } + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(packed_ptr, seg_addr, size); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + if (uncompress((Bytef *)buf, &dest_size, (Bytef *)reader->packed_buf, + reader->packed_size - sizeof(uint64_t)) != Z_OK) { + return GRN_ZLIB_ERROR; + } + if (dest_size != reader->value_size) { + return GRN_ZLIB_ERROR; + } + } else { + char *packed_addr = (char *)reader->body_seg_addr; + packed_addr += reader->body_seg_offset + sizeof(uint64_t); + if (inflateReset(stream) != Z_OK) { + return GRN_ZLIB_ERROR; + } + stream->next_in = (Bytef *)packed_addr; + stream->avail_in = reader->packed_size - sizeof(uint64_t); + stream->next_out = (Bytef *)buf; + stream->avail_out = dest_size; + if ((inflate(stream, Z_FINISH) != Z_STREAM_END) || stream->avail_out) { + return GRN_ZLIB_ERROR; + } + } + return GRN_SUCCESS; +} +#endif /* GRN_WITH_ZLIB */ + +#ifdef GRN_WITH_LZ4 +/* grn_ja_reader_read_lz4() reads a value compressed with LZ4. */ +static grn_rc +grn_ja_reader_read_lz4(grn_ctx *ctx, grn_ja_reader *reader, void *buf) +{ + int src_size, dest_size; + grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo; + if (EHUGE_P(einfo)) { + grn_io *io = reader->ja->io; + void *seg_addr; + char *packed_ptr; + uint32_t size, seg_id; + if (reader->packed_size > reader->packed_buf_size) { + void *new_buf = GRN_REALLOC(reader->packed_buf, reader->packed_size); + if (!new_buf) { + return GRN_NO_MEMORY_AVAILABLE; + } + reader->packed_buf = new_buf; + reader->packed_buf_size = reader->packed_size; + } + packed_ptr = (char *)reader->packed_buf; + grn_memcpy(packed_ptr, (char *)reader->body_seg_addr + sizeof(uint64_t), + io->header->segment_size - sizeof(uint64_t)); + packed_ptr += io->header->segment_size - sizeof(uint64_t); + size = reader->packed_size - (io->header->segment_size - sizeof(uint64_t)); + seg_id = reader->body_seg_id + 1; + while (size > io->header->segment_size) { + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(packed_ptr, seg_addr, io->header->segment_size); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + size -= io->header->segment_size; + packed_ptr += io->header->segment_size; + } + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(packed_ptr, seg_addr, size); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + src_size = (int)(reader->packed_size - sizeof(uint64_t)); + dest_size = LZ4_decompress_safe(reader->packed_buf, buf, src_size, + (int)reader->value_size); + } else { + char *packed_addr = (char *)reader->body_seg_addr; + packed_addr += reader->body_seg_offset + sizeof(uint64_t); + src_size = (int)(reader->packed_size - sizeof(uint64_t)); + dest_size = LZ4_decompress_safe(packed_addr, buf, src_size, + (int)reader->value_size); + } + if ((uint32_t)dest_size != reader->value_size) { + return GRN_LZ4_ERROR; + } + return GRN_SUCCESS; +} +#endif /* GRN_WITH_LZ4 */ + +#ifdef GRN_WITH_ZSTD +/* grn_ja_reader_read_zstd() reads a value compressed with Zstandard. */ +static grn_rc +grn_ja_reader_read_zstd(grn_ctx *ctx, grn_ja_reader *reader, void *buf) +{ + int src_size, dest_size; + grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo; + if (EHUGE_P(einfo)) { + grn_io *io = reader->ja->io; + void *seg_addr; + char *packed_ptr; + uint32_t size, seg_id; + if (reader->packed_size > reader->packed_buf_size) { + void *new_buf = GRN_REALLOC(reader->packed_buf, reader->packed_size); + if (!new_buf) { + return GRN_NO_MEMORY_AVAILABLE; + } + reader->packed_buf = new_buf; + reader->packed_buf_size = reader->packed_size; + } + packed_ptr = (char *)reader->packed_buf; + grn_memcpy(packed_ptr, (char *)reader->body_seg_addr + sizeof(uint64_t), + io->header->segment_size - sizeof(uint64_t)); + packed_ptr += io->header->segment_size - sizeof(uint64_t); + size = reader->packed_size - (io->header->segment_size - sizeof(uint64_t)); + seg_id = reader->body_seg_id + 1; + while (size > io->header->segment_size) { + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(packed_ptr, seg_addr, io->header->segment_size); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + size -= io->header->segment_size; + packed_ptr += io->header->segment_size; + } + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(packed_ptr, seg_addr, size); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + src_size = (int)(reader->packed_size - sizeof(uint64_t)); + dest_size = ZSTD_decompress(reader->packed_buf, reader->value_size, + buf, src_size); + } else { + char *packed_addr = (char *)reader->body_seg_addr; + packed_addr += reader->body_seg_offset + sizeof(uint64_t); + src_size = (int)(reader->packed_size - sizeof(uint64_t)); + dest_size = ZSTD_decompress(packed_addr, reader->value_size, + buf, src_size); + } + if ((uint32_t)dest_size != reader->value_size) { + return GRN_ZSTD_ERROR; + } + return GRN_SUCCESS; +} +#endif /* GRN_WITH_ZSTD */ + +/* grn_ja_reader_read_raw() reads a value. */ +static grn_rc +grn_ja_reader_read_raw(grn_ctx *ctx, grn_ja_reader *reader, void *buf) +{ + grn_io *io = reader->ja->io; + grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo; + if (ETINY_P(einfo)) { + grn_memcpy(buf, einfo, reader->value_size); + } else if (EHUGE_P(einfo)) { + char *buf_ptr = (char *)buf; + void *seg_addr; + uint32_t seg_id = reader->body_seg_id; + uint32_t size = reader->value_size; + while (size > io->header->segment_size) { + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(buf_ptr, seg_addr, io->header->segment_size); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + size -= io->header->segment_size; + buf_ptr += io->header->segment_size; + } + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(buf_ptr, seg_addr, size); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + } else { + if (!reader->body_seg_addr) { + GRN_IO_SEG_REF(io, reader->body_seg_id, reader->body_seg_addr); + if (!reader->body_seg_addr) { + return GRN_UNKNOWN_ERROR; + } + } + grn_memcpy(buf, (char *)reader->body_seg_addr + reader->body_seg_offset, + reader->value_size); + } + return GRN_SUCCESS; +} + +grn_rc +grn_ja_reader_read(grn_ctx *ctx, grn_ja_reader *reader, void *buf) +{ + switch (reader->ja->header->flags & GRN_OBJ_COMPRESS_MASK) { +#ifdef GRN_WITH_ZLIB + case GRN_OBJ_COMPRESS_ZLIB : + return grn_ja_reader_read_zlib(ctx, reader, buf); +#endif /* GRN_WITH_ZLIB */ +#ifdef GRN_WITH_LZ4 + case GRN_OBJ_COMPRESS_LZ4 : + return grn_ja_reader_read_lz4(ctx, reader, buf); +#endif /* GRN_WITH_LZ4 */ +#ifdef GRN_WITH_ZSTD + case GRN_OBJ_COMPRESS_ZSTD : + return grn_ja_reader_read_zstd(ctx, reader, buf); +#endif /* GRN_WITH_ZSTD */ + default : + return grn_ja_reader_read_raw(ctx, reader, buf); + } +} + +#ifdef GRN_WITH_ZLIB +/* grn_ja_reader_pread_zlib() reads a part of a value compressed with zlib. */ +static grn_rc +grn_ja_reader_pread_zlib(grn_ctx *ctx, grn_ja_reader *reader, + size_t offset, size_t size, void *buf) +{ + /* TODO: To be supported? */ + return GRN_FUNCTION_NOT_IMPLEMENTED; +} +#endif /* GRN_WITH_ZLIB */ + +#ifdef GRN_WITH_LZ4 +/* grn_ja_reader_pread_lz4() reads a part of a value compressed with LZ4. */ +static grn_rc +grn_ja_reader_pread_lz4(grn_ctx *ctx, grn_ja_reader *reader, + size_t offset, size_t size, void *buf) +{ + /* TODO: To be supported? */ + return GRN_FUNCTION_NOT_IMPLEMENTED; +} +#endif /* GRN_WITH_LZ4 */ + +#ifdef GRN_WITH_ZSTD +/* grn_ja_reader_pread_zstd() reads a part of a value compressed with ZSTD. */ +static grn_rc +grn_ja_reader_pread_zstd(grn_ctx *ctx, grn_ja_reader *reader, + size_t offset, size_t size, void *buf) +{ + /* TODO: To be supported? */ + return GRN_FUNCTION_NOT_IMPLEMENTED; +} +#endif /* GRN_WITH_ZSTD */ + +/* grn_ja_reader_pread_raw() reads a part of a value. */ +static grn_rc +grn_ja_reader_pread_raw(grn_ctx *ctx, grn_ja_reader *reader, + size_t offset, size_t size, void *buf) +{ + grn_io *io = reader->ja->io; + grn_ja_einfo *einfo = (grn_ja_einfo *)reader->einfo; + if ((offset >= reader->value_size) || !size) { + return GRN_SUCCESS; + } + if (size > (reader->value_size - offset)) { + size = reader->value_size - offset; + } + if (ETINY_P(einfo)) { + grn_memcpy(buf, (char *)einfo + offset, size); + } else if (EHUGE_P(einfo)) { + char *buf_ptr = (char *)buf; + void *seg_addr; + uint32_t seg_id = reader->body_seg_id; + if (offset >= io->header->segment_size) { + seg_id += offset / io->header->segment_size; + offset %= io->header->segment_size; + } + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(buf_ptr, (char *)seg_addr + offset, + io->header->segment_size - offset); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + size -= io->header->segment_size - offset; + buf_ptr += io->header->segment_size - offset; + while (size > io->header->segment_size) { + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(buf_ptr, (char *)seg_addr, io->header->segment_size); + GRN_IO_SEG_UNREF(io, seg_id); + seg_id++; + size -= io->header->segment_size; + buf_ptr += io->header->segment_size; + } + GRN_IO_SEG_REF(io, seg_id, seg_addr); + if (!seg_addr) { + return GRN_UNKNOWN_ERROR; + } + grn_memcpy(buf_ptr, seg_addr, size); + GRN_IO_SEG_UNREF(io, seg_id); + } else { + if (!reader->body_seg_addr) { + GRN_IO_SEG_REF(io, reader->body_seg_id, reader->body_seg_addr); + if (!reader->body_seg_addr) { + return GRN_UNKNOWN_ERROR; + } + } + offset += reader->body_seg_offset; + grn_memcpy(buf, (char *)reader->body_seg_addr + offset, size); + } + return GRN_SUCCESS; +} + +grn_rc +grn_ja_reader_pread(grn_ctx *ctx, grn_ja_reader *reader, + size_t offset, size_t size, void *buf) +{ + switch (reader->ja->header->flags & GRN_OBJ_COMPRESS_MASK) { +#ifdef GRN_WITH_ZLIB + case GRN_OBJ_COMPRESS_ZLIB : + return grn_ja_reader_pread_zlib(ctx, reader, offset, size, buf); +#endif /* GRN_WITH_ZLIB */ +#ifdef GRN_WITH_LZ4 + case GRN_OBJ_COMPRESS_LZ4 : + return grn_ja_reader_pread_lz4(ctx, reader, offset, size, buf); +#endif /* GRN_WITH_LZ4 */ +#ifdef GRN_WITH_ZSTD + case GRN_OBJ_COMPRESS_ZSTD : + return grn_ja_reader_pread_zstd(ctx, reader, offset, size, buf); +#endif /* GRN_WITH_ZSTD */ + default : + return grn_ja_reader_pread_raw(ctx, reader, offset, size, buf); + } +} + +/**** vgram ****/ + +/* + +static int len_sum = 0; +static int img_sum = 0; +static int simple_sum = 0; +static int skip_sum = 0; + +grn_vgram * +grn_vgram_create(const char *path) +{ + grn_vgram *s; + if (!(s = GRN_MALLOCN(grn_vgram, 1))) { return NULL; } + s->vgram = grn_sym_create(path, sizeof(grn_id) * 2, 0, GRN_ENC_NONE); + if (!s->vgram) { + GRN_FREE(s); + return NULL; + } + return s; +} + +grn_vgram * +grn_vgram_open(const char *path) +{ + grn_vgram *s; + if (!(s = GRN_MALLOCN(grn_vgram, 1))) { return NULL; } + s->vgram = grn_sym_open(path); + if (!s->vgram) { + GRN_FREE(s); + return NULL; + } + return s; +} + +grn_vgram_buf * +grn_vgram_buf_open(size_t len) +{ + grn_vgram_buf *b; + if (!(b = GRN_MALLOCN(grn_vgram_buf, 1))) { return NULL; } + b->len = len; + b->tvs = b->tvp = GRN_MALLOCN(grn_id, len); + if (!b->tvp) { GRN_FREE(b); return NULL; } + b->tve = b->tvs + len; + b->vps = b->vpp = GRN_MALLOCN(grn_vgram_vnode, len * 2); + if (!b->vpp) { GRN_FREE(b->tvp); GRN_FREE(b); return NULL; } + b->vpe = b->vps + len; + return b; +} + +grn_rc +grn_vgram_buf_add(grn_vgram_buf *b, grn_id tid) +{ + uint8_t dummybuf[8], *dummyp; + if (b->tvp < b->tve) { *b->tvp++ = tid; } + dummyp = dummybuf; + GRN_B_ENC(tid, dummyp); + simple_sum += dummyp - dummybuf; + return GRN_SUCCESS; +} + +typedef struct { + grn_id vid; + grn_id tid; +} vgram_key; + +grn_rc +grn_vgram_update(grn_vgram *vgram, grn_id rid, grn_vgram_buf *b, grn_hash *terms) +{ + grn_inv_updspec **u; + if (b && b->tvs < b->tvp) { + grn_id *t0, *tn; + for (t0 = b->tvs; t0 < b->tvp - 1; t0++) { + grn_vgram_vnode *v, **vp; + if (grn_set_at(terms, t0, (void **) &u)) { + vp = &(*u)->vnodes; + for (tn = t0 + 1; tn < b->tvp; tn++) { + for (v = *vp; v && v->tid != *tn; v = v->cdr) ; + if (!v) { + if (b->vpp < b->vpe) { + v = b->vpp++; + } else { + // todo; + break; + } + v->car = NULL; + v->cdr = *vp; + *vp = v; + v->tid = *tn; + v->vid = 0; + v->freq = 0; + v->len = tn - t0; + } + v->freq++; + if (v->vid) { + vp = &v->car; + } else { + break; + } + } + } + } + { + grn_set *th = grn_set_open(sizeof(grn_id), sizeof(int), 0); + if (!th) { return GRN_NO_MEMORY_AVAILABLE; } + if (t0 == b->tvp) { GRN_LOG(ctx, GRN_LOG_DEBUG, "t0 == tvp"); } + for (t0 = b->tvs; t0 < b->tvp; t0++) { + grn_id vid, vid0 = *t0, vid1 = 0; + grn_vgram_vnode *v, *v2 = NULL, **vp; + if (grn_set_at(terms, t0, (void **) &u)) { + vp = &(*u)->vnodes; + for (tn = t0 + 1; tn < b->tvp; tn++) { + for (v = *vp; v; v = v->cdr) { + if (!v->vid && (v->freq < 2 || v->freq * v->len < 4)) { + *vp = v->cdr; + v->freq = 0; + } + if (v->tid == *tn) { break; } + vp = &v->cdr; + } + if (v) { + if (v->freq) { + v2 = v; + vid1 = vid0; + vid0 = v->vid; + } + if (v->vid) { + vp = &v->car; + continue; + } + } + break; + } + } + if (v2) { + if (!v2->vid) { + vgram_key key; + key.vid = vid1; + key.tid = v2->tid; + if (!(v2->vid = grn_sym_get(vgram->vgram, (char *)&key))) { + grn_set_close(th); + return GRN_NO_MEMORY_AVAILABLE; + } + } + vid = *t0 = v2->vid * 2 + 1; + memset(t0 + 1, 0, sizeof(grn_id) * v2->len); + t0 += v2->len; + } else { + vid = *t0 *= 2; + } + { + int *tf; + if (!grn_set_get(th, &vid, (void **) &tf)) { + grn_set_close(th); + return GRN_NO_MEMORY_AVAILABLE; + } + (*tf)++; + } + } + if (!th->n_entries) { GRN_LOG(ctx, GRN_LOG_DEBUG, "th->n_entries == 0"); } + { + int j = 0; + int skip = 0; + grn_set_eh *ehs, *ehp, *ehe; + grn_set_sort_optarg arg; + uint8_t *ps = GRN_MALLOC(b->len * 2), *pp, *pe; + if (!ps) { + grn_set_close(th); + return GRN_NO_MEMORY_AVAILABLE; + } + pp = ps; + pe = ps + b->len * 2; + arg.mode = grn_sort_descending; + arg.compar = NULL; + arg.compar_arg = (void *)(intptr_t)sizeof(grn_id); + ehs = grn_set_sort(th, 0, &arg); + if (!ehs) { + GRN_FREE(ps); + grn_set_close(th); + return GRN_NO_MEMORY_AVAILABLE; + } + GRN_B_ENC(th->n_entries, pp); + for (ehp = ehs, ehe = ehs + th->n_entries; ehp < ehe; ehp++, j++) { + int *id = (int *)GRN_SET_INTVAL(*ehp); + GRN_B_ENC(*GRN_SET_INTKEY(*ehp), pp); + *id = j; + } + for (t0 = b->tvs; t0 < b->tvp; t0++) { + if (*t0) { + int *id; + if (!grn_set_at(th, t0, (void **) &id)) { + GRN_LOG(ctx, GRN_LOG_ERROR, "lookup error (%d)", *t0); + } + GRN_B_ENC(*id, pp); + } else { + skip++; + } + } + len_sum += b->len; + img_sum += pp - ps; + skip_sum += skip; + GRN_FREE(ehs); + GRN_FREE(ps); + } + grn_set_close(th); + } + } + return GRN_SUCCESS; +} + +grn_rc +grn_vgram_buf_close(grn_vgram_buf *b) +{ + if (!b) { return GRN_INVALID_ARGUMENT; } + if (b->tvs) { GRN_FREE(b->tvs); } + if (b->vps) { GRN_FREE(b->vps); } + GRN_FREE(b); + return GRN_SUCCESS; +} + +grn_rc +grn_vgram_close(grn_vgram *vgram) +{ + if (!vgram) { return GRN_INVALID_ARGUMENT; } + GRN_LOG(ctx, GRN_LOG_DEBUG, "len=%d img=%d skip=%d simple=%d", len_sum, img_sum, skip_sum, simple_sum); + grn_sym_close(vgram->vgram); + GRN_FREE(vgram); + return GRN_SUCCESS; +} +*/ diff --git a/storage/mroonga/vendor/groonga/lib/str.c b/storage/mroonga/vendor/groonga/lib/str.c new file mode 100644 index 00000000..4f0a3a98 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/str.c @@ -0,0 +1,3276 @@ +/* -*- c-basic-offset: 2 -*- */ +/* Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include +#include +#include +#include "grn_db.h" +#include "grn_str.h" +#include "grn_nfkc.h" + +#ifndef _ISOC99_SOURCE +#define _ISOC99_SOURCE +#endif /* _ISOC99_SOURCE */ +#include + +#if defined(HAVE__GMTIME64_S) && defined(__GNUC__) +# ifdef _WIN64 +# define gmtime_s(tm, time) _gmtime64_s(tm, time) +# else /* _WIN64 */ +# define gmtime_s(tm, time) _gmtime32_s(tm, time) +# endif /* _WIN64 */ +#endif /* defined(HAVE__GMTIME64_S) && defined(__GNUC__) */ + +inline static int +grn_str_charlen_utf8(grn_ctx *ctx, const unsigned char *str, const unsigned char *end) +{ + /* MEMO: This function allows non-null-terminated string as str. */ + /* But requires the end of string. */ + if (end <= str || !*str) { + return 0; + } + if (*str & 0x80) { + int i; + int len; + GRN_BIT_SCAN_REV(~(((uint) *str) << 24), len); + len = 31 - len; + if ((unsigned int)(len - 2) >= 3) { /* (len == 1 || len >= 5) */ + GRN_LOG(ctx, GRN_LOG_WARNING, + "grn_str_charlen_utf8(): first byte is invalid"); + return 0; + } + if (str + len > end) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "grn_str_charlen_utf8(): incomplete character"); + return 0; + } + for (i = 1; i < len; ++i) { + if ((str[i] & 0xc0) != 0x80) { + GRN_LOG(ctx, GRN_LOG_WARNING, + "grn_str_charlen_utf8(): <%d>th byte is invalid", + i + 1); + return 0; + } + } + return len; + } else { + return 1; + } +} + +unsigned int +grn_str_charlen(grn_ctx *ctx, const char *str, grn_encoding encoding) +{ + /* MEMO: This function requires null-terminated string as str.*/ + unsigned char *p = (unsigned char *) str; + if (!*p) { return 0; } + switch (encoding) { + case GRN_ENC_EUC_JP : + if (*p & 0x80) { + if (*(p + 1)) { + return 2; + } else { + /* This is invalid character */ + GRN_LOG(ctx, GRN_LOG_WARNING, "invalid euc-jp string end on grn_str_charlen"); + return 0; + } + } + return 1; + case GRN_ENC_UTF8 : + if (*p & 0x80) { + int b, w; + size_t size; + for (b = 0x40, w = 0; b && (*p & b); b >>= 1, w++); + if (!w) { + GRN_LOG(ctx, GRN_LOG_WARNING, "invalid utf8 string(1) on grn_str_charlen"); + return 0; + } + for (size = 1; w--; size++) { + if (!*++p || (*p & 0xc0) != 0x80) { + GRN_LOG(ctx, GRN_LOG_WARNING, "invalid utf8 string(2) on grn_str_charlen"); + return 0; + } + } + return size; + } else { + return 1; + } + case GRN_ENC_SJIS : + if (*p & 0x80) { + /* we regard 0xa0 as JIS X 0201 KANA. adjusted to other tools. */ + if (0xa0 <= *p && *p <= 0xdf) { + /* hankaku-kana */ + return 1; + } else if (!(*(p + 1))) { + /* This is invalid character */ + GRN_LOG(ctx, GRN_LOG_WARNING, "invalid sjis string end on grn_str_charlen"); + return 0; + } else { + return 2; + } + } else { + return 1; + } + default : + return 1; + } + return 0; +} + +int +grn_charlen_(grn_ctx *ctx, const char *str, const char *end, grn_encoding encoding) +{ + /* MEMO: This function allows non-null-terminated string as str. */ + /* But requires the end of string. */ + unsigned char *p = (unsigned char *) str; + if (p >= (unsigned char *)end) { return 0; } + switch (encoding) { + case GRN_ENC_EUC_JP : + if (*p & 0x80) { + if ((p + 1) < (unsigned char *)end) { + return 2; + } else { + /* This is invalid character */ + GRN_LOG(ctx, GRN_LOG_WARNING, "invalid euc-jp string end on grn_charlen"); + return 0; + } + } + return 1; + case GRN_ENC_UTF8 : + return grn_str_charlen_utf8(ctx, p, (unsigned char *)end); + case GRN_ENC_SJIS : + if (*p & 0x80) { + /* we regard 0xa0 as JIS X 0201 KANA. adjusted to other tools. */ + if (0xa0 <= *p && *p <= 0xdf) { + /* hankaku-kana */ + return 1; + } else if (++p >= (unsigned char *)end) { + /* This is invalid character */ + GRN_LOG(ctx, GRN_LOG_WARNING, "invalid sjis string end on grn_charlen"); + return 0; + } else { + return 2; + } + } else { + return 1; + } + default : + return 1; + } + return 0; +} + +int +grn_charlen(grn_ctx *ctx, const char *str, const char *end) +{ + return grn_charlen_(ctx, str, end, ctx->encoding); +} + +static unsigned char symbol[] = { + ',', '.', 0, ':', ';', '?', '!', 0, 0, 0, '`', 0, '^', '~', '_', 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, '-', '-', '/', '\\', 0, 0, '|', 0, 0, 0, '\'', 0, + '"', '(', ')', 0, 0, '[', ']', '{', '}', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '+', '-', 0, 0, 0, '=', 0, '<', '>', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + '$', 0, 0, '%', '#', '&', '*', '@', 0, 0, 0, 0, 0, 0, 0, 0 +}; + +inline static grn_rc +normalize_euc(grn_ctx *ctx, grn_str *nstr) +{ + static uint16_t hankana[] = { + 0xa1a1, 0xa1a3, 0xa1d6, 0xa1d7, 0xa1a2, 0xa1a6, 0xa5f2, 0xa5a1, 0xa5a3, + 0xa5a5, 0xa5a7, 0xa5a9, 0xa5e3, 0xa5e5, 0xa5e7, 0xa5c3, 0xa1bc, 0xa5a2, + 0xa5a4, 0xa5a6, 0xa5a8, 0xa5aa, 0xa5ab, 0xa5ad, 0xa5af, 0xa5b1, 0xa5b3, + 0xa5b5, 0xa5b7, 0xa5b9, 0xa5bb, 0xa5bd, 0xa5bf, 0xa5c1, 0xa5c4, 0xa5c6, + 0xa5c8, 0xa5ca, 0xa5cb, 0xa5cc, 0xa5cd, 0xa5ce, 0xa5cf, 0xa5d2, 0xa5d5, + 0xa5d8, 0xa5db, 0xa5de, 0xa5df, 0xa5e0, 0xa5e1, 0xa5e2, 0xa5e4, 0xa5e6, + 0xa5e8, 0xa5e9, 0xa5ea, 0xa5eb, 0xa5ec, 0xa5ed, 0xa5ef, 0xa5f3, 0xa1ab, + 0xa1eb + }; + static unsigned char dakuten[] = { + 0xf4, 0, 0, 0, 0, 0xac, 0, 0xae, 0, 0xb0, 0, 0xb2, 0, 0xb4, 0, 0xb6, 0, + 0xb8, 0, 0xba, 0, 0xbc, 0, 0xbe, 0, 0xc0, 0, 0xc2, 0, 0, 0xc5, 0, 0xc7, + 0, 0xc9, 0, 0, 0, 0, 0, 0, 0xd0, 0, 0, 0xd3, 0, 0, 0xd6, 0, 0, 0xd9, 0, + 0, 0xdc + }; + static unsigned char handaku[] = { + 0xd1, 0, 0, 0xd4, 0, 0, 0xd7, 0, 0, 0xda, 0, 0, 0xdd + }; + int16_t *ch; + const unsigned char *s, *s_, *e; + unsigned char *d, *d0, *d_, b; + uint_least8_t *cp, *ctypes, ctype; + size_t size = nstr->orig_blen, length = 0; + int removeblankp = nstr->flags & GRN_STR_REMOVEBLANK; + if (!(nstr->norm = GRN_MALLOC(size * 2 + 1))) { + return GRN_NO_MEMORY_AVAILABLE; + } + d0 = (unsigned char *) nstr->norm; + if (nstr->flags & GRN_STR_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * 2 * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->norm); + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STR_WITH_CTYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->norm); + nstr->checks = NULL; + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->orig + size; + for (s = s_ = (unsigned char *) nstr->orig, d = d_ = d0; s < e; s++) { + if ((*s & 0x80)) { + if (((s + 1) < e) && (*(s + 1) & 0x80)) { + unsigned char c1 = *s++, c2 = *s, c3 = 0; + switch (c1 >> 4) { + case 0x08 : + if (c1 == 0x8e && 0xa0 <= c2 && c2 <= 0xdf) { + uint16_t c = hankana[c2 - 0xa0]; + switch (c) { + case 0xa1ab : + if (d > d0 + 1 && d[-2] == 0xa5 + && 0xa6 <= d[-1] && d[-1] <= 0xdb && (b = dakuten[d[-1] - 0xa6])) { + *(d - 1) = b; + if (ch) { ch[-1] += 2; s_ += 2; } + continue; + } else { + *d++ = c >> 8; *d = c & 0xff; + } + break; + case 0xa1eb : + if (d > d0 + 1 && d[-2] == 0xa5 + && 0xcf <= d[-1] && d[-1] <= 0xdb && (b = handaku[d[-1] - 0xcf])) { + *(d - 1) = b; + if (ch) { ch[-1] += 2; s_ += 2; } + continue; + } else { + *d++ = c >> 8; *d = c & 0xff; + } + break; + default : + *d++ = c >> 8; *d = c & 0xff; + break; + } + ctype = GRN_CHAR_KATAKANA; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + } + break; + case 0x09 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + break; + case 0x0a : + switch (c1 & 0x0f) { + case 1 : + switch (c2) { + case 0xbc : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KATAKANA; + break; + case 0xb9 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KANJI; + break; + case 0xa1 : + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_STR_BLANK|GRN_CHAR_SYMBOL; + } + break; + default : + if (c2 >= 0xa4 && (c3 = symbol[c2 - 0xa4])) { + *d = c3; + ctype = GRN_CHAR_SYMBOL; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + } + break; + } + break; + case 2 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_SYMBOL; + break; + case 3 : + c3 = c2 - 0x80; + if ('a' <= c3 && c3 <= 'z') { + ctype = GRN_CHAR_ALPHA; + *d = c3; + } else if ('A' <= c3 && c3 <= 'Z') { + ctype = GRN_CHAR_ALPHA; + *d = c3 + 0x20; + } else if ('0' <= c3 && c3 <= '9') { + ctype = GRN_CHAR_DIGIT; + *d = c3; + } else { + ctype = GRN_CHAR_OTHERS; + *d++ = c1; *d = c2; + } + break; + case 4 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_HIRAGANA; + break; + case 5 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KATAKANA; + break; + case 6 : + case 7 : + case 8 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_SYMBOL; + break; + default : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + break; + } + break; + default : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KANJI; + break; + } + } else { + /* skip invalid character */ + continue; + } + } else { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_STR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->length = length; + nstr->norm_blen = (size_t)(d - (unsigned char *)nstr->norm); + return GRN_SUCCESS; +} + +#ifdef GRN_WITH_NFKC +inline static grn_rc +normalize_utf8(grn_ctx *ctx, grn_str *nstr) +{ + int16_t *ch; + const unsigned char *s, *s_, *s__ = NULL, *p, *p2, *pe, *e; + unsigned char *d, *d_, *de; + uint_least8_t *cp; + size_t length = 0, ls, lp, size = nstr->orig_blen, ds = size * 3; + int removeblankp = nstr->flags & GRN_STR_REMOVEBLANK; + if (!(nstr->norm = GRN_MALLOC(ds + 1))) { + return GRN_NO_MEMORY_AVAILABLE; + } + if (nstr->flags & GRN_STR_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(ds * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->norm); nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STR_WITH_CTYPES) { + if (!(nstr->ctypes = GRN_MALLOC(ds + 1))) { + if (nstr->checks) { GRN_FREE(nstr->checks); nstr->checks = NULL; } + GRN_FREE(nstr->norm); nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + cp = nstr->ctypes; + d = (unsigned char *)nstr->norm; + de = d + ds; + d_ = NULL; + e = (unsigned char *)nstr->orig + size; + for (s = s_ = (unsigned char *)nstr->orig; ; s += ls) { + if (!(ls = grn_str_charlen_utf8(ctx, s, e))) { + break; + } + if ((p = (unsigned char *)grn_nfkc_decompose(s))) { + pe = p + strlen((char *)p); + } else { + p = s; + pe = p + ls; + } + if (d_ && (p2 = (unsigned char *)grn_nfkc_compose(d_, p))) { + p = p2; + pe = p + strlen((char *)p); + if (cp) { cp--; } + if (ch) { + ch -= (d - d_); + s_ = s__; + } + d = d_; + length--; + } + for (; ; p += lp) { + if (!(lp = grn_str_charlen_utf8(ctx, p, pe))) { + break; + } + if ((*p == ' ' && removeblankp) || *p < 0x20 /* skip unprintable ascii */ ) { + if (cp > nstr->ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + } else { + if (de <= d + lp) { + unsigned char *norm; + ds += (ds >> 1) + lp; + if (!(norm = GRN_REALLOC(nstr->norm, ds + 1))) { + if (nstr->ctypes) { GRN_FREE(nstr->ctypes); nstr->ctypes = NULL; } + if (nstr->checks) { GRN_FREE(nstr->checks); nstr->checks = NULL; } + GRN_FREE(nstr->norm); nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + de = norm + ds; + d = norm + (d - (unsigned char *)nstr->norm); + nstr->norm = (char *)norm; + if (ch) { + int16_t *checks; + if (!(checks = GRN_REALLOC(nstr->checks, ds * sizeof(int16_t)+ 1))) { + if (nstr->ctypes) { GRN_FREE(nstr->ctypes); nstr->ctypes = NULL; } + GRN_FREE(nstr->checks); nstr->checks = NULL; + GRN_FREE(nstr->norm); nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + ch = checks + (ch - nstr->checks); + nstr->checks = checks; + } + if (cp) { + uint_least8_t *ctypes; + if (!(ctypes = GRN_REALLOC(nstr->ctypes, ds + 1))) { + GRN_FREE(nstr->ctypes); nstr->ctypes = NULL; + if (nstr->checks) { GRN_FREE(nstr->checks); nstr->checks = NULL; } + GRN_FREE(nstr->norm); nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + cp = ctypes + (cp - nstr->ctypes); + nstr->ctypes = ctypes; + } + } + grn_memcpy(d, p, lp); + d_ = d; + d += lp; + length++; + if (cp) { *cp++ = grn_nfkc_char_type(p); } + if (ch) { + size_t i; + if (s_ == s + ls) { + *ch++ = -1; + } else { + *ch++ = (int16_t)(s + ls - s_); + s__ = s_; + s_ = s + ls; + } + for (i = lp; i > 1; i--) { *ch++ = 0; } + } + } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->length = length; + nstr->norm_blen = (size_t)(d - (unsigned char *)nstr->norm); + return GRN_SUCCESS; +} +#endif /* GRN_WITH_NFKC */ + +inline static grn_rc +normalize_sjis(grn_ctx *ctx, grn_str *nstr) +{ + static uint16_t hankana[] = { + 0x8140, 0x8142, 0x8175, 0x8176, 0x8141, 0x8145, 0x8392, 0x8340, 0x8342, + 0x8344, 0x8346, 0x8348, 0x8383, 0x8385, 0x8387, 0x8362, 0x815b, 0x8341, + 0x8343, 0x8345, 0x8347, 0x8349, 0x834a, 0x834c, 0x834e, 0x8350, 0x8352, + 0x8354, 0x8356, 0x8358, 0x835a, 0x835c, 0x835e, 0x8360, 0x8363, 0x8365, + 0x8367, 0x8369, 0x836a, 0x836b, 0x836c, 0x836d, 0x836e, 0x8371, 0x8374, + 0x8377, 0x837a, 0x837d, 0x837e, 0x8380, 0x8381, 0x8382, 0x8384, 0x8386, + 0x8388, 0x8389, 0x838a, 0x838b, 0x838c, 0x838d, 0x838f, 0x8393, 0x814a, + 0x814b + }; + static unsigned char dakuten[] = { + 0x94, 0, 0, 0, 0, 0x4b, 0, 0x4d, 0, 0x4f, 0, 0x51, 0, 0x53, 0, 0x55, 0, + 0x57, 0, 0x59, 0, 0x5b, 0, 0x5d, 0, 0x5f, 0, 0x61, 0, 0, 0x64, 0, 0x66, + 0, 0x68, 0, 0, 0, 0, 0, 0, 0x6f, 0, 0, 0x72, 0, 0, 0x75, 0, 0, 0x78, 0, + 0, 0x7b + }; + static unsigned char handaku[] = { + 0x70, 0, 0, 0x73, 0, 0, 0x76, 0, 0, 0x79, 0, 0, 0x7c + }; + int16_t *ch; + const unsigned char *s, *s_; + unsigned char *d, *d0, *d_, b, *e; + uint_least8_t *cp, *ctypes, ctype; + size_t size = nstr->orig_blen, length = 0; + int removeblankp = nstr->flags & GRN_STR_REMOVEBLANK; + if (!(nstr->norm = GRN_MALLOC(size * 2 + 1))) { + return GRN_NO_MEMORY_AVAILABLE; + } + d0 = (unsigned char *) nstr->norm; + if (nstr->flags & GRN_STR_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * 2 * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->norm); + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STR_WITH_CTYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->norm); + nstr->checks = NULL; + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->orig + size; + for (s = s_ = (unsigned char *) nstr->orig, d = d_ = d0; s < e; s++) { + if ((*s & 0x80)) { + if (0xa0 <= *s && *s <= 0xdf) { + uint16_t c = hankana[*s - 0xa0]; + switch (c) { + case 0x814a : + if (d > d0 + 1 && d[-2] == 0x83 + && 0x45 <= d[-1] && d[-1] <= 0x7a && (b = dakuten[d[-1] - 0x45])) { + *(d - 1) = b; + if (ch) { ch[-1]++; s_++; } + continue; + } else { + *d++ = c >> 8; *d = c & 0xff; + } + break; + case 0x814b : + if (d > d0 + 1 && d[-2] == 0x83 + && 0x6e <= d[-1] && d[-1] <= 0x7a && (b = handaku[d[-1] - 0x6e])) { + *(d - 1) = b; + if (ch) { ch[-1]++; s_++; } + continue; + } else { + *d++ = c >> 8; *d = c & 0xff; + } + break; + default : + *d++ = c >> 8; *d = c & 0xff; + break; + } + ctype = GRN_CHAR_KATAKANA; + } else { + if ((s + 1) < e && 0x40 <= *(s + 1) && *(s + 1) <= 0xfc) { + unsigned char c1 = *s++, c2 = *s, c3 = 0; + if (0x81 <= c1 && c1 <= 0x87) { + switch (c1 & 0x0f) { + case 1 : + switch (c2) { + case 0x5b : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KATAKANA; + break; + case 0x58 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KANJI; + break; + case 0x40 : + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_STR_BLANK|GRN_CHAR_SYMBOL; + } + break; + default : + if (0x43 <= c2 && c2 <= 0x7e && (c3 = symbol[c2 - 0x43])) { + *d = c3; + ctype = GRN_CHAR_SYMBOL; + } else if (0x7f <= c2 && c2 <= 0x97 && (c3 = symbol[c2 - 0x44])) { + *d = c3; + ctype = GRN_CHAR_SYMBOL; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + } + break; + } + break; + case 2 : + c3 = c2 - 0x1f; + if (0x4f <= c2 && c2 <= 0x58) { + ctype = GRN_CHAR_DIGIT; + *d = c2 - 0x1f; + } else if (0x60 <= c2 && c2 <= 0x79) { + ctype = GRN_CHAR_ALPHA; + *d = c2 + 0x01; + } else if (0x81 <= c2 && c2 <= 0x9a) { + ctype = GRN_CHAR_ALPHA; + *d = c2 - 0x20; + } else if (0x9f <= c2 && c2 <= 0xf1) { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_HIRAGANA; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + } + break; + case 3 : + if (0x40 <= c2 && c2 <= 0x96) { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KATAKANA; + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 4 : + case 7 : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_SYMBOL; + break; + default : + *d++ = c1; *d = c2; + ctype = GRN_CHAR_OTHERS; + break; + } + } else { + *d++ = c1; *d = c2; + ctype = GRN_CHAR_KANJI; + } + } else { + /* skip invalid character */ + continue; + } + } + } else { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_STR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->length = length; + nstr->norm_blen = (size_t)(d - (unsigned char *)nstr->norm); + return GRN_SUCCESS; +} + +inline static grn_rc +normalize_none(grn_ctx *ctx, grn_str *nstr) +{ + int16_t *ch; + const unsigned char *s, *s_, *e; + unsigned char *d, *d0, *d_; + uint_least8_t *cp, *ctypes, ctype; + size_t size = nstr->orig_blen, length = 0; + int removeblankp = nstr->flags & GRN_STR_REMOVEBLANK; + if (!(nstr->norm = GRN_MALLOC(size + 1))) { + return GRN_NO_MEMORY_AVAILABLE; + } + d0 = (unsigned char *) nstr->norm; + if (nstr->flags & GRN_STR_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->norm); + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STR_WITH_CTYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->norm); + nstr->checks = NULL; + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->orig + size; + for (s = s_ = (unsigned char *) nstr->orig, d = d_ = d0; s < e; s++) { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_STR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->length = length; + nstr->norm_blen = (size_t)(d - (unsigned char *)nstr->norm); + return GRN_SUCCESS; +} + +/* use cp1252 as latin1 */ +inline static grn_rc +normalize_latin1(grn_ctx *ctx, grn_str *nstr) +{ + int16_t *ch; + const unsigned char *s, *s_, *e; + unsigned char *d, *d0, *d_; + uint_least8_t *cp, *ctypes, ctype; + size_t size = nstr->orig_blen, length = 0; + int removeblankp = nstr->flags & GRN_STR_REMOVEBLANK; + if (!(nstr->norm = GRN_MALLOC(size + 1))) { + return GRN_NO_MEMORY_AVAILABLE; + } + d0 = (unsigned char *) nstr->norm; + if (nstr->flags & GRN_STR_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->norm); + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STR_WITH_CTYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->norm); + nstr->checks = NULL; + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->orig + size; + for (s = s_ = (unsigned char *) nstr->orig, d = d_ = d0; s < e; s++) { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_STR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + case 8 : + if (c == 0x8a || c == 0x8c || c == 0x8e) { + *d = c + 0x10; + ctype = GRN_CHAR_ALPHA; + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 9 : + if (c == 0x9a || c == 0x9c || c == 0x9e || c == 0x9f) { + *d = (c == 0x9f) ? c + 0x60 : c; + ctype = GRN_CHAR_ALPHA; + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 0x0c : + *d = c + 0x20; + ctype = GRN_CHAR_ALPHA; + break; + case 0x0d : + *d = (c == 0xd7 || c == 0xdf) ? c : c + 0x20; + ctype = (c == 0xd7) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 0x0e : + *d = c; + ctype = GRN_CHAR_ALPHA; + break; + case 0x0f : + *d = c; + ctype = (c == 0xf7) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->length = length; + nstr->norm_blen = (size_t)(d - (unsigned char *)nstr->norm); + return GRN_SUCCESS; +} + +inline static grn_rc +normalize_koi8r(grn_ctx *ctx, grn_str *nstr) +{ + int16_t *ch; + const unsigned char *s, *s_, *e; + unsigned char *d, *d0, *d_; + uint_least8_t *cp, *ctypes, ctype; + size_t size = strlen(nstr->orig), length = 0; + int removeblankp = nstr->flags & GRN_STR_REMOVEBLANK; + if (!(nstr->norm = GRN_MALLOC(size + 1))) { + return GRN_NO_MEMORY_AVAILABLE; + } + d0 = (unsigned char *) nstr->norm; + if (nstr->flags & GRN_STR_WITH_CHECKS) { + if (!(nstr->checks = GRN_MALLOC(size * sizeof(int16_t) + 1))) { + GRN_FREE(nstr->norm); + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + ch = nstr->checks; + if (nstr->flags & GRN_STR_WITH_CTYPES) { + if (!(nstr->ctypes = GRN_MALLOC(size + 1))) { + GRN_FREE(nstr->checks); + GRN_FREE(nstr->norm); + nstr->checks = NULL; + nstr->norm = NULL; + return GRN_NO_MEMORY_AVAILABLE; + } + } + cp = ctypes = nstr->ctypes; + e = (unsigned char *)nstr->orig + size; + for (s = s_ = (unsigned char *) nstr->orig, d = d_ = d0; s < e; s++) { + unsigned char c = *s; + switch (c >> 4) { + case 0 : + case 1 : + /* skip unprintable ascii */ + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + case 2 : + if (c == 0x20) { + if (removeblankp) { + if (cp > ctypes) { *(cp - 1) |= GRN_STR_BLANK; } + continue; + } else { + *d = ' '; + ctype = GRN_STR_BLANK|GRN_CHAR_SYMBOL; + } + } else { + *d = c; + ctype = GRN_CHAR_SYMBOL; + } + break; + case 3 : + *d = c; + ctype = (c <= 0x39) ? GRN_CHAR_DIGIT : GRN_CHAR_SYMBOL; + break; + case 4 : + *d = ('A' <= c) ? c + 0x20 : c; + ctype = (c == 0x40) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 5 : + *d = (c <= 'Z') ? c + 0x20 : c; + ctype = (c <= 0x5a) ? GRN_CHAR_ALPHA : GRN_CHAR_SYMBOL; + break; + case 6 : + *d = c; + ctype = (c == 0x60) ? GRN_CHAR_SYMBOL : GRN_CHAR_ALPHA; + break; + case 7 : + *d = c; + ctype = (c <= 0x7a) ? GRN_CHAR_ALPHA : (c == 0x7f ? GRN_CHAR_OTHERS : GRN_CHAR_SYMBOL); + break; + case 0x0a : + *d = c; + ctype = (c == 0xa3) ? GRN_CHAR_ALPHA : GRN_CHAR_OTHERS; + break; + case 0x0b : + if (c == 0xb3) { + *d = c - 0x10; + ctype = GRN_CHAR_ALPHA; + } else { + *d = c; + ctype = GRN_CHAR_OTHERS; + } + break; + case 0x0c : + case 0x0d : + *d = c; + ctype = GRN_CHAR_ALPHA; + break; + case 0x0e : + case 0x0f : + *d = c - 0x20; + ctype = GRN_CHAR_ALPHA; + break; + default : + *d = c; + ctype = GRN_CHAR_OTHERS; + break; + } + d++; + length++; + if (cp) { *cp++ = ctype; } + if (ch) { + *ch++ = (int16_t)(s + 1 - s_); + s_ = s + 1; + while (++d_ < d) { *ch++ = 0; } + } + } + if (cp) { *cp = GRN_CHAR_NULL; } + *d = '\0'; + nstr->length = length; + nstr->norm_blen = (size_t)(d - (unsigned char *)nstr->norm); + return GRN_SUCCESS; +} + +static grn_str * +grn_fakenstr_open(grn_ctx *ctx, const char *str, size_t str_len, grn_encoding encoding, int flags) +{ + /* TODO: support GRN_STR_REMOVEBLANK flag and ctypes */ + grn_str *nstr; + if (!(nstr = GRN_MALLOC(sizeof(grn_str)))) { + GRN_LOG(ctx, GRN_LOG_ALERT, "memory allocation on grn_fakenstr_open failed !"); + return NULL; + } + if (!(nstr->norm = GRN_MALLOC(str_len + 1))) { + GRN_LOG(ctx, GRN_LOG_ALERT, "memory allocation for keyword on grn_snip_add_cond failed !"); + GRN_FREE(nstr); + return NULL; + } + nstr->orig = str; + nstr->orig_blen = str_len; + grn_memcpy(nstr->norm, str, str_len); + nstr->norm[str_len] = '\0'; + nstr->norm_blen = str_len; + nstr->ctypes = NULL; + nstr->flags = flags; + + if (flags & GRN_STR_WITH_CHECKS) { + int16_t f = 0; + unsigned char c; + size_t i; + if (!(nstr->checks = (int16_t *) GRN_MALLOC(sizeof(int16_t) * str_len))) { + GRN_FREE(nstr->norm); + GRN_FREE(nstr); + return NULL; + } + switch (encoding) { + case GRN_ENC_EUC_JP: + for (i = 0; i < str_len; i++) { + if (!f) { + c = (unsigned char) str[i]; + f = ((c >= 0xa1U && c <= 0xfeU) || c == 0x8eU ? 2 : (c == 0x8fU ? 3 : 1) + ); + nstr->checks[i] = f; + } else { + nstr->checks[i] = 0; + } + f--; + } + break; + case GRN_ENC_SJIS: + for (i = 0; i < str_len; i++) { + if (!f) { + c = (unsigned char) str[i]; + f = (c >= 0x81U && ((c <= 0x9fU) || (c >= 0xe0U && c <= 0xfcU)) ? 2 : 1); + nstr->checks[i] = f; + } else { + nstr->checks[i] = 0; + } + f--; + } + break; + case GRN_ENC_UTF8: + for (i = 0; i < str_len; i++) { + if (!f) { + c = (unsigned char) str[i]; + f = (c & 0x80U ? (c & 0x20U ? (c & 0x10U ? 4 : 3) + : 2) + : 1); + nstr->checks[i] = f; + } else { + nstr->checks[i] = 0; + } + f--; + } + break; + default: + for (i = 0; i < str_len; i++) { + nstr->checks[i] = 1; + } + break; + } + } else { + nstr->checks = NULL; + } + return nstr; +} + +grn_str * +grn_str_open_(grn_ctx *ctx, const char *str, unsigned int str_len, int flags, grn_encoding encoding) +{ + grn_rc rc; + grn_str *nstr; + if (!str || !str_len) { return NULL; } + + if (!(flags & GRN_STR_NORMALIZE)) { + return grn_fakenstr_open(ctx, str, str_len, encoding, flags); + } + + if (!(nstr = GRN_MALLOC(sizeof(grn_str)))) { + GRN_LOG(ctx, GRN_LOG_ALERT, "memory allocation on grn_str_open failed !"); + return NULL; + } + nstr->orig = str; + nstr->orig_blen = str_len; + nstr->norm = NULL; + nstr->norm_blen = 0; + nstr->checks = NULL; + nstr->ctypes = NULL; + nstr->encoding = encoding; + nstr->flags = flags; + switch (encoding) { + case GRN_ENC_EUC_JP : + rc = normalize_euc(ctx, nstr); + break; + case GRN_ENC_UTF8 : +#ifdef GRN_WITH_NFKC + rc = normalize_utf8(ctx, nstr); +#else /* GRN_WITH_NFKC */ + rc = normalize_none(ctx, nstr); +#endif /* GRN_WITH_NFKC */ + break; + case GRN_ENC_SJIS : + rc = normalize_sjis(ctx, nstr); + break; + case GRN_ENC_LATIN1 : + rc = normalize_latin1(ctx, nstr); + break; + case GRN_ENC_KOI8R : + rc = normalize_koi8r(ctx, nstr); + break; + default : + rc = normalize_none(ctx, nstr); + break; + } + if (rc) { + grn_str_close(ctx, nstr); + return NULL; + } + return nstr; +} + +grn_str * +grn_str_open(grn_ctx *ctx, const char *str, unsigned int str_len, int flags) +{ + return grn_str_open_(ctx, str, str_len, flags, ctx->encoding); +} + +grn_rc +grn_str_close(grn_ctx *ctx, grn_str *nstr) +{ + if (nstr) { + if (nstr->norm) { GRN_FREE(nstr->norm); } + if (nstr->ctypes) { GRN_FREE(nstr->ctypes); } + if (nstr->checks) { GRN_FREE(nstr->checks); } + GRN_FREE(nstr); + return GRN_SUCCESS; + } else { + return GRN_INVALID_ARGUMENT; + } +} + +static const char *grn_enc_string[] = { + "default", + "none", + "euc_jp", + "utf8", + "sjis", + "latin1", + "koi8r" +}; + +const char * +grn_encoding_to_string(grn_encoding enc) +{ + if (enc < (sizeof(grn_enc_string) / sizeof(char *))) { + return grn_enc_string[enc]; + } else { + return "unknown"; + } +} + +grn_encoding +grn_encoding_parse(const char *str) +{ + grn_encoding e = GRN_ENC_UTF8; + int i = sizeof(grn_enc_string) / sizeof(grn_enc_string[0]); + while (i--) { + if (!strcmp(str, grn_enc_string[i])) { + e = (grn_encoding)i; + } + } + return e; +} + +size_t +grn_str_len(grn_ctx *ctx, const char *str, grn_encoding encoding, const char **last) +{ + size_t len, tlen; + const char *p = NULL; + for (len = 0; ; len++) { + p = str; + if (!(tlen = grn_str_charlen(ctx, str, encoding))) { + break; + } + str += tlen; + } + if (last) { *last = p; } + return len; +} + +int +grn_isspace(const char *str, grn_encoding encoding) +{ + const unsigned char *s = (const unsigned char *) str; + if (!s) { return 0; } + switch (s[0]) { + case ' ' : + case '\f' : + case '\n' : + case '\r' : + case '\t' : + case '\v' : + return 1; + case 0x81 : + if (encoding == GRN_ENC_SJIS && s[1] == 0x40) { return 2; } + break; + case 0xA1 : + if (encoding == GRN_ENC_EUC_JP && s[1] == 0xA1) { return 2; } + break; + case 0xE3 : + if (encoding == GRN_ENC_UTF8 && s[1] == 0x80 && s[2] == 0x80) { return 3; } + break; + default : + break; + } + return 0; +} + +int8_t +grn_atoi8(const char *nptr, const char *end, const char **rest) +{ + const char *p = nptr; + int8_t v = 0, t, n = 0, o = 0; + if (p < end && *p == '-') { + p++; + n = 1; + o = 1; + } + while (p < end && *p >= '0' && *p <= '9') { + t = v * 10 - (*p - '0'); + if (t > v || (!n && t == INT8_MIN)) { v = 0; break; } + v = t; + o = 0; + p++; + } + if (rest) { *rest = o ? nptr : p; } + return n ? v : -v; +} + +uint8_t +grn_atoui8(const char *nptr, const char *end, const char **rest) +{ + uint8_t v = 0, t; + while (nptr < end && *nptr >= '0' && *nptr <= '9') { + t = v * 10 + (*nptr - '0'); + if (t < v) { v = 0; break; } + v = t; + nptr++; + } + if (rest) { *rest = nptr; } + return v; +} + +int16_t +grn_atoi16(const char *nptr, const char *end, const char **rest) +{ + const char *p = nptr; + int16_t v = 0, t, n = 0, o = 0; + if (p < end && *p == '-') { + p++; + n = 1; + o = 1; + } + while (p < end && *p >= '0' && *p <= '9') { + t = v * 10 - (*p - '0'); + if (t > v || (!n && t == INT16_MIN)) { v = 0; break; } + v = t; + o = 0; + p++; + } + if (rest) { *rest = o ? nptr : p; } + return n ? v : -v; +} + +uint16_t +grn_atoui16(const char *nptr, const char *end, const char **rest) +{ + uint16_t v = 0, t; + while (nptr < end && *nptr >= '0' && *nptr <= '9') { + t = v * 10 + (*nptr - '0'); + if (t < v) { v = 0; break; } + v = t; + nptr++; + } + if (rest) { *rest = nptr; } + return v; +} + +int +grn_atoi(const char *nptr, const char *end, const char **rest) +{ + const char *p = nptr; + int v = 0, t, n = 0, o = 0; + if (p < end && *p == '-') { + p++; + n = 1; + o = 1; + } + while (p < end && *p >= '0' && *p <= '9') { + t = v * 10 - (*p - '0'); + if (t > v || (!n && t == INT32_MIN)) { v = 0; break; } + v = t; + o = 0; + p++; + } + if (rest) { *rest = o ? nptr : p; } + return n ? v : -v; +} + +unsigned int +grn_atoui(const char *nptr, const char *end, const char **rest) +{ + unsigned int v = 0, t; + while (nptr < end && *nptr >= '0' && *nptr <= '9') { + t = v * 10 + (*nptr - '0'); + if (t < v) { v = 0; break; } + v = t; + nptr++; + } + if (rest) { *rest = nptr; } + return v; +} + +int64_t +grn_atoll(const char *nptr, const char *end, const char **rest) +{ + const char *p = nptr; + int o = 0; + int64_t v = 0; + if (p < end && *p == '-') { + p++; + o = 1; + while (p < end && *p >= '0' && *p <= '9') { + int64_t t = v * 10 - (*p - '0'); + if (t > v) { v = 0; break; } + v = t; + o = 0; + p++; + } + } else { + while (p < end && *p >= '0' && *p <= '9') { + int64_t t = v * 10 + (*p - '0'); + if (t < v) { v = 0; break; } + v = t; + p++; + } + } + if (rest) { *rest = o ? nptr : p; } + return v; +} + +uint64_t +grn_atoull(const char *nptr, const char *end, const char **rest) +{ + uint64_t v = 0, t; + while (nptr < end && *nptr >= '0' && *nptr <= '9') { + t = v * 10 + (*nptr - '0'); + if (t < v) { v = 0; break; } + v = t; + nptr++; + } + if (rest) { *rest = nptr; } + return v; +} + +unsigned int +grn_htoui(const char *nptr, const char *end, const char **rest) +{ + unsigned int v = 0, t; + while (nptr < end) { + switch (*nptr) { + case '0' : + case '1' : + case '2' : + case '3' : + case '4' : + case '5' : + case '6' : + case '7' : + case '8' : + case '9' : + t = v * 16 + (*nptr++ - '0'); + break; + case 'a' : + case 'b' : + case 'c' : + case 'd' : + case 'e' : + case 'f' : + t = v * 16 + (*nptr++ - 'a') + 10; + break; + case 'A' : + case 'B' : + case 'C' : + case 'D' : + case 'E' : + case 'F' : + t = v * 16 + (*nptr++ - 'A') + 10; + break; + default : + v = 0; goto exit; + } + if (t < v) { v = 0; goto exit; } + v = t; + } +exit : + if (rest) { *rest = nptr; } + return v; +} + +void +grn_itoh(unsigned int i, char *p, unsigned int len) +{ + static const char *hex = "0123456789ABCDEF"; + p += len - 1; + while (len--) { + *p-- = hex[i & 0xf]; + i >>= 4; + } +} + +grn_rc +grn_itoa(int i, char *p, char *end, char **rest) +{ + char *q; + if (p >= end) { return GRN_INVALID_ARGUMENT; } + q = p; + if (i < 0) { + *p++ = '-'; + q = p; + if (i == INT_MIN) { + if (p >= end) { return GRN_INVALID_ARGUMENT; } + *p++ = (-(i % 10)) + '0'; + i /= 10; + } + i = -i; + } + do { + if (p >= end) { return GRN_INVALID_ARGUMENT; } + *p++ = i % 10 + '0'; + } while ((i /= 10) > 0); + if (rest) { *rest = p; } + for (p--; q < p; q++, p--) { + char t = *q; + *q = *p; + *p = t; + } + return GRN_SUCCESS; +} + +grn_rc +grn_itoa_padded(int i, char *p, char *end, char ch) +{ + char *q; + if (p >= end) { return GRN_INVALID_ARGUMENT; } + if (i < 0) { + *p++ = '-'; + if (i == INT_MIN) { + if (p >= end) { return GRN_INVALID_ARGUMENT; } + *p++ = (-(i % 10)) + '0'; + i /= 10; + } + i = -i; + } + q = end - 1; + do { + if (q < p) { return GRN_INVALID_ARGUMENT; } + *q-- = i % 10 + '0'; + } while ((i /= 10) > 0); + while (q >= p) { + *q-- = ch; + } + return GRN_SUCCESS; +} + +grn_rc +grn_lltoa(int64_t i, char *p, char *end, char **rest) +{ + char *q; + if (p >= end) { return GRN_INVALID_ARGUMENT; } + q = p; + if (i < 0) { + *p++ = '-'; + q = p; + if (i == INT64_MIN) { + *p++ = (-(i % 10)) + '0'; + i /= 10; + } + i = -i; + } + do { + if (p >= end) { return GRN_INVALID_ARGUMENT; } + *p++ = i % 10 + '0'; + } while ((i /= 10) > 0); + if (rest) { *rest = p; } + for (p--; q < p; q++, p--) { + char t = *q; + *q = *p; + *p = t; + } + return GRN_SUCCESS; +} + +grn_rc +grn_ulltoa(uint64_t i, char *p, char *end, char **rest) +{ + char *q; + if (p >= end) { return GRN_INVALID_ARGUMENT; } + q = p; + do { + if (p >= end) { return GRN_INVALID_ARGUMENT; } + *p++ = i % 10 + '0'; + } while ((i /= 10) > 0); + if (rest) { *rest = p; } + for (p--; q < p; q++, p--) { + char t = *q; + *q = *p; + *p = t; + } + return GRN_SUCCESS; +} + +#define I2B(i) \ + ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(i) & 0x3f]) + +#define B2I(b) \ + (((b) < '+' || 'z' < (b)) ? 0xff : "\x3e\xff\xff\xff\x3f\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\xff\xff\xff\xff\xff\xff\xff\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\xff\xff\xff\xff\xff\xff\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33"[(b) - '+']) + +#define MASK 0x34d34d34 + +char * +grn_itob(grn_id id, char *p) +{ + id ^= MASK; + *p++ = I2B(id >> 24); + *p++ = I2B(id >> 18); + *p++ = I2B(id >> 12); + *p++ = I2B(id >> 6); + *p++ = I2B(id); + return p; +} + +grn_id +grn_btoi(char *b) +{ + uint8_t i; + grn_id id = 0; + int len = 5; + while (len--) { + char c = *b++; + if ((i = B2I(c)) == 0xff) { return 0; } + id = (id << 6) + i; + } + return id ^ MASK; +} + +#define I2B32H(i) ("0123456789ABCDEFGHIJKLMNOPQRSTUV"[(i) & 0x1f]) + +char * +grn_lltob32h(int64_t i, char *p) +{ + uint64_t u = (uint64_t)i + 0x8000000000000000ULL; + *p++ = I2B32H(u >> 60); + *p++ = I2B32H(u >> 55); + *p++ = I2B32H(u >> 50); + *p++ = I2B32H(u >> 45); + *p++ = I2B32H(u >> 40); + *p++ = I2B32H(u >> 35); + *p++ = I2B32H(u >> 30); + *p++ = I2B32H(u >> 25); + *p++ = I2B32H(u >> 20); + *p++ = I2B32H(u >> 15); + *p++ = I2B32H(u >> 10); + *p++ = I2B32H(u >> 5); + *p++ = I2B32H(u); + return p; +} + +char * +grn_ulltob32h(uint64_t i, char *p) +{ + char lb = (i >> 59) & 0x10; + i += 0x8000000000000000ULL; + *p++ = lb + I2B32H(i >> 60); + *p++ = I2B32H(i >> 55); + *p++ = I2B32H(i >> 50); + *p++ = I2B32H(i >> 45); + *p++ = I2B32H(i >> 40); + *p++ = I2B32H(i >> 35); + *p++ = I2B32H(i >> 30); + *p++ = I2B32H(i >> 25); + *p++ = I2B32H(i >> 20); + *p++ = I2B32H(i >> 15); + *p++ = I2B32H(i >> 10); + *p++ = I2B32H(i >> 5); + *p++ = I2B32H(i); + return p; +} + +grn_rc +grn_aton(grn_ctx *ctx, const char *p, const char *end, const char **rest, + grn_obj *res) +{ + if (*p == '+') { + p++; + } + + switch (*p) { + case '-' : + case '0' : case '1' : case '2' : case '3' : case '4' : + case '5' : case '6' : case '7' : case '8' : case '9' : + { + int64_t int64; + char rest_char; + int64 = grn_atoll(p, end, rest); + rest_char = **rest; + if (end == *rest) { + if ((int64_t)INT32_MIN <= int64 && int64 <= (int64_t)INT32_MAX) { + grn_obj_reinit(ctx, res, GRN_DB_INT32, 0); + GRN_INT32_SET(ctx, res, int64); + } else if ((int64_t)INT32_MAX < int64 && int64 <= (int64_t)UINT32_MAX) { + grn_obj_reinit(ctx, res, GRN_DB_UINT32, 0); + GRN_UINT32_SET(ctx, res, int64); + } else { + grn_obj_reinit(ctx, res, GRN_DB_INT64, 0); + GRN_INT64_SET(ctx, res, int64); + } + } else { + if (*p != '-' && rest_char >= '0' && rest_char <= '9') { + uint64_t uint64 = grn_atoull(p, end, rest); + if (end == *rest) { + grn_obj_reinit(ctx, res, GRN_DB_UINT64, 0); + GRN_UINT64_SET(ctx, res, uint64); + } + } + if (end != *rest) { + if (rest_char == '.' || rest_char == 'e' || rest_char == 'E' || + (rest_char >= '0' && rest_char <= '9')) { + char *rest_float; + double d; + errno = 0; + d = strtod(p, &rest_float); + if (!errno && rest_float == end) { + grn_obj_reinit(ctx, res, GRN_DB_FLOAT, 0); + GRN_FLOAT_SET(ctx, res, d); + *rest = rest_float; + } else { + return GRN_INVALID_ARGUMENT; + } + } + } + } + } + break; + default : + return GRN_INVALID_ARGUMENT; + } + + return GRN_SUCCESS; +} + +int +grn_str_tok(const char *str, size_t str_len, char delim, const char **tokbuf, int buf_size, const char **rest) +{ + const char **tok = tokbuf, **tok_end = tokbuf + buf_size; + if (buf_size > 0) { + const char *str_end = str + str_len; + for (;;str++) { + if (str == str_end) { + *tok++ = str; + break; + } + if (delim == *str) { + // *str = '\0'; + *tok++ = str; + if (tok == tok_end) { break; } + } + } + } + if (rest) { *rest = str; } + return tok - tokbuf; +} + +inline static int +op_getopt_flag(int *flags, const grn_str_getopt_opt *o, + int argc, char * const argv[], int i, const char *optvalue) +{ + switch (o->op) { + case GETOPT_OP_NONE: + break; + case GETOPT_OP_ON: + *flags |= o->flag; + break; + case GETOPT_OP_OFF: + *flags &= ~o->flag; + break; + case GETOPT_OP_UPDATE: + *flags = o->flag; + break; + default: + return i; + } + if (o->arg) { + if (optvalue) { + *o->arg = (char *)optvalue; + } else if (++i < argc) { + *o->arg = argv[i]; + } else { + return -1; + } + } + return i; +} + +int +grn_str_getopt(int argc, char * const argv[], const grn_str_getopt_opt *opts, + int *flags) +{ + int i; + for (i = 1; i < argc; i++) { + const char * v = argv[i]; + if (*v == '-') { + const grn_str_getopt_opt *o; + int found; + if (*++v == '-') { + const char *eq; + size_t len; + found = 0; + v++; + for (eq = v; *eq != '\0' && *eq != '='; eq++) {} + len = eq - v; + for (o = opts; o->opt != '\0' || o->longopt != NULL; o++) { + if (o->longopt && strlen(o->longopt) == len && + !memcmp(v, o->longopt, len)) { + i = op_getopt_flag(flags, o, argc, argv, i, + (*eq == '\0' ? NULL : eq + 1)); + if (i < 0) { + fprintf(stderr, "%s: option '--%s' needs argument.\n", argv[0], o->longopt); + return -1; + } + found = 1; + break; + } + } + if (!found) { goto exit; } + } else { + const char *p; + for (p = v; *p; p++) { + found = 0; + for (o = opts; o->opt != '\0' || o->longopt != NULL; o++) { + if (o->opt && *p == o->opt) { + i = op_getopt_flag(flags, o, argc, argv, i, NULL); + if (i < 0) { + fprintf(stderr, "%s: option '-%c' needs argument.\n", argv[0], *p); + return -1; + } + found = 1; + break; + } + } + if (!found) { goto exit; } + } + } + } else { + break; + } + } + return i; +exit: + fprintf(stderr, "%s: cannot recognize option '%s'.\n", argv[0], argv[i]); + return -1; +} + +#define UNIT_SIZE (1 << 12) +#define UNIT_MASK (UNIT_SIZE - 1) + +int grn_bulk_margin_size = 0; + +grn_rc +grn_bulk_resize(grn_ctx *ctx, grn_obj *buf, unsigned int newsize) +{ + char *head; + unsigned int rounded_newsize; + newsize += grn_bulk_margin_size + 1; + if (GRN_BULK_OUTP(buf)) { + rounded_newsize = (newsize + (UNIT_MASK)) & ~UNIT_MASK; + if (rounded_newsize < newsize) { return GRN_NOT_ENOUGH_SPACE; } + newsize = rounded_newsize; + head = buf->u.b.head - (buf->u.b.head ? grn_bulk_margin_size : 0); + if (!(head = GRN_REALLOC(head, newsize))) { return GRN_NO_MEMORY_AVAILABLE; } + buf->u.b.curr = head + grn_bulk_margin_size + GRN_BULK_VSIZE(buf); + buf->u.b.head = head + grn_bulk_margin_size; + buf->u.b.tail = head + newsize; + } else { + if (newsize > GRN_BULK_BUFSIZE) { + rounded_newsize = (newsize + (UNIT_MASK)) & ~UNIT_MASK; + if (rounded_newsize < newsize) { return GRN_NOT_ENOUGH_SPACE; } + newsize = rounded_newsize; + if (!(head = GRN_MALLOC(newsize))) { return GRN_NO_MEMORY_AVAILABLE; } + grn_memcpy(head, GRN_BULK_HEAD(buf), GRN_BULK_VSIZE(buf)); + buf->u.b.curr = head + grn_bulk_margin_size + GRN_BULK_VSIZE(buf); + buf->u.b.head = head + grn_bulk_margin_size; + buf->u.b.tail = head + newsize; + buf->header.impl_flags |= GRN_OBJ_OUTPLACE; + } + } + return GRN_SUCCESS; +} + +grn_rc +grn_bulk_reinit(grn_ctx *ctx, grn_obj *buf, unsigned int size) +{ + GRN_BULK_REWIND(buf); + return grn_bulk_resize(ctx, buf, size); +} + +grn_rc +grn_bulk_write(grn_ctx *ctx, grn_obj *buf, const char *str, unsigned int len) +{ + grn_rc rc = GRN_SUCCESS; + char *curr; + if (GRN_BULK_REST(buf) < len) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_VSIZE(buf) + len))) { return rc; } + } + curr = GRN_BULK_CURR(buf); + if (str) + grn_memcpy(curr, str, len); + GRN_BULK_INCR_LEN(buf, len); + return rc; +} + +grn_rc +grn_bulk_write_from(grn_ctx *ctx, grn_obj *bulk, + const char *str, unsigned int from, unsigned int len) +{ + grn_rc rc = grn_bulk_truncate(ctx, bulk, from); + if (!rc) { rc = grn_bulk_write(ctx, bulk, str, len); } + return rc; +} + +grn_rc +grn_bulk_reserve(grn_ctx *ctx, grn_obj *buf, unsigned int len) +{ + grn_rc rc = GRN_SUCCESS; + if (GRN_BULK_REST(buf) < len) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_VSIZE(buf) + len))) { return rc; } + } + return rc; +} + +grn_rc +grn_bulk_space(grn_ctx *ctx, grn_obj *buf, unsigned int len) +{ + grn_rc rc = grn_bulk_reserve(ctx, buf, len); + if (!rc) { + GRN_BULK_INCR_LEN(buf, len); + } + return rc; +} + +static grn_rc +grn_bulk_space_clear(grn_ctx *ctx, grn_obj *buf, unsigned int len) +{ + grn_rc rc = grn_bulk_reserve(ctx, buf, len); + if (!rc) { + memset(GRN_BULK_CURR(buf), 0, len); + GRN_BULK_INCR_LEN(buf, len); + } + return rc; +} + +grn_rc +grn_bulk_truncate(grn_ctx *ctx, grn_obj *bulk, unsigned int len) +{ + if (GRN_BULK_OUTP(bulk)) { + if ((bulk->u.b.tail - bulk->u.b.head) < len) { + return grn_bulk_space_clear(ctx, bulk, len); + } else { + bulk->u.b.curr = bulk->u.b.head + len; + } + } else { + if (GRN_BULK_BUFSIZE < len) { + return grn_bulk_space_clear(ctx, bulk, len); + } else { + bulk->header.flags &= ~GRN_BULK_BUFSIZE_MAX; + bulk->header.flags += len; + } + } + return GRN_SUCCESS; +} + +grn_rc +grn_text_itoa(grn_ctx *ctx, grn_obj *buf, int i) +{ + grn_rc rc = GRN_SUCCESS; + for (;;) { + char *curr = GRN_BULK_CURR(buf); + char *tail = GRN_BULK_TAIL(buf); + if (grn_itoa(i, curr, tail, &curr)) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_WSIZE(buf) + UNIT_SIZE))) { return rc; } + } else { + GRN_BULK_SET_CURR(buf, curr); + break; + } + } + return rc; +} + +grn_rc +grn_text_itoa_padded(grn_ctx *ctx, grn_obj *buf, int i, char ch, unsigned int len) +{ + grn_rc rc = GRN_SUCCESS; + char *curr; + if ((rc = grn_bulk_reserve(ctx, buf, len))) { return rc; } + curr = GRN_BULK_CURR(buf); + if (!grn_itoa_padded(i, curr, curr + len, ch)) { + GRN_BULK_SET_CURR(buf, curr + len); + } + return rc; +} + +grn_rc +grn_text_lltoa(grn_ctx *ctx, grn_obj *buf, long long int i) +{ + grn_rc rc = GRN_SUCCESS; + for (;;) { + char *curr = GRN_BULK_CURR(buf); + char *tail = GRN_BULK_TAIL(buf); + if (grn_lltoa(i, curr, tail, &curr)) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_WSIZE(buf) + UNIT_SIZE))) { return rc; } + } else { + GRN_BULK_SET_CURR(buf, curr); + break; + } + } + return rc; +} + +grn_rc +grn_text_ulltoa(grn_ctx *ctx, grn_obj *buf, unsigned long long int i) +{ + grn_rc rc = GRN_SUCCESS; + for (;;) { + char *curr = GRN_BULK_CURR(buf); + char *tail = GRN_BULK_TAIL(buf); + if (grn_ulltoa(i, curr, tail, &curr)) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_WSIZE(buf) + UNIT_SIZE))) { return rc; } + } else { + GRN_BULK_SET_CURR(buf, curr); + break; + } + } + return rc; +} + +inline static void +ftoa_(grn_ctx *ctx, grn_obj *buf, double d) +{ + char *start; + size_t before_size; + size_t len; +#define DIGIT_NUMBER 16 +#define FIRST_BUFFER_SIZE (DIGIT_NUMBER + 4) + before_size = GRN_BULK_VSIZE(buf); + grn_bulk_reserve(ctx, buf, FIRST_BUFFER_SIZE); + grn_text_printf(ctx, buf, "%#.*g", DIGIT_NUMBER, d); + len = GRN_BULK_VSIZE(buf) - before_size; + start = GRN_BULK_CURR(buf) - len; +#undef FIRST_BUFFER_SIZE +#undef DIGIT_NUMBER + if (start[len - 1] == '.') { + GRN_TEXT_PUTC(ctx, buf, '0'); + } else { + char *p, *q; + start[len] = '\0'; + if ((p = strchr(start, 'e'))) { + for (q = p; *(q - 2) != '.' && *(q - 1) == '0'; q--) { len--; } + grn_memmove(q, p, start + len - q); + } else { + for (q = start + len; *(q - 2) != '.' && *(q - 1) == '0'; q--) { len--; } + } + grn_bulk_truncate(ctx, buf, before_size + len); + } +} + +grn_rc +grn_text_ftoa(grn_ctx *ctx, grn_obj *buf, double d) +{ + grn_rc rc = GRN_SUCCESS; + if (GRN_BULK_REST(buf) < 32) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_VSIZE(buf) + 32))) { return rc; } + } +#ifdef HAVE_FPCLASSIFY + switch (fpclassify(d)) { + case FP_NAN : + GRN_TEXT_PUTS(ctx, buf, "#"); + break; + case FP_INFINITE : + GRN_TEXT_PUTS(ctx, buf, d > 0 ? "#i1/0" : "#i-1/0"); + break; + default : + ftoa_(ctx, buf, d); + break; + } +#else /* HAVE_FPCLASSIFY */ + if (d == d) { + if (d != 0 && ((d / 2.0) == d)) { + GRN_TEXT_PUTS(ctx, buf, d > 0 ? "#i1/0" : "#i-1/0"); + } else { + ftoa_(ctx, buf, d); + } + } else { + GRN_TEXT_PUTS(ctx, buf, "#"); + } +#endif /* HAVE_FPCLASSIFY */ + return rc; +} + +grn_rc +grn_text_itoh(grn_ctx *ctx, grn_obj *buf, int i, unsigned int len) +{ + grn_rc rc = GRN_SUCCESS; + if (GRN_BULK_REST(buf) < len) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_VSIZE(buf) + len))) { return rc; } + } + grn_itoh(i, GRN_BULK_CURR(buf), len); + GRN_BULK_INCR_LEN(buf, len); + return rc; +} + +grn_rc +grn_text_itob(grn_ctx *ctx, grn_obj *buf, grn_id id) +{ + size_t len = 5; + grn_rc rc = GRN_SUCCESS; + if (GRN_BULK_REST(buf) < len) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_VSIZE(buf) + len))) { return rc; } + } + grn_itob(id, GRN_BULK_CURR(buf)); + GRN_BULK_INCR_LEN(buf, len); + return rc; +} + +grn_rc +grn_text_lltob32h(grn_ctx *ctx, grn_obj *buf, long long int i) +{ + size_t len = 13; + grn_rc rc = GRN_SUCCESS; + if (GRN_BULK_REST(buf) < len) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_VSIZE(buf) + len))) { return rc; } + } + grn_lltob32h(i, GRN_BULK_CURR(buf)); + GRN_BULK_INCR_LEN(buf, len); + return rc; +} + +grn_rc +grn_text_esc(grn_ctx *ctx, grn_obj *buf, const char *s, unsigned int len) +{ + const char *e; + unsigned int l; + grn_rc rc = GRN_SUCCESS; + + GRN_TEXT_PUTC(ctx, buf, '"'); + for (e = s + len; s < e; s += l) { + if (!(l = grn_charlen(ctx, s, e))) { break; } + if (l == 1) { + switch (*s) { + case '"' : + grn_bulk_write(ctx, buf, "\\\"", 2); + break; + case '\\' : + grn_bulk_write(ctx, buf, "\\\\", 2); + break; + case '\b' : + grn_bulk_write(ctx, buf, "\\b", 2); + break; + case '\f' : + grn_bulk_write(ctx, buf, "\\f", 2); + break; + case '\n' : + grn_bulk_write(ctx, buf, "\\n", 2); + break; + case '\r' : + grn_bulk_write(ctx, buf, "\\r", 2); + break; + case '\t' : + grn_bulk_write(ctx, buf, "\\t", 2); + break; + case '\x00': case '\x01': case '\x02': case '\x03': case '\x04': case '\x05': + case '\x06': case '\x07': case '\x0b': case '\x0e': case '\x0f': case '\x10': + case '\x11': case '\x12': case '\x13': case '\x14': case '\x15': case '\x16': + case '\x17': case '\x18': case '\x19': case '\x1a': case '\x1b': case '\x1c': + case '\x1d': case '\x1e': case '\x1f': case '\x7f': + if (!(rc = grn_bulk_write(ctx, buf, "\\u", 2))) { + if ((rc = grn_text_itoh(ctx, buf, *s, 4))) { + GRN_BULK_INCR_LEN(buf, -2); + return rc; + } + } else { + return rc; + } + break; + default : + GRN_TEXT_PUTC(ctx, buf, *s); + } + } else if (l == 3) { + if (*s == '\xe2' && *(s + 1) == '\x80') { + switch (*(s + 2)) { + case '\xa8': /* \u2028 */ + grn_bulk_write(ctx, buf, "\\u2028", 6); + break; + case '\xa9': /* \u2029 */ + grn_bulk_write(ctx, buf, "\\u2029", 6); + break; + default: + grn_bulk_write(ctx, buf, s, l); + } + } else { + grn_bulk_write(ctx, buf, s, l); + } + } else { + grn_bulk_write(ctx, buf, s, l); + } + } + GRN_TEXT_PUTC(ctx, buf, '"'); + return rc; +} + +grn_rc +grn_text_escape_xml(grn_ctx *ctx, grn_obj *buf, const char *s, unsigned int len) +{ + const char *e; + unsigned int l; + grn_rc rc = GRN_SUCCESS; + + for (e = s + len; s < e; s += l) { + if (!(l = grn_charlen(ctx, s, e))) { break; } + if (l == 1) { + switch (*s) { + case '"' : + grn_bulk_write(ctx, buf, """, 6); + break; + case '<' : + grn_bulk_write(ctx, buf, "<", 4); + break; + case '>' : + grn_bulk_write(ctx, buf, ">", 4); + break; + case '&' : + grn_bulk_write(ctx, buf, "&", 5); + break; + default : + GRN_TEXT_PUTC(ctx, buf, *s); + } + } else { + grn_bulk_write(ctx, buf, s, l); + } + } + return rc; +} + +#define TOK_ESC (0x80) + +const char * +grn_text_unesc_tok(grn_ctx *ctx, grn_obj *buf, const char *s, const char *e, char *tok_type) +{ + const char *p; + unsigned int len; + uint8_t stat = GRN_TOK_VOID; + for (p = s; p < e; p += len) { + if (!(len = grn_charlen(ctx, p, e))) { + p = e; + stat &= ~TOK_ESC; + goto exit; + } + switch (stat) { + case GRN_TOK_VOID : + if (*p == ' ') { continue; } + switch (*p) { + case '"' : + stat = GRN_TOK_STRING; + break; + case '\'' : + stat = GRN_TOK_QUOTE; + break; + case ')' : + case '(' : + GRN_TEXT_PUT(ctx, buf, p, len); + p += len; + stat = GRN_TOK_SYMBOL; + goto exit; + case '\\' : + stat = GRN_TOK_SYMBOL|TOK_ESC; + break; + default : + stat = GRN_TOK_SYMBOL; + GRN_TEXT_PUT(ctx, buf, p, len); + break; + } + break; + case GRN_TOK_SYMBOL : + if (*p == ' ') { goto exit; } + switch (*p) { + case '\'' : + case '"' : + case ')' : + case '(' : + goto exit; + case '\\' : + stat |= TOK_ESC; + break; + default : + GRN_TEXT_PUT(ctx, buf, p, len); + break; + } + break; + case GRN_TOK_STRING : + switch (*p) { + case '"' : + p += len; + goto exit; + case '\\' : + stat |= TOK_ESC; + break; + default : + GRN_TEXT_PUT(ctx, buf, p, len); + break; + } + break; + case GRN_TOK_QUOTE : + switch (*p) { + case '\'' : + p += len; + goto exit; + case '\\' : + stat |= TOK_ESC; + break; + default : + GRN_TEXT_PUT(ctx, buf, p, len); + break; + } + break; + case GRN_TOK_SYMBOL|TOK_ESC : + case GRN_TOK_STRING|TOK_ESC : + case GRN_TOK_QUOTE|TOK_ESC : + switch (*p) { + case 'b' : + GRN_TEXT_PUTC(ctx, buf, '\b'); + break; + case 'f' : + GRN_TEXT_PUTC(ctx, buf, '\f'); + break; + case 'n' : + GRN_TEXT_PUTC(ctx, buf, '\n'); + break; + case 'r' : + GRN_TEXT_PUTC(ctx, buf, '\r'); + break; + case 't' : + GRN_TEXT_PUTC(ctx, buf, '\t'); + break; + default : + GRN_TEXT_PUT(ctx, buf, p, len); + break; + } + stat &= ~TOK_ESC; + break; + } + } +exit : + *tok_type = stat; + return p; +} + +grn_rc +grn_text_benc(grn_ctx *ctx, grn_obj *buf, unsigned int v) +{ + grn_rc rc = GRN_SUCCESS; + uint8_t *p; + if (GRN_BULK_REST(buf) < 5) { + if ((rc = grn_bulk_resize(ctx, buf, GRN_BULK_VSIZE(buf) + 5))) { return rc; } + } + p = (uint8_t *)GRN_BULK_CURR(buf); + GRN_B_ENC(v, p); + GRN_BULK_SET_CURR(buf, (char *)p); + return rc; +} + +/* 0x00 - 0x7f */ +static const int_least8_t urlenc_tbl[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +}; + +grn_rc +grn_text_urlenc(grn_ctx *ctx, grn_obj *buf, const char *s, unsigned int len) +{ + const char *e, c = '%'; + for (e = s + len; s < e; s++) { + if ((signed char)*s < 0 || urlenc_tbl[(int)*s]) { + if (!grn_bulk_write(ctx, buf, &c, 1)) { + if (grn_text_itoh(ctx, buf, *s, 2)) { + GRN_BULK_INCR_LEN(buf, -1); + } + } + } else { + GRN_TEXT_PUTC(ctx, buf, *s); + } + } + return GRN_SUCCESS; +} + +static const char *weekdays[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; +static const char *months[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +grn_rc +grn_text_time2rfc1123(grn_ctx *ctx, grn_obj *bulk, int sec) +{ + time_t tsec; + struct tm *t; +#ifdef HAVE__GMTIME64_S + struct tm tm; + tsec = (time_t)sec; + t = (gmtime_s(&tm, &tsec) == 0) ? &tm : NULL; +#else /* HAVE__GMTIME64_S */ +# ifdef HAVE_GMTIME_R + struct tm tm; + tsec = (time_t)sec; + t = gmtime_r(&tsec, &tm); +# else /* HAVE_GMTIME_R */ + tsec = (time_t)sec; + t = gmtime(&tsec); +# endif /* HAVE_GMTIME_R */ +#endif /* HAVE__GMTIME64_S */ + if (t) { + GRN_TEXT_SET(ctx, bulk, weekdays[t->tm_wday], 3); + GRN_TEXT_PUTS(ctx, bulk, ", "); + grn_text_itoa_padded(ctx, bulk, t->tm_mday, '0', 2); + GRN_TEXT_PUTS(ctx, bulk, " "); + GRN_TEXT_PUT(ctx, bulk, months[t->tm_mon], 3); + GRN_TEXT_PUTS(ctx, bulk, " "); + grn_text_itoa(ctx, bulk, t->tm_year + 1900); + GRN_TEXT_PUTS(ctx, bulk, " "); + grn_text_itoa_padded(ctx, bulk, t->tm_hour, '0', 2); + GRN_TEXT_PUTS(ctx, bulk, ":"); + grn_text_itoa_padded(ctx, bulk, t->tm_min, '0', 2); + GRN_TEXT_PUTS(ctx, bulk, ":"); + grn_text_itoa_padded(ctx, bulk, t->tm_sec, '0', 2); + GRN_TEXT_PUTS(ctx, bulk, " GMT"); + } else { + GRN_TEXT_SETS(ctx, bulk, "Mon, 16 Mar 1980 20:40:00 GMT"); + } + return GRN_SUCCESS; +} + +grn_rc +grn_text_printf(grn_ctx *ctx, grn_obj *bulk, const char *format, ...) +{ + va_list args; + + va_start(args, format); + grn_text_vprintf(ctx, bulk, format, args); + va_end(args); + + return GRN_SUCCESS; +} + +grn_rc +grn_text_vprintf(grn_ctx *ctx, grn_obj *bulk, const char *format, va_list args) +{ + grn_bool is_written = GRN_FALSE; + int written_size; + + { + int rest_size; + va_list copied_args; + + rest_size = GRN_BULK_REST(bulk); + va_copy(copied_args, args); + written_size = vsnprintf(GRN_BULK_CURR(bulk), rest_size, + format, copied_args); + va_end(copied_args); + + if (0 <= written_size && written_size < rest_size) { + is_written = GRN_TRUE; + } + } + + if (!is_written) { +#ifdef WIN32 +# define N_NEW_SIZES 3 + int i; + int new_sizes[N_NEW_SIZES]; + + new_sizes[0] = GRN_BULK_REST(bulk) + strlen(format) * 2; + new_sizes[1] = new_sizes[0] + 4096; + new_sizes[2] = new_sizes[0] + 65536; + + for (i = 0; i < N_NEW_SIZES; i++) { + grn_rc rc; + int new_size = new_sizes[i]; + va_list copied_args; + + rc = grn_bulk_reserve(ctx, bulk, GRN_BULK_VSIZE(bulk) + new_size); + if (rc) { + return rc; + } + va_copy(copied_args, args); + written_size = vsnprintf(GRN_BULK_CURR(bulk), new_size, + format, copied_args); + va_end(copied_args); + if (written_size != -1) { + break; + } + } +# undef N_NEW_SIZES +#else /* WIN32 */ + grn_rc rc; + int required_size = written_size + 1; /* "+ 1" for terminate '\0'. */ + + rc = grn_bulk_reserve(ctx, bulk, GRN_BULK_VSIZE(bulk) + required_size); + if (rc) { + return rc; + } + written_size = vsnprintf(GRN_BULK_CURR(bulk), required_size, + format, args); +#endif /* WIN32 */ + } + + if (written_size < 0) { + return GRN_INVALID_ARGUMENT; + } + + GRN_BULK_INCR_LEN(bulk, written_size); + return GRN_SUCCESS; +} + +grn_rc +grn_bulk_fin(grn_ctx *ctx, grn_obj *buf) +{ + if (!(buf->header.impl_flags & GRN_OBJ_REFER)) { + if (GRN_BULK_OUTP(buf) && buf->u.b.head) { + GRN_REALLOC(buf->u.b.head - grn_bulk_margin_size, 0); + } + } + buf->header.flags = 0; + buf->header.impl_flags &= ~GRN_OBJ_DO_SHALLOW_COPY; + buf->u.b.head = NULL; + buf->u.b.curr = NULL; + buf->u.b.tail = NULL; + return GRN_SUCCESS; +} + +grn_rc +grn_substring(grn_ctx *ctx, char **str, char **str_end, int start, int end, grn_encoding encoding) +{ + int i; + size_t l; + char *s = *str, *e = *str_end; + for (i = 0; s < e; i++, s += l) { + if (i == start) { *str = s; } + if (!(l = grn_charlen(ctx, s, e))) { + return GRN_INVALID_ARGUMENT; + } + if (i == end) { + *str_end = s; + break; + } + } + return GRN_SUCCESS; +} + +static void +grn_text_atoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj, grn_id id) +{ + uint32_t vs; + grn_obj buf; + if (obj->header.type == GRN_ACCESSOR) { + grn_accessor *a = (grn_accessor *)obj; + GRN_TEXT_INIT(&buf, 0); + for (;;) { + GRN_BULK_REWIND(&buf); + switch (a->action) { + case GRN_ACCESSOR_GET_ID : + GRN_UINT32_PUT(ctx, &buf, id); + buf.header.domain = GRN_DB_UINT32; + break; + case GRN_ACCESSOR_GET_KEY : + grn_table_get_key2(ctx, a->obj, id, &buf); + buf.header.domain = DB_OBJ(a->obj)->header.domain; + break; + case GRN_ACCESSOR_GET_VALUE : + grn_obj_get_value(ctx, a->obj, id, &buf); + buf.header.domain = GRN_DB_INT32; /* fix me */ + break; + case GRN_ACCESSOR_GET_SCORE : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + int32_t int32_score = ri->score; + GRN_INT32_PUT(ctx, &buf, int32_score); + } + buf.header.domain = GRN_DB_INT32; + break; + case GRN_ACCESSOR_GET_NSUBRECS : + { + grn_rset_recinfo *ri = (grn_rset_recinfo *)grn_obj_get_value_(ctx, a->obj, id, &vs); + GRN_INT32_PUT(ctx, &buf, ri->n_subrecs); + } + buf.header.domain = GRN_DB_INT32; + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + if ((a->obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) { + if (a->next) { + grn_id *idp; + grn_obj_get_value(ctx, a->obj, id, &buf); + idp = (grn_id *)GRN_BULK_HEAD(&buf); + GRN_TEXT_PUTC(ctx, bulk, '['); + for (vs = GRN_BULK_VSIZE(&buf) / sizeof(grn_id); vs--; idp++) { + grn_text_atoj(ctx, bulk, (grn_obj *)a->next, *idp); + if (vs) { GRN_TEXT_PUTC(ctx, bulk, ','); } + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } else { + grn_text_atoj(ctx, bulk, a->obj, id); + } + goto exit; + } else { + grn_obj_get_value(ctx, a->obj, id, &buf); + } + break; + case GRN_ACCESSOR_GET_DB_OBJ : + /* todo */ + break; + case GRN_ACCESSOR_LOOKUP : + /* todo */ + break; + case GRN_ACCESSOR_FUNCALL : + /* todo */ + break; + } + if (a->next) { + a = a->next; + id = *((grn_id *)GRN_BULK_HEAD(&buf)); + } else { + break; + } + } + } else { + switch (obj->header.type) { + case GRN_COLUMN_FIX_SIZE : + GRN_VALUE_FIX_SIZE_INIT(&buf, 0, DB_OBJ(obj)->range); + break; + case GRN_COLUMN_VAR_SIZE : + if ((obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) == GRN_OBJ_COLUMN_VECTOR) { + grn_obj *range = grn_ctx_at(ctx, DB_OBJ(obj)->range); + if (range->header.flags & GRN_OBJ_KEY_VAR_SIZE) { + GRN_VALUE_VAR_SIZE_INIT(&buf, GRN_OBJ_VECTOR, DB_OBJ(obj)->range); + } else { + GRN_VALUE_FIX_SIZE_INIT(&buf, GRN_OBJ_VECTOR, DB_OBJ(obj)->range); + } + } else { + GRN_VALUE_VAR_SIZE_INIT(&buf, 0, DB_OBJ(obj)->range); + } + break; + case GRN_COLUMN_INDEX : + GRN_UINT32_INIT(&buf, 0); + break; + default: + GRN_TEXT_INIT(&buf, 0); + break; + } + grn_obj_get_value(ctx, obj, id, &buf); + } + grn_text_otoj(ctx, bulk, &buf, NULL); +exit : + grn_obj_close(ctx, &buf); +} + +grn_rc +grn_text_otoj(grn_ctx *ctx, grn_obj *bulk, grn_obj *obj, grn_obj_format *format) +{ + grn_obj buf; + GRN_TEXT_INIT(&buf, 0); + switch (obj->header.type) { + case GRN_BULK : + switch (obj->header.domain) { + case GRN_DB_VOID : + case GRN_DB_SHORT_TEXT : + case GRN_DB_TEXT : + case GRN_DB_LONG_TEXT : + grn_text_esc(ctx, bulk, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj)); + break; + case GRN_DB_BOOL : + if (*((unsigned char *)GRN_BULK_HEAD(obj))) { + GRN_TEXT_PUTS(ctx, bulk, "true"); + } else { + GRN_TEXT_PUTS(ctx, bulk, "false"); + } + break; + case GRN_DB_INT8 : + grn_text_itoa(ctx, bulk, GRN_BULK_VSIZE(obj) ? GRN_INT8_VALUE(obj) : 0); + break; + case GRN_DB_UINT8 : + grn_text_lltoa(ctx, bulk, GRN_BULK_VSIZE(obj) ? GRN_UINT8_VALUE(obj) : 0); + break; + case GRN_DB_INT16 : + grn_text_itoa(ctx, bulk, GRN_BULK_VSIZE(obj) ? GRN_INT16_VALUE(obj) : 0); + break; + case GRN_DB_UINT16 : + grn_text_lltoa(ctx, bulk, GRN_BULK_VSIZE(obj) ? GRN_UINT16_VALUE(obj) : 0); + break; + case GRN_DB_INT32 : + grn_text_itoa(ctx, bulk, GRN_BULK_VSIZE(obj) ? GRN_INT32_VALUE(obj) : 0); + break; + case GRN_DB_UINT32 : + grn_text_lltoa(ctx, bulk, GRN_BULK_VSIZE(obj) ? GRN_UINT32_VALUE(obj) : 0); + break; + case GRN_DB_INT64 : + grn_text_lltoa(ctx, bulk, GRN_BULK_VSIZE(obj) ? GRN_INT64_VALUE(obj) : 0); + break; + case GRN_DB_UINT64 : + grn_text_ulltoa(ctx, bulk, GRN_BULK_VSIZE(obj) ? GRN_UINT64_VALUE(obj) : 0); + break; + case GRN_DB_FLOAT : + grn_text_ftoa(ctx, bulk, GRN_BULK_VSIZE(obj) ? GRN_FLOAT_VALUE(obj) : 0); + break; + case GRN_DB_TIME : + { + double dv = *((int64_t *)GRN_BULK_HEAD(obj)); + dv /= 1000000.0; + grn_text_ftoa(ctx, bulk, dv); + } + break; + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + if (GRN_BULK_VSIZE(obj) == sizeof(grn_geo_point)) { + grn_geo_point *gp = (grn_geo_point *)GRN_BULK_HEAD(obj); + GRN_TEXT_PUTC(ctx, bulk, '"'); + grn_text_itoa(ctx, bulk, gp->latitude); + GRN_TEXT_PUTC(ctx, bulk, 'x'); + grn_text_itoa(ctx, bulk, gp->longitude); + GRN_TEXT_PUTC(ctx, bulk, '"'); + } else { + GRN_TEXT_PUTS(ctx, bulk, "\"\""); + } + break; + default : + if (format) { + int j; + int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *); + grn_id id = GRN_RECORD_VALUE(obj); + grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); + if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { + GRN_TEXT_PUTS(ctx, bulk, "["); + for (j = 0; j < ncolumns; j++) { + grn_id range_id; + if (j) { GRN_TEXT_PUTC(ctx, bulk, ','); } + GRN_TEXT_PUTS(ctx, bulk, "["); + GRN_BULK_REWIND(&buf); + grn_column_name_(ctx, columns[j], &buf); + grn_text_otoj(ctx, bulk, &buf, NULL); + GRN_TEXT_PUTC(ctx, bulk, ','); + /* column range */ + range_id = grn_obj_get_range(ctx, columns[j]); + if (range_id == GRN_ID_NIL) { + GRN_TEXT_PUTS(ctx, bulk, "null"); + } else { + int name_len; + grn_obj *range_obj; + char name_buf[GRN_TABLE_MAX_KEY_SIZE]; + + range_obj = grn_ctx_at(ctx, range_id); + name_len = grn_obj_name(ctx, range_obj, name_buf, + GRN_TABLE_MAX_KEY_SIZE); + GRN_BULK_REWIND(&buf); + GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); + grn_text_otoj(ctx, bulk, &buf, NULL); + } + GRN_TEXT_PUTS(ctx, bulk, "]"); + } + GRN_TEXT_PUTS(ctx, bulk, "],"); + } + GRN_TEXT_PUTC(ctx, bulk, '['); + for (j = 0; j < ncolumns; j++) { + if (j) { GRN_TEXT_PUTC(ctx, bulk, ','); } + grn_text_atoj(ctx, bulk, columns[j], id); + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } else { + if (GRN_BULK_VSIZE(obj) == 0) { + GRN_TEXT_PUTS(ctx, bulk, "null"); + } else { + grn_obj *table = grn_ctx_at(ctx, obj->header.domain); + grn_id id = GRN_RECORD_VALUE(obj); + if (table && table->header.type != GRN_TABLE_NO_KEY) { + /* todo : temporal patch. grn_table_at() is kinda costful... */ + if (grn_table_at(ctx, table, id)) { + grn_obj *accessor = grn_obj_column(ctx, table, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + if (accessor) { + grn_obj_get_value(ctx, accessor, id, &buf); + grn_obj_unlink(ctx, accessor); + } + } + grn_text_otoj(ctx, bulk, &buf, format); + } else { + grn_text_lltoa(ctx, bulk, id); + } + } + } + } + break; + case GRN_UVECTOR : + if (format) { + if (format->flags & GRN_OBJ_FORMAT_WITH_WEIGHT) { + int i, n; + grn_obj *domain; + + n = grn_uvector_size(ctx, obj); + domain = grn_ctx_at(ctx, obj->header.domain); + GRN_TEXT_PUTS(ctx, bulk, "{"); + for (i = 0; i < n; i++) { + grn_id id; + unsigned int weight; + + if (i > 0) { + GRN_TEXT_PUTC(ctx, bulk, ','); + } + id = grn_uvector_get_element(ctx, obj, i, &weight); + if (domain) { + if (domain->header.type == GRN_TABLE_NO_KEY) { + GRN_TEXT_PUTC(ctx, bulk, '"'); + grn_text_ulltoa(ctx, bulk, id); + GRN_TEXT_PUTC(ctx, bulk, '"'); + } else { + GRN_BULK_REWIND(&buf); + grn_table_get_key2(ctx, domain, id, &buf); + grn_text_otoj(ctx, bulk, &buf, NULL); + } + } else { + GRN_TEXT_PUTC(ctx, bulk, '"'); + grn_text_ulltoa(ctx, bulk, id); + GRN_TEXT_PUTC(ctx, bulk, '"'); + } + GRN_TEXT_PUTC(ctx, bulk, ':'); + grn_text_ulltoa(ctx, bulk, weight); + } + GRN_TEXT_PUTS(ctx, bulk, "}"); + } else { + /* TODO: Does we still need this code? If we don't need this, we should + remove this. */ + int i, j; + grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), *ve = (grn_id *)GRN_BULK_CURR(obj); + int ncolumns = GRN_BULK_VSIZE(&format->columns) / sizeof(grn_obj *); + grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); + GRN_TEXT_PUTS(ctx, bulk, "[["); + grn_text_itoa(ctx, bulk, ve - v); + GRN_TEXT_PUTC(ctx, bulk, ']'); + if (v < ve) { + if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { + GRN_TEXT_PUTS(ctx, bulk, ",["); + for (j = 0; j < ncolumns; j++) { + grn_id range_id; + if (j) { GRN_TEXT_PUTC(ctx, bulk, ','); } + GRN_TEXT_PUTS(ctx, bulk, "["); + GRN_BULK_REWIND(&buf); + grn_column_name_(ctx, columns[j], &buf); + grn_text_otoj(ctx, bulk, &buf, NULL); + GRN_TEXT_PUTC(ctx, bulk, ','); + /* column range */ + range_id = grn_obj_get_range(ctx, columns[j]); + if (range_id == GRN_ID_NIL) { + GRN_TEXT_PUTS(ctx, bulk, "null"); + } else { + int name_len; + grn_obj *range_obj; + char name_buf[GRN_TABLE_MAX_KEY_SIZE]; + + range_obj = grn_ctx_at(ctx, range_id); + name_len = grn_obj_name(ctx, range_obj, name_buf, + GRN_TABLE_MAX_KEY_SIZE); + GRN_BULK_REWIND(&buf); + GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); + grn_text_otoj(ctx, bulk, &buf, NULL); + } + GRN_TEXT_PUTS(ctx, bulk, "]"); + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } + for (i = 0;; i++) { + GRN_TEXT_PUTS(ctx, bulk, ",["); + for (j = 0; j < ncolumns; j++) { + if (j) { GRN_TEXT_PUTC(ctx, bulk, ','); } + GRN_BULK_REWIND(&buf); + grn_obj_get_value(ctx, columns[j], *v, &buf); + grn_text_otoj(ctx, bulk, &buf, NULL); + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + v++; + if (v < ve) { + GRN_TEXT_PUTC(ctx, bulk, ','); + } else { + break; + } + } + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } + } else { + grn_obj *range = grn_ctx_at(ctx, obj->header.domain); + if (range && range->header.type == GRN_TYPE) { + grn_id value_size = ((struct _grn_type *)range)->obj.range; + char *v = (char *)GRN_BULK_HEAD(obj), + *ve = (char *)GRN_BULK_CURR(obj); + GRN_TEXT_PUTC(ctx, bulk, '['); + if (v < ve) { + for (;;) { + grn_obj value; + GRN_OBJ_INIT(&value, GRN_BULK, 0, obj->header.domain); + grn_bulk_write_from(ctx, &value, v, 0, value_size); + grn_text_otoj(ctx, bulk, &value, NULL); + + v += value_size; + if (v < ve) { + GRN_TEXT_PUTC(ctx, bulk, ','); + } else { + break; + } + } + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } else { + grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), + *ve = (grn_id *)GRN_BULK_CURR(obj); + GRN_TEXT_PUTC(ctx, bulk, '['); + if (v < ve) { + for (;;) { + if (range->header.type != GRN_TABLE_NO_KEY) { + grn_obj key; + GRN_OBJ_INIT(&key, GRN_BULK, 0, range->header.domain); + grn_table_get_key2(ctx, range, *v, &key); + grn_text_otoj(ctx, bulk, &key, NULL); + GRN_OBJ_FIN(ctx, &key); + } else { + grn_text_lltoa(ctx, bulk, *v); + } + v++; + if (v < ve) { + GRN_TEXT_PUTC(ctx, bulk, ','); + } else { + break; + } + } + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } + } + break; + case GRN_VECTOR : + if (obj->header.domain == GRN_DB_VOID) { + ERR(GRN_INVALID_ARGUMENT, "invalid obj->header.domain"); + } else { + unsigned int i, n; + grn_obj value; + grn_obj weight; + grn_bool with_weight; + + GRN_VOID_INIT(&value); + GRN_UINT32_INIT(&weight, 0); + with_weight = (format && format->flags & GRN_OBJ_FORMAT_WITH_WEIGHT); + n = grn_vector_size(ctx, obj); + if (with_weight) { + GRN_TEXT_PUTC(ctx, bulk, '{'); + } else { + GRN_TEXT_PUTC(ctx, bulk, '['); + } + for (i = 0; i < n; i++) { + const char *_value; + unsigned int _weight, length; + grn_id domain; + if (i) { GRN_TEXT_PUTC(ctx, bulk, ','); } + + length = grn_vector_get_element(ctx, obj, i, + &_value, &_weight, &domain); + if (domain != GRN_DB_VOID) { + grn_obj_reinit(ctx, &value, domain, 0); + } else { + grn_obj_reinit(ctx, &value, obj->header.domain, 0); + } + grn_bulk_write(ctx, &value, _value, length); + grn_text_otoj(ctx, bulk, &value, NULL); + if (with_weight) { + GRN_TEXT_PUTC(ctx, bulk, ':'); + GRN_UINT32_SET(ctx, &weight, _weight); + grn_text_otoj(ctx, bulk, &weight, NULL); + } + } + if (with_weight) { + GRN_TEXT_PUTC(ctx, bulk, '}'); + } else { + GRN_TEXT_PUTC(ctx, bulk, ']'); + } + GRN_OBJ_FIN(ctx, &value); + GRN_OBJ_FIN(ctx, &weight); + } + break; + case GRN_PVECTOR : + if (format) { + ERR(GRN_FUNCTION_NOT_IMPLEMENTED, + "cannot print GRN_PVECTOR using grn_obj_format"); + } else { + unsigned int i, n; + GRN_TEXT_PUTC(ctx, bulk, '['); + n = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *); + for (i = 0; i < n; i++) { + grn_obj *value; + + if (i) { GRN_TEXT_PUTC(ctx, bulk, ','); } + value = GRN_PTR_VALUE_AT(obj, i); + grn_text_otoj(ctx, bulk, value, NULL); + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } + break; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_NO_KEY : + if (format) { + int i, j; + int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *); + grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); + grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, + format->offset, format->limit, + GRN_CURSOR_ASCENDING); + if (!tc) { ERRCLR(ctx); } + GRN_TEXT_PUTS(ctx, bulk, "[["); + grn_text_itoa(ctx, bulk, format->nhits); + GRN_TEXT_PUTC(ctx, bulk, ']'); + if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { + GRN_TEXT_PUTS(ctx, bulk, ",["); + for (j = 0; j < ncolumns; j++) { + grn_id range_id; + if (j) { GRN_TEXT_PUTC(ctx, bulk, ','); } + GRN_TEXT_PUTS(ctx, bulk, "["); + GRN_BULK_REWIND(&buf); + grn_column_name_(ctx, columns[j], &buf); + grn_text_otoj(ctx, bulk, &buf, NULL); + GRN_TEXT_PUTC(ctx, bulk, ','); + /* column range */ + range_id = grn_obj_get_range(ctx, columns[j]); + if (range_id == GRN_ID_NIL) { + GRN_TEXT_PUTS(ctx, bulk, "null"); + } else { + int name_len; + grn_obj *range_obj; + char name_buf[GRN_TABLE_MAX_KEY_SIZE]; + + range_obj = grn_ctx_at(ctx, range_id); + name_len = grn_obj_name(ctx, range_obj, name_buf, + GRN_TABLE_MAX_KEY_SIZE); + GRN_BULK_REWIND(&buf); + GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); + grn_text_otoj(ctx, bulk, &buf, NULL); + } + GRN_TEXT_PUTS(ctx, bulk, "]"); + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } + if (tc) { + grn_id id; + for (i = 0; (id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL; i++) { + GRN_TEXT_PUTS(ctx, bulk, ",["); + for (j = 0; j < ncolumns; j++) { + if (j) { GRN_TEXT_PUTC(ctx, bulk, ','); } + grn_text_atoj(ctx, bulk, columns[j], id); + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } + grn_table_cursor_close(ctx, tc); + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + } else { + int i; + grn_id id; + grn_obj *column = grn_obj_column(ctx, obj, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, + 0, -1, GRN_CURSOR_ASCENDING); + GRN_TEXT_PUTC(ctx, bulk, '['); + if (tc) { + for (i = 0; (id = grn_table_cursor_next(ctx, tc)) != GRN_ID_NIL; i++) { + if (i) { GRN_TEXT_PUTC(ctx, bulk, ','); } + GRN_BULK_REWIND(&buf); + grn_obj_get_value(ctx, column, id, &buf); + grn_text_esc(ctx, bulk, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf)); + } + grn_table_cursor_close(ctx, tc); + } + GRN_TEXT_PUTC(ctx, bulk, ']'); + grn_obj_unlink(ctx, column); + } + break; + } + grn_obj_close(ctx, &buf); + return GRN_SUCCESS; +} + +const char * +grn_text_urldec(grn_ctx *ctx, grn_obj *buf, const char *p, const char *e, char d) +{ + while (p < e) { + if (*p == d) { + p++; break; + } else if (*p == '%' && p + 3 <= e) { + const char *r; + unsigned int c = grn_htoui(p + 1, p + 3, &r); + if (p + 3 == r) { + GRN_TEXT_PUTC(ctx, buf, c); + p += 3; + } else { + GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid %% sequence (%c%c)", p[1], p[2]); + GRN_TEXT_PUTC(ctx, buf, '%'); + p += 1; + } + } else { + GRN_TEXT_PUTC(ctx, buf, *p); + p++; + } + } + return p; +} + +const char * +grn_text_cgidec(grn_ctx *ctx, grn_obj *buf, const char *p, const char *e, + const char *delimiters) +{ + while (p < e) { + grn_bool found_delimiter = GRN_FALSE; + const char *delimiter; + for (delimiter = delimiters; *delimiter; delimiter++) { + if (*p == *delimiter) { + found_delimiter = GRN_TRUE; + break; + } + } + if (found_delimiter) { + p++; + break; + } + + if (*p == '+') { + GRN_TEXT_PUTC(ctx, buf, ' '); + p++; + } else if (*p == '%' && p + 3 <= e) { + const char *r; + unsigned int c = grn_htoui(p + 1, p + 3, &r); + if (p + 3 == r) { + GRN_TEXT_PUTC(ctx, buf, c); + p += 3; + } else { + GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid %% sequence (%c%c)", p[1], p[2]); + GRN_TEXT_PUTC(ctx, buf, '%'); + p += 1; + } + } else { + GRN_TEXT_PUTC(ctx, buf, *p); + p++; + } + } + return p; +} + +void +grn_str_url_path_normalize(grn_ctx *ctx, const char *path, size_t path_len, + char *buf, size_t buf_len) +{ + char *b = buf, *be = buf + buf_len - 1; + const char *p = path, *pe = path + path_len, *pc; + + if (buf_len < 2) { return; } + + while (p < pe) { + for (pc = p; pc < pe && *pc != '/'; pc++) {} + if (*p == '.') { + if (pc == p + 2 && *(p + 1) == '.') { + /* '..' */ + if (b - buf >= 2) { + for (b -= 2; *b != '/' && b >= buf; b--) {} + } + if (*b == '/') { + b++; + ERR(GRN_INVALID_ARGUMENT, "parent path doesn't exist."); + } + p = pc + 1; + continue; + } else if (pc == p + 1) { + /* '.' */ + p = pc + 1; + continue; + } + } + if (be - b >= pc - p) { + grn_memcpy(b, p, (pc - p)); + b += pc - p; + p = pc; + if (p < pe && *pc == '/' && be > b) { + *b++ = '/'; + p++; + } + } + } + *b = '\0'; +} + +grn_bool +grn_bulk_is_zero(grn_ctx *ctx, grn_obj *obj) +{ + const char *v = GRN_BULK_HEAD(obj); + unsigned int s = GRN_BULK_VSIZE(obj); + for (; s; s--, v++) { + if (*v) { return GRN_FALSE; } + } + return GRN_TRUE; +} + diff --git a/storage/mroonga/vendor/groonga/lib/string.c b/storage/mroonga/vendor/groonga/lib/string.c new file mode 100644 index 00000000..8e591100 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/string.c @@ -0,0 +1,416 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2012 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include +#include "grn_string.h" +#include "grn_normalizer.h" +#include "grn_str.h" +#include "grn_util.h" + +#include + +static grn_string * +grn_fake_string_open(grn_ctx *ctx, grn_string *string) +{ + /* TODO: support GRN_STRING_REMOVE_BLANK flag and ctypes */ + grn_string *nstr = string; + const char *str; + unsigned int str_len; + + str = nstr->original; + str_len = nstr->original_length_in_bytes; + + if (!(nstr->normalized = GRN_MALLOC(str_len + 1))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[strinig][fake] failed to allocate normalized text space"); + grn_string_close(ctx, (grn_obj *)nstr); + return NULL; + } + + if (nstr->flags & GRN_STRING_REMOVE_TOKENIZED_DELIMITER && + ctx->encoding == GRN_ENC_UTF8) { + int char_length; + const char *source_current = str; + const char *source_end = str + str_len; + char *destination = nstr->normalized; + unsigned int destination_length = 0; + while ((char_length = grn_charlen(ctx, source_current, source_end)) > 0) { + if (!grn_tokenizer_is_tokenized_delimiter(ctx, + source_current, char_length, + ctx->encoding)) { + grn_memcpy(destination, source_current, char_length); + destination += char_length; + destination_length += char_length; + } + source_current += char_length; + } + nstr->normalized[destination_length] = '\0'; + nstr->normalized_length_in_bytes = destination_length; + } else { + grn_memcpy(nstr->normalized, str, str_len); + nstr->normalized[str_len] = '\0'; + nstr->normalized_length_in_bytes = str_len; + } + + if (nstr->flags & GRN_STRING_WITH_CHECKS) { + int16_t f = 0; + unsigned char c; + size_t i; + if (!(nstr->checks = (int16_t *) GRN_MALLOC(sizeof(int16_t) * str_len))) { + grn_string_close(ctx, (grn_obj *)nstr); + ERR(GRN_NO_MEMORY_AVAILABLE, + "[strinig][fake] failed to allocate checks space"); + return NULL; + } + switch (nstr->encoding) { + case GRN_ENC_EUC_JP: + for (i = 0; i < str_len; i++) { + if (!f) { + c = (unsigned char) str[i]; + f = ((c >= 0xa1U && c <= 0xfeU) || c == 0x8eU ? 2 : (c == 0x8fU ? 3 : 1) + ); + nstr->checks[i] = f; + } else { + nstr->checks[i] = 0; + } + f--; + } + break; + case GRN_ENC_SJIS: + for (i = 0; i < str_len; i++) { + if (!f) { + c = (unsigned char) str[i]; + f = (c >= 0x81U && ((c <= 0x9fU) || (c >= 0xe0U && c <= 0xfcU)) ? 2 : 1); + nstr->checks[i] = f; + } else { + nstr->checks[i] = 0; + } + f--; + } + break; + case GRN_ENC_UTF8: + for (i = 0; i < str_len; i++) { + if (!f) { + c = (unsigned char) str[i]; + f = (c & 0x80U ? (c & 0x20U ? (c & 0x10U ? 4 : 3) + : 2) + : 1); + nstr->checks[i] = f; + } else { + nstr->checks[i] = 0; + } + f--; + } + break; + default: + for (i = 0; i < str_len; i++) { + nstr->checks[i] = 1; + } + break; + } + } + return nstr; +} + +grn_obj * +grn_string_open_(grn_ctx *ctx, const char *str, unsigned int str_len, + grn_obj *normalizer, int flags, grn_encoding encoding) +{ + grn_string *string; + grn_obj *obj; + grn_bool is_normalizer_auto; + + if (!str || !str_len) { + return NULL; + } + + is_normalizer_auto = (normalizer == GRN_NORMALIZER_AUTO); + if (is_normalizer_auto) { + normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); + if (!normalizer) { + ERR(GRN_INVALID_ARGUMENT, + "[string][open] NormalizerAuto normalizer isn't available"); + return NULL; + } + } + + string = GRN_MALLOCN(grn_string, 1); + if (!string) { + if (is_normalizer_auto) { + grn_obj_unlink(ctx, normalizer); + } + GRN_LOG(ctx, GRN_LOG_ALERT, + "[string][open] failed to allocate memory"); + return NULL; + } + + obj = (grn_obj *)string; + GRN_OBJ_INIT(obj, GRN_STRING, GRN_OBJ_ALLOCATED, GRN_ID_NIL); + string->original = str; + string->original_length_in_bytes = str_len; + string->normalized = NULL; + string->normalized_length_in_bytes = 0; + string->n_characters = 0; + string->checks = NULL; + string->ctypes = NULL; + string->encoding = encoding; + string->flags = flags; + + if (!normalizer) { + return (grn_obj *)grn_fake_string_open(ctx, string); + } + + grn_normalizer_normalize(ctx, normalizer, (grn_obj *)string); + if (ctx->rc) { + grn_obj_close(ctx, obj); + obj = NULL; + } + + if (is_normalizer_auto) { + grn_obj_unlink(ctx, normalizer); + } + + return obj; +} + +grn_obj * +grn_string_open(grn_ctx *ctx, const char *str, unsigned int str_len, + grn_obj *normalizer, int flags) +{ + return grn_string_open_(ctx, str, str_len, normalizer, flags, ctx->encoding); +} + +grn_rc +grn_string_get_original(grn_ctx *ctx, grn_obj *string, + const char **original, + unsigned int *length_in_bytes) +{ + grn_rc rc; + grn_string *string_ = (grn_string *)string; + GRN_API_ENTER; + if (string_) { + if (original) { *original = string_->original; } + if (length_in_bytes) { + *length_in_bytes = string_->original_length_in_bytes; + } + rc = GRN_SUCCESS; + } else { + rc = GRN_INVALID_ARGUMENT; + } + GRN_API_RETURN(rc); +} + +int +grn_string_get_flags(grn_ctx *ctx, grn_obj *string) +{ + int flags = 0; + grn_string *string_ = (grn_string *)string; + GRN_API_ENTER; + if (string_) { + flags = string_->flags; + } + GRN_API_RETURN(flags); +} + +grn_rc +grn_string_get_normalized(grn_ctx *ctx, grn_obj *string, + const char **normalized, + unsigned int *length_in_bytes, + unsigned int *n_characters) +{ + grn_rc rc; + grn_string *string_ = (grn_string *)string; + GRN_API_ENTER; + if (string_) { + if (normalized) { *normalized = string_->normalized; } + if (length_in_bytes) { + *length_in_bytes = string_->normalized_length_in_bytes; + } + if (n_characters) { *n_characters = string_->n_characters; } + rc = GRN_SUCCESS; + } else { + if (normalized) { *normalized = NULL; } + if (length_in_bytes) { *length_in_bytes = 0; } + if (n_characters) { *n_characters = 0; } + rc = GRN_INVALID_ARGUMENT; + } + GRN_API_RETURN(rc); +} + +grn_rc +grn_string_set_normalized(grn_ctx *ctx, grn_obj *string, + char *normalized, unsigned int length_in_bytes, + unsigned int n_characters) +{ + grn_rc rc; + grn_string *string_ = (grn_string *)string; + GRN_API_ENTER; + if (string_) { + if (string_->normalized) { GRN_FREE(string_->normalized); } + string_->normalized = normalized; + string_->normalized_length_in_bytes = length_in_bytes; + string_->n_characters = n_characters; + rc = GRN_SUCCESS; + } else { + rc = GRN_INVALID_ARGUMENT; + } + GRN_API_RETURN(rc); +} + +const short * +grn_string_get_checks(grn_ctx *ctx, grn_obj *string) +{ + int16_t *checks = NULL; + grn_string *string_ = (grn_string *)string; + GRN_API_ENTER; + if (string_) { + checks = string_->checks; + } else { + checks = NULL; + } + GRN_API_RETURN(checks); +} + +grn_rc +grn_string_set_checks(grn_ctx *ctx, grn_obj *string, short *checks) +{ + grn_rc rc; + grn_string *string_ = (grn_string *)string; + GRN_API_ENTER; + if (string_) { + if (string_->checks) { GRN_FREE(string_->checks); } + string_->checks = checks; + rc = GRN_SUCCESS; + } else { + rc = GRN_INVALID_ARGUMENT; + } + GRN_API_RETURN(rc); +} + +const unsigned char * +grn_string_get_types(grn_ctx *ctx, grn_obj *string) +{ + unsigned char *types = NULL; + grn_string *string_ = (grn_string *)string; + GRN_API_ENTER; + if (string_) { + types = string_->ctypes; + } else { + types = NULL; + } + GRN_API_RETURN(types); +} + +grn_rc +grn_string_set_types(grn_ctx *ctx, grn_obj *string, unsigned char *types) +{ + grn_rc rc; + grn_string *string_ = (grn_string *)string; + GRN_API_ENTER; + if (string_) { + if (string_->ctypes) { GRN_FREE(string_->ctypes); } + string_->ctypes = types; + rc = GRN_SUCCESS; + } else { + rc = GRN_INVALID_ARGUMENT; + } + GRN_API_RETURN(rc); +} + +grn_encoding +grn_string_get_encoding(grn_ctx *ctx, grn_obj *string) +{ + grn_encoding encoding = GRN_ENC_NONE; + grn_string *string_ = (grn_string *)string; + GRN_API_ENTER; + if (string_) { + encoding = string_->encoding; + } + GRN_API_RETURN(encoding); +} + +grn_rc +grn_string_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *string) +{ + grn_string *string_ = (grn_string *)string; + + GRN_TEXT_PUTS(ctx, buffer, "#original, + string_->original_length_in_bytes); + GRN_TEXT_PUTS(ctx, buffer, ">"); + GRN_TEXT_PUTS(ctx, buffer, "("); + grn_text_itoa(ctx, buffer, string_->original_length_in_bytes); + GRN_TEXT_PUTS(ctx, buffer, ")"); + + GRN_TEXT_PUTS(ctx, buffer, " normalized:<"); + GRN_TEXT_PUT(ctx, buffer, + string_->normalized, + string_->normalized_length_in_bytes); + GRN_TEXT_PUTS(ctx, buffer, ">"); + GRN_TEXT_PUTS(ctx, buffer, "("); + grn_text_itoa(ctx, buffer, string_->normalized_length_in_bytes); + GRN_TEXT_PUTS(ctx, buffer, ")"); + + GRN_TEXT_PUTS(ctx, buffer, " n_characters:"); + grn_text_itoa(ctx, buffer, string_->n_characters); + + GRN_TEXT_PUTS(ctx, buffer, " encoding:"); + grn_inspect_encoding(ctx, buffer, string_->encoding); + + GRN_TEXT_PUTS(ctx, buffer, " flags:"); + if (string_->flags & GRN_STRING_REMOVE_BLANK) { + GRN_TEXT_PUTS(ctx, buffer, "REMOVE_BLANK|"); + } + if (string_->flags & GRN_STRING_WITH_TYPES) { + GRN_TEXT_PUTS(ctx, buffer, "WITH_TYPES|"); + } + if (string_->flags & GRN_STRING_WITH_CHECKS) { + GRN_TEXT_PUTS(ctx, buffer, "WITH_CHECKS|"); + } + if (string_->flags & GRN_STRING_REMOVE_TOKENIZED_DELIMITER) { + GRN_TEXT_PUTS(ctx, buffer, "REMOVE_TOKENIZED_DELIMITER|"); + } + if (GRN_TEXT_VALUE(buffer)[GRN_TEXT_LEN(buffer) - 1] == '|') { + grn_bulk_truncate(ctx, buffer, GRN_TEXT_LEN(buffer) - 1); + } + + GRN_TEXT_PUTS(ctx, buffer, ">"); + + return GRN_SUCCESS; +} + +grn_rc +grn_string_close(grn_ctx *ctx, grn_obj *string) +{ + grn_rc rc; + grn_string *string_ = (grn_string *)string; + if (string_) { + if (string_->normalized) { GRN_FREE(string_->normalized); } + if (string_->ctypes) { GRN_FREE(string_->ctypes); } + if (string_->checks) { GRN_FREE(string_->checks); } + GRN_FREE(string); + rc = GRN_SUCCESS; + } else { + rc = GRN_INVALID_ARGUMENT; + } + return rc; +} diff --git a/storage/mroonga/vendor/groonga/lib/table.c b/storage/mroonga/vendor/groonga/lib/table.c new file mode 100644 index 00000000..0047c787 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/table.c @@ -0,0 +1,122 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_ctx.h" +#include "grn_expr_executor.h" + +grn_rc +grn_table_apply_expr(grn_ctx *ctx, + grn_obj *table, + grn_obj *output_column, + grn_obj *expr) +{ + grn_expr_executor *executor; + + GRN_API_ENTER; + + if (!grn_obj_is_data_column(ctx, output_column)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, output_column); + ERR(GRN_INVALID_ARGUMENT, + "[table][apply-expr] output column isn't data column: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + GRN_API_RETURN(ctx->rc); + } + + if (!grn_obj_is_expr(ctx, expr)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, expr); + ERR(GRN_INVALID_ARGUMENT, + "[table][apply-expr] expr is invalid: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + GRN_API_RETURN(ctx->rc); + } + + executor = grn_expr_executor_open(ctx, expr); + if (!executor) { + GRN_API_RETURN(ctx->rc); + } + GRN_TABLE_EACH_BEGIN_FLAGS(ctx, table, cursor, id, GRN_CURSOR_BY_ID) { + grn_obj *value; + value = grn_expr_executor_exec(ctx, executor, id); + if (ctx->rc != GRN_SUCCESS) { + break; + } + if (value) { + grn_obj_set_value(ctx, output_column, id, value, GRN_OBJ_SET); + } + } GRN_TABLE_EACH_END(ctx, cursor); + grn_expr_executor_close(ctx, executor); + + GRN_API_RETURN(ctx->rc); +} + +grn_id +grn_table_find_reference_object(grn_ctx *ctx, grn_obj *table) +{ + grn_id table_id; + grn_id reference_object_id = GRN_ID_NIL; + + GRN_API_ENTER; + + if (!grn_obj_is_table(ctx, table)) { + GRN_API_RETURN(GRN_ID_NIL); + } + + table_id = DB_OBJ(table)->id; + + GRN_DB_SPEC_EACH_BEGIN(ctx, cursor, id, spec) { + if (id == table_id) { + continue; + } + + switch (spec->header.type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + if (spec->header.domain == table_id) { + reference_object_id = id; + } + break; + case GRN_COLUMN_VAR_SIZE : + case GRN_COLUMN_FIX_SIZE : + if (spec->header.domain == table_id) { + break; + } + if (spec->range == table_id) { + reference_object_id = id; + } + break; + default : + break; + } + + if (reference_object_id != GRN_ID_NIL) { + break; + } + } GRN_DB_SPEC_EACH_END(ctx, cursor); + + GRN_API_RETURN(reference_object_id); +} diff --git a/storage/mroonga/vendor/groonga/lib/thread.c b/storage/mroonga/vendor/groonga/lib/thread.c new file mode 100644 index 00000000..7e823ab3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/thread.c @@ -0,0 +1,59 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_ctx.h" + +static grn_thread_get_limit_func get_limit_func = NULL; +static void *get_limit_func_data = NULL; +static grn_thread_set_limit_func set_limit_func = NULL; +static void *set_limit_func_data = NULL; + +uint32_t +grn_thread_get_limit(void) +{ + if (get_limit_func) { + return get_limit_func(get_limit_func_data); + } else { + return 0; + } +} + +void +grn_thread_set_limit(uint32_t new_limit) +{ + if (!set_limit_func) { + return; + } + + set_limit_func(new_limit, set_limit_func_data); +} + +void +grn_thread_set_get_limit_func(grn_thread_get_limit_func func, + void *data) +{ + get_limit_func = func; + get_limit_func_data = data; +} + +void +grn_thread_set_set_limit_func(grn_thread_set_limit_func func, void *data) +{ + set_limit_func = func; + set_limit_func_data = data; +} diff --git a/storage/mroonga/vendor/groonga/lib/time.c b/storage/mroonga/vendor/groonga/lib/time.c new file mode 100644 index 00000000..b11bc7a0 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/time.c @@ -0,0 +1,245 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_time.h" +#include "grn_ctx.h" +#include "grn_str.h" + +#include +#include + +#if defined(HAVE__LOCALTIME64_S) && defined(__GNUC__) +# ifdef _WIN64 +# define localtime_s(tm, time) _localtime64_s(tm, time) +# else /* _WIN64 */ +# define localtime_s(tm, time) _localtime32_s(tm, time) +# endif /* _WIN64 */ +#endif /* defined(HAVE__LOCALTIME64_S) && defined(__GNUC__) */ + +/* fixme by 2038 */ + +grn_rc +grn_timeval_now(grn_ctx *ctx, grn_timeval *tv) +{ +#ifdef HAVE_CLOCK_GETTIME + struct timespec t; + if (clock_gettime(CLOCK_REALTIME, &t)) { + SERR("clock_gettime"); + } else { + tv->tv_sec = t.tv_sec; + tv->tv_nsec = t.tv_nsec; + } + return ctx->rc; +#else /* HAVE_CLOCK_GETTIME */ +# ifdef WIN32 + time_t t; + struct _timeb tb; + time(&t); + _ftime(&tb); + tv->tv_sec = t; + tv->tv_nsec = tb.millitm * (GRN_TIME_NSEC_PER_SEC / 1000); + return GRN_SUCCESS; +# else /* WIN32 */ + struct timeval t; + if (gettimeofday(&t, NULL)) { + SERR("gettimeofday"); + } else { + tv->tv_sec = t.tv_sec; + tv->tv_nsec = GRN_TIME_USEC_TO_NSEC(t.tv_usec); + } + return ctx->rc; +# endif /* WIN32 */ +#endif /* HAVE_CLOCK_GETTIME */ +} + +void +grn_time_now(grn_ctx *ctx, grn_obj *obj) +{ + grn_timeval tv; + grn_timeval_now(ctx, &tv); + GRN_TIME_SET(ctx, obj, GRN_TIME_PACK(tv.tv_sec, + GRN_TIME_NSEC_TO_USEC(tv.tv_nsec))); +} + +static grn_bool +grn_time_t_to_tm(grn_ctx *ctx, const time_t time, struct tm *tm) +{ + grn_bool success; + const char *function_name; +#ifdef HAVE__LOCALTIME64_S + function_name = "localtime_s"; + success = (localtime_s(tm, &time) == 0); +#else /* HAVE__LOCALTIME64_S */ +# ifdef HAVE_LOCALTIME_R + function_name = "localtime_r"; + success = (localtime_r(&time, tm) != NULL); +# else /* HAVE_LOCALTIME_R */ + function_name = "localtime"; + { + struct tm *local_tm; + local_tm = localtime(&time); + if (local_tm) { + success = GRN_TRUE; + memcpy(tm, local_tm, sizeof(struct tm)); + } else { + success = GRN_FALSE; + } + } +# endif /* HAVE_LOCALTIME_R */ +#endif /* HAVE__LOCALTIME64_S */ + if (!success) { + SERR("%s: failed to convert time_t to struct tm: <%" GRN_FMT_INT64D ">", + function_name, + (int64_t)time); + } + return success; +} + +struct tm * +grn_timeval2tm(grn_ctx *ctx, grn_timeval *tv, struct tm *tm) +{ + if (grn_time_t_to_tm(ctx, tv->tv_sec, tm)) { + return tm; + } else { + return NULL; + } +} + +grn_bool +grn_time_to_tm(grn_ctx *ctx, int64_t time, struct tm *tm) +{ + int64_t sec; + int32_t usec; + + GRN_TIME_UNPACK(time, sec, usec); + return grn_time_t_to_tm(ctx, sec, tm); +} + +static grn_bool +grn_time_t_from_tm(grn_ctx *ctx, time_t *time, struct tm *tm) +{ + grn_bool success; + + tm->tm_yday = -1; + *time = mktime(tm); + success = (tm->tm_yday != -1); + if (!success) { + ERR(GRN_INVALID_ARGUMENT, + "mktime: failed to convert struct tm to time_t: " + "<%04d-%02d-%02dT%02d:%02d:%02d>(%d)", + 1900 + tm->tm_year, + tm->tm_mon + 1, + tm->tm_mday, + tm->tm_hour, + tm->tm_min, + tm->tm_sec, + tm->tm_isdst); + } + return success; +} + +grn_bool +grn_time_from_tm(grn_ctx *ctx, int64_t *time, struct tm *tm) +{ + time_t sec_time_t; + int64_t sec; + int32_t usec = 0; + + if (!grn_time_t_from_tm(ctx, &sec_time_t, tm)) { + return GRN_FALSE; + } + + sec = sec_time_t; + *time = GRN_TIME_PACK(sec, usec); + return GRN_TRUE; +} + +grn_rc +grn_timeval2str(grn_ctx *ctx, grn_timeval *tv, char *buf, size_t buf_size) +{ + struct tm tm; + struct tm *ltm; + ltm = grn_timeval2tm(ctx, tv, &tm); + grn_snprintf(buf, buf_size, GRN_TIMEVAL_STR_SIZE, + GRN_TIMEVAL_STR_FORMAT, + ltm->tm_year + 1900, ltm->tm_mon + 1, ltm->tm_mday, + ltm->tm_hour, ltm->tm_min, ltm->tm_sec, + (int)(GRN_TIME_NSEC_TO_USEC(tv->tv_nsec))); + if (buf_size > GRN_TIMEVAL_STR_SIZE) { + buf[GRN_TIMEVAL_STR_SIZE - 1] = '\0'; + } else { + buf[buf_size - 1] = '\0'; + } + return ctx->rc; +} + +grn_rc +grn_str2timeval(const char *str, uint32_t str_len, grn_timeval *tv) +{ + struct tm tm; + const char *r1, *r2, *rend = str + str_len; + uint32_t uv; + memset(&tm, 0, sizeof(struct tm)); + + tm.tm_year = (int)grn_atoui(str, rend, &r1) - 1900; + if ((r1 + 1) >= rend || (*r1 != '/' && *r1 != '-')) { + return GRN_INVALID_ARGUMENT; + } + r1++; + tm.tm_mon = (int)grn_atoui(r1, rend, &r1) - 1; + if ((r1 + 1) >= rend || (*r1 != '/' && *r1 != '-') || + tm.tm_mon < 0 || tm.tm_mon >= 12) { return GRN_INVALID_ARGUMENT; } + r1++; + tm.tm_mday = (int)grn_atoui(r1, rend, &r1); + if ((r1 + 1) >= rend || *r1 != ' ' || + tm.tm_mday < 1 || tm.tm_mday > 31) { return GRN_INVALID_ARGUMENT; } + + tm.tm_hour = (int)grn_atoui(++r1, rend, &r2); + if ((r2 + 1) >= rend || r1 == r2 || *r2 != ':' || + tm.tm_hour < 0 || tm.tm_hour >= 24) { + return GRN_INVALID_ARGUMENT; + } + r1 = r2 + 1; + tm.tm_min = (int)grn_atoui(r1, rend, &r2); + if ((r2 + 1) >= rend || r1 == r2 || *r2 != ':' || + tm.tm_min < 0 || tm.tm_min >= 60) { + return GRN_INVALID_ARGUMENT; + } + r1 = r2 + 1; + tm.tm_sec = (int)grn_atoui(r1, rend, &r2); + if (r1 == r2 || + tm.tm_sec < 0 || tm.tm_sec > 61 /* leap 2sec */) { + return GRN_INVALID_ARGUMENT; + } + r1 = r2; + tm.tm_yday = -1; + tm.tm_isdst = -1; + + /* tm_yday is set appropriately (0-365) on successful completion. */ + tv->tv_sec = mktime(&tm); + if (tm.tm_yday == -1) { return GRN_INVALID_ARGUMENT; } + if ((r1 + 1) < rend && *r1 == '.') { r1++; } + uv = grn_atoi(r1, rend, &r2); + while (r2 < r1 + 6) { + uv *= 10; + r2++; + } + if (uv >= GRN_TIME_USEC_PER_SEC) { return GRN_INVALID_ARGUMENT; } + tv->tv_nsec = GRN_TIME_USEC_TO_NSEC(uv); + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/token_cursor.c b/storage/mroonga/vendor/groonga/lib/token_cursor.c new file mode 100644 index 00000000..179d0f31 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/token_cursor.c @@ -0,0 +1,386 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn_token_cursor.h" +#include "grn_string.h" +#include "grn_pat.h" +#include "grn_dat.h" + +static void +grn_token_cursor_open_initialize_token_filters(grn_ctx *ctx, + grn_token_cursor *token_cursor) +{ + grn_obj *token_filters = token_cursor->token_filter.objects; + unsigned int i, n_token_filters; + + token_cursor->token_filter.data = NULL; + + if (token_filters) { + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + } else { + n_token_filters = 0; + } + + if (n_token_filters == 0) { + return; + } + + token_cursor->token_filter.data = GRN_CALLOC(sizeof(void *) * n_token_filters); + if (!token_cursor->token_filter.data) { + return; + } + + for (i = 0; i < n_token_filters; i++) { + grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); + grn_proc *token_filter = (grn_proc *)token_filter_object; + + token_cursor->token_filter.data[i] = + token_filter->callbacks.token_filter.init(ctx, + token_cursor->table, + token_cursor->mode); + } +} + +grn_token_cursor * +grn_token_cursor_open(grn_ctx *ctx, grn_obj *table, + const char *str, size_t str_len, + grn_tokenize_mode mode, unsigned int flags) +{ + grn_token_cursor *token_cursor; + grn_encoding encoding; + grn_obj *tokenizer; + grn_obj *normalizer; + grn_obj *token_filters; + grn_table_flags table_flags; + if (grn_table_get_info(ctx, table, &table_flags, &encoding, &tokenizer, + &normalizer, &token_filters)) { + return NULL; + } + if (!(token_cursor = GRN_MALLOC(sizeof(grn_token_cursor)))) { return NULL; } + token_cursor->table = table; + token_cursor->mode = mode; + token_cursor->encoding = encoding; + token_cursor->tokenizer = tokenizer; + token_cursor->token_filter.objects = token_filters; + token_cursor->token_filter.data = NULL; + token_cursor->orig = (const unsigned char *)str; + token_cursor->orig_blen = str_len; + token_cursor->curr = NULL; + token_cursor->nstr = NULL; + token_cursor->curr_size = 0; + token_cursor->pos = -1; + token_cursor->status = GRN_TOKEN_CURSOR_DOING; + token_cursor->force_prefix = GRN_FALSE; + if (tokenizer) { + grn_obj str_, flags_, mode_; + GRN_TEXT_INIT(&str_, GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET_REF(&str_, str, str_len); + GRN_UINT32_INIT(&flags_, 0); + GRN_UINT32_SET(ctx, &flags_, flags); + GRN_UINT32_INIT(&mode_, 0); + GRN_UINT32_SET(ctx, &mode_, mode); + token_cursor->pctx.caller = NULL; + token_cursor->pctx.user_data.ptr = NULL; + token_cursor->pctx.proc = (grn_proc *)tokenizer; + token_cursor->pctx.hooks = NULL; + token_cursor->pctx.currh = NULL; + token_cursor->pctx.phase = PROC_INIT; + grn_ctx_push(ctx, &mode_); + grn_ctx_push(ctx, &str_); + grn_ctx_push(ctx, &flags_); + ((grn_proc *)tokenizer)->funcs[PROC_INIT](ctx, 1, &table, &token_cursor->pctx.user_data); + grn_obj_close(ctx, &flags_); + grn_obj_close(ctx, &str_); + grn_obj_close(ctx, &mode_); + } else { + int nflags = 0; + token_cursor->nstr = grn_string_open_(ctx, str, str_len, + normalizer, + nflags, + token_cursor->encoding); + if (token_cursor->nstr) { + const char *normalized; + grn_string_get_normalized(ctx, token_cursor->nstr, + &normalized, &(token_cursor->curr_size), NULL); + token_cursor->curr = (const unsigned char *)normalized; + } else { + ERR(GRN_TOKENIZER_ERROR, + "[token-cursor][open] failed to grn_string_open()"); + } + } + + if (ctx->rc == GRN_SUCCESS) { + grn_token_cursor_open_initialize_token_filters(ctx, token_cursor); + } + + if (ctx->rc) { + grn_token_cursor_close(ctx, token_cursor); + token_cursor = NULL; + } + return token_cursor; +} + +static int +grn_token_cursor_next_apply_token_filters(grn_ctx *ctx, + grn_token_cursor *token_cursor, + grn_obj *current_token_data, + grn_obj *status) +{ + grn_obj *token_filters = token_cursor->token_filter.objects; + unsigned int i, n_token_filters; + grn_token current_token; + grn_token next_token; + + if (token_filters) { + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + } else { + n_token_filters = 0; + } + + GRN_TEXT_INIT(&(current_token.data), GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET(ctx, &(current_token.data), + GRN_TEXT_VALUE(current_token_data), + GRN_TEXT_LEN(current_token_data)); + current_token.status = GRN_INT32_VALUE(status); + GRN_TEXT_INIT(&(next_token.data), GRN_OBJ_DO_SHALLOW_COPY); + GRN_TEXT_SET(ctx, &(next_token.data), + GRN_TEXT_VALUE(&(current_token.data)), + GRN_TEXT_LEN(&(current_token.data))); + next_token.status = current_token.status; + + for (i = 0; i < n_token_filters; i++) { + grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); + grn_proc *token_filter = (grn_proc *)token_filter_object; + void *data = token_cursor->token_filter.data[i]; + +#define SKIP_FLAGS\ + (GRN_TOKEN_SKIP |\ + GRN_TOKEN_SKIP_WITH_POSITION) + if (current_token.status & SKIP_FLAGS) { + break; + } +#undef SKIP_FLAGS + + token_filter->callbacks.token_filter.filter(ctx, + ¤t_token, + &next_token, + data); + GRN_TEXT_SET(ctx, &(current_token.data), + GRN_TEXT_VALUE(&(next_token.data)), + GRN_TEXT_LEN(&(next_token.data))); + current_token.status = next_token.status; + } + + token_cursor->curr = + (const unsigned char *)GRN_TEXT_VALUE(&(current_token.data)); + token_cursor->curr_size = GRN_TEXT_LEN(&(current_token.data)); + + return current_token.status; +} + +grn_id +grn_token_cursor_next(grn_ctx *ctx, grn_token_cursor *token_cursor) +{ + int status; + grn_id tid = GRN_ID_NIL; + grn_obj *table = token_cursor->table; + grn_obj *tokenizer = token_cursor->tokenizer; + while (token_cursor->status != GRN_TOKEN_CURSOR_DONE) { + if (tokenizer) { + grn_obj *curr_, *stat_; + ((grn_proc *)tokenizer)->funcs[PROC_NEXT](ctx, 1, &table, &token_cursor->pctx.user_data); + stat_ = grn_ctx_pop(ctx); + curr_ = grn_ctx_pop(ctx); + status = grn_token_cursor_next_apply_token_filters(ctx, token_cursor, + curr_, stat_); + token_cursor->status = + ((status & GRN_TOKEN_LAST) || + (token_cursor->mode == GRN_TOKENIZE_GET && + (status & GRN_TOKEN_REACH_END))) + ? GRN_TOKEN_CURSOR_DONE : GRN_TOKEN_CURSOR_DOING; + token_cursor->force_prefix = GRN_FALSE; +#define SKIP_FLAGS \ + (GRN_TOKEN_SKIP | GRN_TOKEN_SKIP_WITH_POSITION) + if (status & SKIP_FLAGS) { + if (status & GRN_TOKEN_SKIP) { + token_cursor->pos++; + } + if (token_cursor->status == GRN_TOKEN_CURSOR_DONE && tid == GRN_ID_NIL) { + token_cursor->status = GRN_TOKEN_CURSOR_DONE_SKIP; + break; + } else { + continue; + } + } +#undef SKIP_FLAGS + if (status & GRN_TOKEN_FORCE_PREFIX) { + token_cursor->force_prefix = GRN_TRUE; + } + if (token_cursor->curr_size == 0) { + if (token_cursor->status != GRN_TOKEN_CURSOR_DONE) { + char tokenizer_name[GRN_TABLE_MAX_KEY_SIZE]; + int tokenizer_name_length; + tokenizer_name_length = + grn_obj_name(ctx, token_cursor->tokenizer, + tokenizer_name, GRN_TABLE_MAX_KEY_SIZE); + GRN_LOG(ctx, GRN_WARN, + "[token_next] ignore an empty token: <%.*s>: <%.*s>", + tokenizer_name_length, tokenizer_name, + token_cursor->orig_blen, token_cursor->orig); + } + continue; + } + if (token_cursor->curr_size > GRN_TABLE_MAX_KEY_SIZE) { + GRN_LOG(ctx, GRN_WARN, + "[token_next] ignore too long token. " + "Token must be less than or equal to %d: <%d>(<%.*s>)", + GRN_TABLE_MAX_KEY_SIZE, + token_cursor->curr_size, + token_cursor->curr_size, token_cursor->curr); + continue; + } + if (status & GRN_TOKEN_UNMATURED) { + if (status & GRN_TOKEN_OVERLAP) { + if (token_cursor->mode == GRN_TOKENIZE_GET) { + token_cursor->pos++; + continue; + } + } else { + if (status & GRN_TOKEN_REACH_END) { + token_cursor->force_prefix = GRN_TRUE; + } + } + } + } else { + token_cursor->status = GRN_TOKEN_CURSOR_DONE; + } + if (token_cursor->mode == GRN_TOKENIZE_ADD) { + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + if (grn_io_lock(ctx, ((grn_pat *)table)->io, grn_lock_timeout)) { + tid = GRN_ID_NIL; + } else { + tid = grn_pat_add(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size, + NULL, NULL); + grn_io_unlock(((grn_pat *)table)->io); + } + break; + case GRN_TABLE_DAT_KEY : + if (grn_io_lock(ctx, ((grn_dat *)table)->io, grn_lock_timeout)) { + tid = GRN_ID_NIL; + } else { + tid = grn_dat_add(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size, + NULL, NULL); + grn_io_unlock(((grn_dat *)table)->io); + } + break; + case GRN_TABLE_HASH_KEY : + if (grn_io_lock(ctx, ((grn_hash *)table)->io, grn_lock_timeout)) { + tid = GRN_ID_NIL; + } else { + tid = grn_hash_add(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size, + NULL, NULL); + grn_io_unlock(((grn_hash *)table)->io); + } + break; + case GRN_TABLE_NO_KEY : + if (token_cursor->curr_size == sizeof(grn_id)) { + tid = *((grn_id *)token_cursor->curr); + } else { + tid = GRN_ID_NIL; + } + break; + } + } else if (token_cursor->mode != GRN_TOKENIZE_ONLY) { + switch (table->header.type) { + case GRN_TABLE_PAT_KEY : + tid = grn_pat_get(ctx, (grn_pat *)table, token_cursor->curr, token_cursor->curr_size, NULL); + break; + case GRN_TABLE_DAT_KEY : + tid = grn_dat_get(ctx, (grn_dat *)table, token_cursor->curr, token_cursor->curr_size, NULL); + break; + case GRN_TABLE_HASH_KEY : + tid = grn_hash_get(ctx, (grn_hash *)table, token_cursor->curr, token_cursor->curr_size, NULL); + break; + case GRN_TABLE_NO_KEY : + if (token_cursor->curr_size == sizeof(grn_id)) { + tid = *((grn_id *)token_cursor->curr); + } else { + tid = GRN_ID_NIL; + } + break; + } + } + if (token_cursor->mode != GRN_TOKENIZE_ONLY && + tid == GRN_ID_NIL && token_cursor->status != GRN_TOKEN_CURSOR_DONE) { + token_cursor->status = GRN_TOKEN_CURSOR_NOT_FOUND; + } + token_cursor->pos++; + break; + } + return tid; +} + +static void +grn_token_cursor_close_token_filters(grn_ctx *ctx, + grn_token_cursor *token_cursor) +{ + grn_obj *token_filters = token_cursor->token_filter.objects; + unsigned int i, n_token_filters; + + if (!token_cursor->token_filter.data) { + return; + } + + if (token_filters) { + n_token_filters = GRN_BULK_VSIZE(token_filters) / sizeof(grn_obj *); + } else { + n_token_filters = 0; + } + + if (n_token_filters == 0) { + return; + } + + for (i = 0; i < n_token_filters; i++) { + grn_obj *token_filter_object = GRN_PTR_VALUE_AT(token_filters, i); + grn_proc *token_filter = (grn_proc *)token_filter_object; + void *data = token_cursor->token_filter.data[i]; + + token_filter->callbacks.token_filter.fin(ctx, data); + } + GRN_FREE(token_cursor->token_filter.data); +} + +grn_rc +grn_token_cursor_close(grn_ctx *ctx, grn_token_cursor *token_cursor) +{ + if (token_cursor) { + if (token_cursor->tokenizer) { + ((grn_proc *)token_cursor->tokenizer)->funcs[PROC_FIN](ctx, 1, &token_cursor->table, + &token_cursor->pctx.user_data); + } + grn_token_cursor_close_token_filters(ctx, token_cursor); + if (token_cursor->nstr) { + grn_obj_close(ctx, token_cursor->nstr); + } + GRN_FREE(token_cursor); + return GRN_SUCCESS; + } else { + return GRN_INVALID_ARGUMENT; + } +} diff --git a/storage/mroonga/vendor/groonga/lib/token_filter.c b/storage/mroonga/vendor/groonga/lib/token_filter.c new file mode 100644 index 00000000..55367762 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/token_filter.c @@ -0,0 +1,59 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2014-2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include + +#include "grn.h" +#include "grn_db.h" +#include + +grn_rc +grn_token_filter_register(grn_ctx *ctx, + const char *plugin_name_ptr, + int plugin_name_length, + grn_token_filter_init_func *init, + grn_token_filter_filter_func *filter, + grn_token_filter_fin_func *fin) +{ + if (plugin_name_length == -1) { + plugin_name_length = strlen(plugin_name_ptr); + } + + { + grn_obj *token_filter_object = grn_proc_create(ctx, + plugin_name_ptr, + plugin_name_length, + GRN_PROC_TOKEN_FILTER, + NULL, NULL, NULL, 0, NULL); + if (token_filter_object == NULL) { + GRN_PLUGIN_ERROR(ctx, GRN_TOKEN_FILTER_ERROR, + "[token-filter][%.*s] failed to grn_proc_create()", + plugin_name_length, plugin_name_ptr); + return ctx->rc; + } + + { + grn_proc *token_filter = (grn_proc *)token_filter_object; + token_filter->callbacks.token_filter.init = init; + token_filter->callbacks.token_filter.filter = filter; + token_filter->callbacks.token_filter.fin = fin; + } + } + + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/tokenizer.c b/storage/mroonga/vendor/groonga/lib/tokenizer.c new file mode 100644 index 00000000..faf47fd6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/tokenizer.c @@ -0,0 +1,375 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2012-2014 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include "grn.h" +#include + +#include + +#include "grn_ctx.h" +#include "grn_db.h" +#include "grn_str.h" +#include "grn_string.h" +#include "grn_token_cursor.h" + +/* + Just for backward compatibility. See grn_plugin_charlen() instead. + */ +int +grn_tokenizer_charlen(grn_ctx *ctx, const char *str_ptr, + unsigned int str_length, grn_encoding encoding) +{ + return grn_plugin_charlen(ctx, str_ptr, str_length, encoding); +} + +/* + Just for backward compatibility. See grn_plugin_isspace() instead. + */ +int +grn_tokenizer_isspace(grn_ctx *ctx, const char *str_ptr, + unsigned int str_length, grn_encoding encoding) +{ + return grn_plugin_isspace(ctx, str_ptr, str_length, encoding); +} + +grn_bool +grn_tokenizer_is_tokenized_delimiter(grn_ctx *ctx, + const char *str_ptr, + unsigned int str_length, + grn_encoding encoding) +{ + if (encoding != GRN_ENC_UTF8) { + return GRN_FALSE; + } + + if (str_length != GRN_TOKENIZER_TOKENIZED_DELIMITER_UTF8_LEN) { + return GRN_FALSE; + } + + return memcmp(str_ptr, + GRN_TOKENIZER_TOKENIZED_DELIMITER_UTF8, + GRN_TOKENIZER_TOKENIZED_DELIMITER_UTF8_LEN) == 0; +} + +grn_bool +grn_tokenizer_have_tokenized_delimiter(grn_ctx *ctx, + const char *str_ptr, + unsigned int str_length, + grn_encoding encoding) +{ + int char_length; + const char *current = str_ptr; + const char *end = str_ptr + str_length; + + if (encoding != GRN_ENC_UTF8) { + return GRN_FALSE; + } + + if (str_length == 0) { + return GRN_FALSE; + } + + while ((char_length = grn_charlen_(ctx, current, end, encoding)) > 0) { + if (grn_tokenizer_is_tokenized_delimiter(ctx, + current, char_length, + encoding)) { + return GRN_TRUE; + } + current += char_length; + } + return GRN_FALSE; +} + +grn_tokenizer_query * +grn_tokenizer_query_open(grn_ctx *ctx, int num_args, grn_obj **args, + unsigned int normalize_flags) +{ + grn_obj *flags = grn_ctx_pop(ctx); + grn_obj *query_str = grn_ctx_pop(ctx); + grn_obj *tokenize_mode = grn_ctx_pop(ctx); + + if (query_str == NULL) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "missing argument"); + return NULL; + } + + if ((num_args < 1) || (args == NULL) || (args[0] == NULL)) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "invalid NULL pointer"); + return NULL; + } + + { + grn_tokenizer_query * const query = + GRN_PLUGIN_MALLOC(ctx, sizeof(grn_tokenizer_query)); + if (query == NULL) { + return NULL; + } + query->normalized_query = NULL; + query->query_buf = NULL; + if (flags) { + query->flags = GRN_UINT32_VALUE(flags); + } else { + query->flags = 0; + } + if (tokenize_mode) { + query->tokenize_mode = GRN_UINT32_VALUE(tokenize_mode); + } else { + query->tokenize_mode = GRN_TOKENIZE_ADD; + } + query->token_mode = query->tokenize_mode; + + { + grn_obj * const table = args[0]; + grn_table_flags table_flags; + grn_encoding table_encoding; + unsigned int query_length = GRN_TEXT_LEN(query_str); + char *query_buf = (char *)GRN_PLUGIN_MALLOC(ctx, query_length + 1); + grn_obj *normalizer = NULL; + + if (query_buf == NULL) { + GRN_PLUGIN_FREE(ctx, query); + GRN_PLUGIN_ERROR(ctx, GRN_TOKENIZER_ERROR, + "[tokenizer] failed to duplicate query"); + return NULL; + } + grn_table_get_info(ctx, table, &table_flags, &table_encoding, NULL, + &normalizer, NULL); + { + grn_obj *normalized_query; + if (table_flags & GRN_OBJ_KEY_NORMALIZE) { + normalizer = GRN_NORMALIZER_AUTO; + } + normalized_query = grn_string_open_(ctx, + GRN_TEXT_VALUE(query_str), + GRN_TEXT_LEN(query_str), + normalizer, + normalize_flags, + table_encoding); + if (!normalized_query) { + GRN_PLUGIN_FREE(ctx, query_buf); + GRN_PLUGIN_FREE(ctx, query); + GRN_PLUGIN_ERROR(ctx, GRN_TOKENIZER_ERROR, + "[tokenizer] failed to open normalized string"); + return NULL; + } + query->normalized_query = normalized_query; + grn_memcpy(query_buf, GRN_TEXT_VALUE(query_str), query_length); + query_buf[query_length] = '\0'; + query->query_buf = query_buf; + query->ptr = query_buf; + query->length = query_length; + } + query->encoding = table_encoding; + + if (query->flags & GRN_TOKEN_CURSOR_ENABLE_TOKENIZED_DELIMITER) { + const char *normalized_string; + unsigned int normalized_string_length; + + grn_string_get_normalized(ctx, + query->normalized_query, + &normalized_string, + &normalized_string_length, + NULL); + query->have_tokenized_delimiter = + grn_tokenizer_have_tokenized_delimiter(ctx, + normalized_string, + normalized_string_length, + query->encoding); + } else { + query->have_tokenized_delimiter = GRN_FALSE; + } + } + return query; + } +} + +grn_tokenizer_query * +grn_tokenizer_query_create(grn_ctx *ctx, int num_args, grn_obj **args) +{ + return grn_tokenizer_query_open(ctx, num_args, args, 0); +} + +void +grn_tokenizer_query_close(grn_ctx *ctx, grn_tokenizer_query *query) +{ + if (query != NULL) { + if (query->normalized_query != NULL) { + grn_obj_unlink(ctx, query->normalized_query); + } + if (query->query_buf != NULL) { + GRN_PLUGIN_FREE(ctx, query->query_buf); + } + GRN_PLUGIN_FREE(ctx, query); + } +} + +void +grn_tokenizer_query_destroy(grn_ctx *ctx, grn_tokenizer_query *query) +{ + grn_tokenizer_query_close(ctx, query); +} + +void +grn_tokenizer_token_init(grn_ctx *ctx, grn_tokenizer_token *token) +{ + GRN_TEXT_INIT(&token->str, GRN_OBJ_DO_SHALLOW_COPY); + GRN_UINT32_INIT(&token->status, 0); +} + +void +grn_tokenizer_token_fin(grn_ctx *ctx, grn_tokenizer_token *token) +{ + GRN_OBJ_FIN(ctx, &(token->str)); + GRN_OBJ_FIN(ctx, &(token->status)); +} + +void +grn_tokenizer_token_push(grn_ctx *ctx, grn_tokenizer_token *token, + const char *str_ptr, unsigned int str_length, + grn_token_status status) +{ + GRN_TEXT_SET_REF(&token->str, str_ptr, str_length); + GRN_UINT32_SET(ctx, &token->status, status); + grn_ctx_push(ctx, &token->str); + grn_ctx_push(ctx, &token->status); +} + +const char * +grn_tokenizer_tokenized_delimiter_next(grn_ctx *ctx, + grn_tokenizer_token *token, + const char *str_ptr, + unsigned int str_length, + grn_encoding encoding) +{ + size_t char_length = 0; + const char *start = str_ptr; + const char *current; + const char *end = str_ptr + str_length; + const char *next_start = NULL; + unsigned int token_length; + grn_token_status status; + + for (current = start; current < end; current += char_length) { + char_length = grn_charlen_(ctx, current, end, encoding); + if (char_length == 0) { + break; + } + if (grn_tokenizer_is_tokenized_delimiter(ctx, current, char_length, + encoding)) { + next_start = str_ptr + (current - start + char_length); + break; + } + } + + token_length = current - start; + if (current == end) { + status = GRN_TOKENIZER_LAST; + } else { + status = GRN_TOKENIZER_CONTINUE; + } + grn_tokenizer_token_push(ctx, token, start, token_length, status); + + return next_start; +} + +grn_rc +grn_tokenizer_register(grn_ctx *ctx, const char *plugin_name_ptr, + unsigned int plugin_name_length, + grn_proc_func *init, grn_proc_func *next, + grn_proc_func *fin) +{ + grn_expr_var vars[] = { + { NULL, 0 }, + { NULL, 0 }, + { NULL, 0 } + }; + GRN_TEXT_INIT(&vars[0].value, 0); + GRN_TEXT_INIT(&vars[1].value, 0); + GRN_UINT32_INIT(&vars[2].value, 0); + + { + /* + grn_proc_create() registers a plugin to the database which is associated + with `ctx'. A returned object must not be finalized here. + */ + grn_obj * const obj = grn_proc_create(ctx, plugin_name_ptr, + plugin_name_length, + GRN_PROC_TOKENIZER, + init, next, fin, 3, vars); + if (obj == NULL) { + GRN_PLUGIN_ERROR(ctx, GRN_TOKENIZER_ERROR, "grn_proc_create() failed"); + return ctx->rc; + } + } + return GRN_SUCCESS; +} + +grn_obj * +grn_token_get_data(grn_ctx *ctx, grn_token *token) +{ + GRN_API_ENTER; + if (!token) { + ERR(GRN_INVALID_ARGUMENT, "token must not be NULL"); + GRN_API_RETURN(NULL); + } + GRN_API_RETURN(&(token->data)); +} + +grn_rc +grn_token_set_data(grn_ctx *ctx, + grn_token *token, + const char *str_ptr, + int str_length) +{ + GRN_API_ENTER; + if (!token) { + ERR(GRN_INVALID_ARGUMENT, "token must not be NULL"); + goto exit; + } + if (str_length == -1) { + str_length = strlen(str_ptr); + } + GRN_TEXT_SET(ctx, &(token->data), str_ptr, str_length); +exit: + GRN_API_RETURN(ctx->rc); +} + +grn_token_status +grn_token_get_status(grn_ctx *ctx, grn_token *token) +{ + GRN_API_ENTER; + if (!token) { + ERR(GRN_INVALID_ARGUMENT, "token must not be NULL"); + GRN_API_RETURN(GRN_TOKEN_CONTINUE); + } + GRN_API_RETURN(token->status); +} + +grn_rc +grn_token_set_status(grn_ctx *ctx, + grn_token *token, + grn_token_status status) +{ + GRN_API_ENTER; + if (!token) { + ERR(GRN_INVALID_ARGUMENT, "token must not be NULL"); + goto exit; + } + token->status = status; +exit: + GRN_API_RETURN(ctx->rc); +} diff --git a/storage/mroonga/vendor/groonga/lib/tokenizers.c b/storage/mroonga/vendor/groonga/lib/tokenizers.c new file mode 100644 index 00000000..3daacce7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/tokenizers.c @@ -0,0 +1,890 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ +#include +#include "grn_token_cursor.h" +#include "grn_string.h" +#include "grn_plugin.h" +#include + +grn_obj *grn_tokenizer_uvector = NULL; + +typedef struct { + grn_tokenizer_token token; + byte *curr; + byte *tail; + uint32_t unit; +} grn_uvector_tokenizer; + +static grn_obj * +uvector_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_obj *str, *flags, *mode; + grn_uvector_tokenizer *tokenizer; + if (!(flags = grn_ctx_pop(ctx))) { + ERR(GRN_INVALID_ARGUMENT, "[tokenizer][uvector] missing argument: flags"); + return NULL; + } + if (!(str = grn_ctx_pop(ctx))) { + ERR(GRN_INVALID_ARGUMENT, "[tokenizer][uvector] missing argument: string"); + return NULL; + } + if (!(mode = grn_ctx_pop(ctx))) { + ERR(GRN_INVALID_ARGUMENT, "[tokenizer][uvector] missing argument: mode"); + return NULL; + } + if (!(tokenizer = GRN_MALLOC(sizeof(grn_uvector_tokenizer)))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[tokenizer][uvector] " + "memory allocation to grn_uvector_tokenizer failed"); + return NULL; + } + user_data->ptr = tokenizer; + + grn_tokenizer_token_init(ctx, &(tokenizer->token)); + tokenizer->curr = (byte *)GRN_TEXT_VALUE(str); + tokenizer->tail = tokenizer->curr + GRN_TEXT_LEN(str); + tokenizer->unit = sizeof(grn_id); + return NULL; +} + +static grn_obj * +uvector_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_uvector_tokenizer *tokenizer = user_data->ptr; + byte *p = tokenizer->curr + tokenizer->unit; + if (tokenizer->tail < p) { + grn_tokenizer_token_push(ctx, &(tokenizer->token), + (const char *)tokenizer->curr, 0, + GRN_TOKEN_LAST); + } else { + grn_token_status status; + if (tokenizer->tail == p) { + status = GRN_TOKEN_LAST; + } else { + status = GRN_TOKEN_CONTINUE; + } + grn_tokenizer_token_push(ctx, &(tokenizer->token), + (const char *)tokenizer->curr, tokenizer->unit, + status); + tokenizer->curr = p; + } + return NULL; +} + +static grn_obj * +uvector_fin(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_uvector_tokenizer *tokenizer = user_data->ptr; + if (!tokenizer) { + return NULL; + } + grn_tokenizer_token_fin(ctx, &(tokenizer->token)); + GRN_FREE(tokenizer); + return NULL; +} + +typedef struct { + const uint8_t *delimiter; + uint32_t delimiter_len; + const unsigned char *next; + const unsigned char *end; + grn_tokenizer_token token; + grn_tokenizer_query *query; + grn_bool have_tokenized_delimiter; +} grn_delimited_tokenizer; + +static grn_obj * +delimited_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data, + const uint8_t *delimiter, uint32_t delimiter_len) +{ + grn_tokenizer_query *query; + unsigned int normalize_flags = 0; + const char *normalized; + unsigned int normalized_length_in_bytes; + grn_delimited_tokenizer *tokenizer; + + query = grn_tokenizer_query_open(ctx, nargs, args, normalize_flags); + if (!query) { + return NULL; + } + + if (!(tokenizer = GRN_MALLOC(sizeof(grn_delimited_tokenizer)))) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "[tokenizer][delimit] " + "memory allocation to grn_delimited_tokenizer failed"); + grn_tokenizer_query_close(ctx, query); + return NULL; + } + user_data->ptr = tokenizer; + + tokenizer->query = query; + + tokenizer->have_tokenized_delimiter = + grn_tokenizer_have_tokenized_delimiter(ctx, + tokenizer->query->ptr, + tokenizer->query->length, + tokenizer->query->encoding); + tokenizer->delimiter = delimiter; + tokenizer->delimiter_len = delimiter_len; + grn_string_get_normalized(ctx, tokenizer->query->normalized_query, + &normalized, &normalized_length_in_bytes, + NULL); + tokenizer->next = (const unsigned char *)normalized; + tokenizer->end = tokenizer->next + normalized_length_in_bytes; + + grn_tokenizer_token_init(ctx, &(tokenizer->token)); + + return NULL; +} + +static grn_obj * +delimited_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_delimited_tokenizer *tokenizer = user_data->ptr; + + if (tokenizer->have_tokenized_delimiter) { + unsigned int rest_length; + rest_length = tokenizer->end - tokenizer->next; + tokenizer->next = + (unsigned char *)grn_tokenizer_tokenized_delimiter_next( + ctx, + &(tokenizer->token), + (const char *)tokenizer->next, + rest_length, + tokenizer->query->encoding); + } else { + size_t cl; + const unsigned char *p = tokenizer->next, *r; + const unsigned char *e = tokenizer->end; + grn_token_status status; + for (r = p; r < e; r += cl) { + if (!(cl = grn_charlen_(ctx, (char *)r, (char *)e, + tokenizer->query->encoding))) { + tokenizer->next = (unsigned char *)e; + break; + } + { + grn_bool found_delimiter = GRN_FALSE; + const unsigned char *current_end = r; + while (current_end + tokenizer->delimiter_len <= e && + !memcmp(current_end, + tokenizer->delimiter, tokenizer->delimiter_len)) { + current_end += tokenizer->delimiter_len; + tokenizer->next = current_end; + found_delimiter = GRN_TRUE; + } + if (found_delimiter) { + break; + } + } + } + if (r == e) { + status = GRN_TOKEN_LAST; + } else { + status = GRN_TOKEN_CONTINUE; + } + grn_tokenizer_token_push(ctx, + &(tokenizer->token), + (const char *)p, + r - p, + status); + } + + return NULL; +} + +static grn_obj * +delimited_fin(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_delimited_tokenizer *tokenizer = user_data->ptr; + if (!tokenizer) { + return NULL; + } + grn_tokenizer_query_close(ctx, tokenizer->query); + grn_tokenizer_token_fin(ctx, &(tokenizer->token)); + GRN_FREE(tokenizer); + return NULL; +} + +static grn_obj * +delimit_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + static const uint8_t delimiter[1] = {' '}; + return delimited_init(ctx, nargs, args, user_data, delimiter, 1); +} + +static grn_obj * +delimit_null_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + static const uint8_t delimiter[1] = {'\0'}; + return delimited_init(ctx, nargs, args, user_data, delimiter, 1); +} + +/* ngram tokenizer */ + +static grn_bool grn_ngram_tokenizer_remove_blank_disable = GRN_FALSE; + +typedef struct { + grn_tokenizer_token token; + grn_tokenizer_query *query; + uint8_t uni_alpha; + uint8_t uni_digit; + uint8_t uni_symbol; + uint8_t ngram_unit; + uint8_t ignore_blank; + uint8_t overlap; + int32_t pos; + uint32_t skip; + const unsigned char *next; + const unsigned char *end; + const uint_least8_t *ctypes; + uint32_t len; + uint32_t tail; +} grn_ngram_tokenizer; + +static grn_obj * +ngram_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data, uint8_t ngram_unit, + uint8_t uni_alpha, uint8_t uni_digit, uint8_t uni_symbol, uint8_t ignore_blank) +{ + unsigned int normalize_flags = + GRN_STRING_REMOVE_BLANK | + GRN_STRING_WITH_TYPES | + GRN_STRING_REMOVE_TOKENIZED_DELIMITER; + grn_tokenizer_query *query; + const char *normalized; + unsigned int normalized_length_in_bytes; + grn_ngram_tokenizer *tokenizer; + + if (grn_ngram_tokenizer_remove_blank_disable) { + normalize_flags &= ~GRN_STRING_REMOVE_BLANK; + } + query = grn_tokenizer_query_open(ctx, nargs, args, normalize_flags); + if (!query) { + return NULL; + } + + if (!(tokenizer = GRN_MALLOC(sizeof(grn_ngram_tokenizer)))) { + grn_tokenizer_query_close(ctx, query); + ERR(GRN_NO_MEMORY_AVAILABLE, + "[tokenizer][ngram] " + "memory allocation to grn_ngram_tokenizer failed"); + return NULL; + } + user_data->ptr = tokenizer; + + grn_tokenizer_token_init(ctx, &(tokenizer->token)); + tokenizer->query = query; + + tokenizer->uni_alpha = uni_alpha; + tokenizer->uni_digit = uni_digit; + tokenizer->uni_symbol = uni_symbol; + tokenizer->ngram_unit = ngram_unit; + tokenizer->ignore_blank = ignore_blank; + tokenizer->overlap = 0; + tokenizer->pos = 0; + tokenizer->skip = 0; + + grn_string_get_normalized(ctx, tokenizer->query->normalized_query, + &normalized, &normalized_length_in_bytes, + &(tokenizer->len)); + tokenizer->next = (const unsigned char *)normalized; + tokenizer->end = tokenizer->next + normalized_length_in_bytes; + tokenizer->ctypes = + grn_string_get_types(ctx, tokenizer->query->normalized_query); + return NULL; +} + +static grn_obj * +unigram_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 1, 1, 1, 1, 0); } + +static grn_obj * +bigram_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 2, 1, 1, 1, 0); } + +static grn_obj * +trigram_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 3, 1, 1, 1, 0); } + +static grn_obj * +bigrams_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 2, 1, 1, 0, 0); } + +static grn_obj * +bigramsa_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 2, 0, 1, 0, 0); } + +static grn_obj * +bigramsad_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 2, 0, 0, 0, 0); } + +static grn_obj * +bigrami_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 2, 1, 1, 1, 1); } + +static grn_obj * +bigramis_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 2, 1, 1, 0, 1); } + +static grn_obj * +bigramisa_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 2, 0, 1, 0, 1); } + +static grn_obj * +bigramisad_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ return ngram_init(ctx, nargs, args, user_data, 2, 0, 0, 0, 1); } + +static grn_obj * +ngram_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + size_t cl; + grn_ngram_tokenizer *tokenizer = user_data->ptr; + const unsigned char *p = tokenizer->next, *r = p, *e = tokenizer->end; + int32_t len = 0, pos = tokenizer->pos + tokenizer->skip; + grn_token_status status = 0; + const uint_least8_t *cp = tokenizer->ctypes ? tokenizer->ctypes + pos : NULL; + if (cp && tokenizer->uni_alpha && GRN_STR_CTYPE(*cp) == GRN_CHAR_ALPHA) { + while ((cl = grn_charlen_(ctx, (char *)r, (char *)e, + tokenizer->query->encoding))) { + len++; + r += cl; + if (/* !tokenizer->ignore_blank && */ GRN_STR_ISBLANK(*cp)) { break; } + if (GRN_STR_CTYPE(*++cp) != GRN_CHAR_ALPHA) { break; } + } + tokenizer->next = r; + tokenizer->overlap = 0; + } else if (cp && + tokenizer->uni_digit && + GRN_STR_CTYPE(*cp) == GRN_CHAR_DIGIT) { + while ((cl = grn_charlen_(ctx, (char *)r, (char *)e, + tokenizer->query->encoding))) { + len++; + r += cl; + if (/* !tokenizer->ignore_blank && */ GRN_STR_ISBLANK(*cp)) { break; } + if (GRN_STR_CTYPE(*++cp) != GRN_CHAR_DIGIT) { break; } + } + tokenizer->next = r; + tokenizer->overlap = 0; + } else if (cp && + tokenizer->uni_symbol && + GRN_STR_CTYPE(*cp) == GRN_CHAR_SYMBOL) { + while ((cl = grn_charlen_(ctx, (char *)r, (char *)e, + tokenizer->query->encoding))) { + len++; + r += cl; + if (!tokenizer->ignore_blank && GRN_STR_ISBLANK(*cp)) { break; } + if (GRN_STR_CTYPE(*++cp) != GRN_CHAR_SYMBOL) { break; } + } + tokenizer->next = r; + tokenizer->overlap = 0; + } else { +#ifdef PRE_DEFINED_UNSPLIT_WORDS + const unsigned char *key = NULL; + // todo : grn_pat_lcp_search + if ((tid = grn_sym_common_prefix_search(sym, p))) { + if (!(key = _grn_sym_key(sym, tid))) { + tokenizer->status = GRN_TOKEN_CURSOR_NOT_FOUND; + return NULL; + } + len = grn_str_len(key, tokenizer->query->encoding, NULL); + } + r = p + grn_charlen_(ctx, p, e, tokenizer->query->encoding); + if (tid && (len > 1 || r == p)) { + if (r != p && pos + len - 1 <= tokenizer->tail) { continue; } + p += strlen(key); + if (!*p && tokenizer->mode == GRN_TOKEN_GET) { + tokenizer->status = GRN_TOKEN_CURSOR_DONE; + } + } +#endif /* PRE_DEFINED_UNSPLIT_WORDS */ + if ((cl = grn_charlen_(ctx, (char *)r, (char *)e, + tokenizer->query->encoding))) { + len++; + r += cl; + tokenizer->next = r; + while (len < tokenizer->ngram_unit && + (cl = grn_charlen_(ctx, (char *)r, (char *)e, + tokenizer->query->encoding))) { + if (cp) { + if (!tokenizer->ignore_blank && GRN_STR_ISBLANK(*cp)) { break; } + cp++; + if ((tokenizer->uni_alpha && GRN_STR_CTYPE(*cp) == GRN_CHAR_ALPHA) || + (tokenizer->uni_digit && GRN_STR_CTYPE(*cp) == GRN_CHAR_DIGIT) || + (tokenizer->uni_symbol && GRN_STR_CTYPE(*cp) == GRN_CHAR_SYMBOL)) { + break; + } + } + len++; + r += cl; + } + if (tokenizer->overlap) { + status |= GRN_TOKEN_OVERLAP; + } + if (len < tokenizer->ngram_unit) { + status |= GRN_TOKEN_UNMATURED; + } + tokenizer->overlap = (len > 1) ? 1 : 0; + } + } + tokenizer->pos = pos; + tokenizer->len = len; + tokenizer->tail = pos + len - 1; + if (p == r || tokenizer->next == e) { + tokenizer->skip = 0; + status |= GRN_TOKEN_LAST; + } else { + tokenizer->skip = tokenizer->overlap ? 1 : len; + } + if (r == e) { status |= GRN_TOKEN_REACH_END; } + grn_tokenizer_token_push(ctx, + &(tokenizer->token), + (const char *)p, + r - p, + status); + return NULL; +} + +static grn_obj * +ngram_fin(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_ngram_tokenizer *tokenizer = user_data->ptr; + if (!tokenizer) { + return NULL; + } + grn_tokenizer_token_fin(ctx, &(tokenizer->token)); + grn_tokenizer_query_close(ctx, tokenizer->query); + GRN_FREE(tokenizer); + return NULL; +} + +/* regexp tokenizer */ + +typedef struct { + grn_tokenizer_token token; + grn_tokenizer_query *query; + struct { + int32_t n_skip_tokens; + } get; + grn_bool is_begin; + grn_bool is_end; + grn_bool is_start_token; + grn_bool is_overlapping; + const char *next; + const char *end; + unsigned int nth_char; + const uint_least8_t *char_types; + grn_obj buffer; +} grn_regexp_tokenizer; + +static grn_obj * +regexp_init(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + unsigned int normalize_flags = GRN_STRING_WITH_TYPES; + grn_tokenizer_query *query; + const char *normalized; + unsigned int normalized_length_in_bytes; + grn_regexp_tokenizer *tokenizer; + + query = grn_tokenizer_query_open(ctx, nargs, args, normalize_flags); + if (!query) { + return NULL; + } + + tokenizer = GRN_MALLOC(sizeof(grn_regexp_tokenizer)); + if (!tokenizer) { + grn_tokenizer_query_close(ctx, query); + ERR(GRN_NO_MEMORY_AVAILABLE, + "[tokenizer][regexp] failed to allocate memory"); + return NULL; + } + user_data->ptr = tokenizer; + + grn_tokenizer_token_init(ctx, &(tokenizer->token)); + tokenizer->query = query; + + tokenizer->get.n_skip_tokens = 0; + + tokenizer->is_begin = GRN_TRUE; + tokenizer->is_end = GRN_FALSE; + tokenizer->is_start_token = GRN_TRUE; + tokenizer->is_overlapping = GRN_FALSE; + + grn_string_get_normalized(ctx, tokenizer->query->normalized_query, + &normalized, &normalized_length_in_bytes, + NULL); + tokenizer->next = normalized; + tokenizer->end = tokenizer->next + normalized_length_in_bytes; + tokenizer->nth_char = 0; + tokenizer->char_types = + grn_string_get_types(ctx, tokenizer->query->normalized_query); + + GRN_TEXT_INIT(&(tokenizer->buffer), 0); + + return NULL; +} + +static grn_obj * +regexp_next(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + int char_len; + grn_token_status status = 0; + grn_regexp_tokenizer *tokenizer = user_data->ptr; + unsigned int n_characters = 0; + int ngram_unit = 2; + grn_obj *buffer = &(tokenizer->buffer); + const char *current = tokenizer->next; + const char *end = tokenizer->end; + const uint_least8_t *char_types = tokenizer->char_types; + grn_tokenize_mode mode = tokenizer->query->tokenize_mode; + grn_bool is_begin = tokenizer->is_begin; + grn_bool is_start_token = tokenizer->is_start_token; + grn_bool break_by_blank = GRN_FALSE; + grn_bool break_by_end_mark = GRN_FALSE; + + GRN_BULK_REWIND(buffer); + tokenizer->is_begin = GRN_FALSE; + tokenizer->is_start_token = GRN_FALSE; + + if (char_types) { + char_types += tokenizer->nth_char; + } + + if (mode != GRN_TOKEN_GET) { + if (is_begin) { + grn_tokenizer_token_push(ctx, + &(tokenizer->token), + GRN_TOKENIZER_BEGIN_MARK_UTF8, + GRN_TOKENIZER_BEGIN_MARK_UTF8_LEN, + status); + return NULL; + } + + if (tokenizer->is_end) { + status |= GRN_TOKEN_LAST | GRN_TOKEN_REACH_END; + grn_tokenizer_token_push(ctx, + &(tokenizer->token), + GRN_TOKENIZER_END_MARK_UTF8, + GRN_TOKENIZER_END_MARK_UTF8_LEN, + status); + return NULL; + } + if (is_start_token) { + if (char_types && GRN_STR_ISBLANK(char_types[-1])) { + status |= GRN_TOKEN_SKIP; + grn_tokenizer_token_push(ctx, &(tokenizer->token), "", 0, status); + return NULL; + } + } + } + + char_len = grn_charlen_(ctx, current, end, tokenizer->query->encoding); + if (char_len == 0) { + status |= GRN_TOKEN_LAST | GRN_TOKEN_REACH_END; + grn_tokenizer_token_push(ctx, &(tokenizer->token), "", 0, status); + return NULL; + } + + if (mode == GRN_TOKEN_GET) { + if (is_begin && + char_len == GRN_TOKENIZER_BEGIN_MARK_UTF8_LEN && + memcmp(current, GRN_TOKENIZER_BEGIN_MARK_UTF8, char_len) == 0) { + tokenizer->is_start_token = GRN_TRUE; + n_characters++; + GRN_TEXT_PUT(ctx, buffer, current, char_len); + current += char_len; + tokenizer->next = current; + tokenizer->nth_char++; + if (current == end) { + status |= GRN_TOKEN_LAST | GRN_TOKEN_REACH_END; + } + grn_tokenizer_token_push(ctx, + &(tokenizer->token), + GRN_TOKENIZER_BEGIN_MARK_UTF8, + GRN_TOKENIZER_BEGIN_MARK_UTF8_LEN, + status); + return NULL; + } + + if (current + char_len == end && + char_len == GRN_TOKENIZER_END_MARK_UTF8_LEN && + memcmp(current, GRN_TOKENIZER_END_MARK_UTF8, char_len) == 0) { + status |= GRN_TOKEN_LAST | GRN_TOKEN_REACH_END; + grn_tokenizer_token_push(ctx, + &(tokenizer->token), + GRN_TOKENIZER_END_MARK_UTF8, + GRN_TOKENIZER_END_MARK_UTF8_LEN, + status); + return NULL; + } + } + + while (GRN_TRUE) { + n_characters++; + GRN_TEXT_PUT(ctx, buffer, current, char_len); + current += char_len; + if (n_characters == 1) { + tokenizer->next = current; + tokenizer->nth_char++; + } + + if (char_types) { + uint_least8_t char_type; + char_type = char_types[0]; + char_types++; + if (GRN_STR_ISBLANK(char_type)) { + break_by_blank = GRN_TRUE; + } + } + + char_len = grn_charlen_(ctx, (const char *)current, (const char *)end, + tokenizer->query->encoding); + if (char_len == 0) { + break; + } + + if (mode == GRN_TOKEN_GET && + current + char_len == end && + char_len == GRN_TOKENIZER_END_MARK_UTF8_LEN && + memcmp(current, GRN_TOKENIZER_END_MARK_UTF8, char_len) == 0) { + break_by_end_mark = GRN_TRUE; + } + + if (break_by_blank || break_by_end_mark) { + break; + } + + if (n_characters == ngram_unit) { + break; + } + } + + if (tokenizer->is_overlapping) { + status |= GRN_TOKEN_OVERLAP; + } + if (n_characters < ngram_unit) { + status |= GRN_TOKEN_UNMATURED; + } + tokenizer->is_overlapping = (n_characters > 1); + + if (mode == GRN_TOKEN_GET) { + if (current == end) { + tokenizer->is_end = GRN_TRUE; + status |= GRN_TOKEN_LAST | GRN_TOKEN_REACH_END; + if (status & GRN_TOKEN_UNMATURED) { + status |= GRN_TOKEN_FORCE_PREFIX; + } + } else { + if (break_by_blank) { + tokenizer->get.n_skip_tokens = 0; + tokenizer->is_start_token = GRN_TRUE; + } else if (break_by_end_mark) { + if (!is_start_token && (status & GRN_TOKEN_UNMATURED)) { + status |= GRN_TOKEN_SKIP; + } + } else if (tokenizer->get.n_skip_tokens > 0) { + tokenizer->get.n_skip_tokens--; + status |= GRN_TOKEN_SKIP; + } else { + tokenizer->get.n_skip_tokens = ngram_unit - 1; + } + } + } else { + if (tokenizer->next == end) { + tokenizer->is_end = GRN_TRUE; + } + if (break_by_blank) { + tokenizer->is_start_token = GRN_TRUE; + } + } + + grn_tokenizer_token_push(ctx, + &(tokenizer->token), + GRN_TEXT_VALUE(buffer), + GRN_TEXT_LEN(buffer), + status); + + return NULL; +} + +static grn_obj * +regexp_fin(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data) +{ + grn_regexp_tokenizer *tokenizer = user_data->ptr; + if (!tokenizer) { + return NULL; + } + grn_tokenizer_token_fin(ctx, &(tokenizer->token)); + grn_tokenizer_query_close(ctx, tokenizer->query); + GRN_OBJ_FIN(ctx, &(tokenizer->buffer)); + GRN_FREE(tokenizer); + return NULL; +} + +/* external */ + +grn_rc +grn_tokenizers_init(void) +{ + static grn_proc _grn_tokenizer_uvector; + _grn_tokenizer_uvector.obj.db = NULL; + _grn_tokenizer_uvector.obj.id = GRN_ID_NIL; + _grn_tokenizer_uvector.obj.header.domain = GRN_ID_NIL; + _grn_tokenizer_uvector.obj.range = GRN_ID_NIL; + _grn_tokenizer_uvector.funcs[PROC_INIT] = uvector_init; + _grn_tokenizer_uvector.funcs[PROC_NEXT] = uvector_next; + _grn_tokenizer_uvector.funcs[PROC_FIN] = uvector_fin; + grn_tokenizer_uvector = (grn_obj *)&_grn_tokenizer_uvector; + return GRN_SUCCESS; +} + +grn_rc +grn_tokenizers_fin(void) +{ + return GRN_SUCCESS; +} + +grn_rc +grn_db_init_mecab_tokenizer(grn_ctx *ctx) +{ + switch (GRN_CTX_GET_ENCODING(ctx)) { + case GRN_ENC_EUC_JP : + case GRN_ENC_UTF8 : + case GRN_ENC_SJIS : +#if defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) + { + GRN_PLUGIN_DECLARE_FUNCTIONS(tokenizers_mecab); + grn_rc rc; + rc = GRN_PLUGIN_IMPL_NAME_TAGGED(init, tokenizers_mecab)(ctx); + if (rc == GRN_SUCCESS) { + rc = GRN_PLUGIN_IMPL_NAME_TAGGED(register, tokenizers_mecab)(ctx); + if (rc != GRN_SUCCESS) { + GRN_PLUGIN_IMPL_NAME_TAGGED(fin, tokenizers_mecab)(ctx); + } + } + return rc; + } +#else /* defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) */ + { + const char *mecab_plugin_name = "tokenizers/mecab"; + char *path; + path = grn_plugin_find_path(ctx, mecab_plugin_name); + if (path) { + GRN_FREE(path); + return grn_plugin_register(ctx, mecab_plugin_name); + } else { + return GRN_NO_SUCH_FILE_OR_DIRECTORY; + } + } +#endif /* defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) */ + break; + default : + return GRN_OPERATION_NOT_SUPPORTED; + } +} + +void +grn_db_fin_mecab_tokenizer(grn_ctx *ctx) +{ + switch (GRN_CTX_GET_ENCODING(ctx)) { + case GRN_ENC_EUC_JP : + case GRN_ENC_UTF8 : + case GRN_ENC_SJIS : +#if defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) + { + GRN_PLUGIN_DECLARE_FUNCTIONS(tokenizers_mecab); + GRN_PLUGIN_IMPL_NAME_TAGGED(fin, tokenizers_mecab)(ctx); + } +#else /* defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) */ + { + const char *mecab_plugin_name = "tokenizers/mecab"; + char *path; + path = grn_plugin_find_path(ctx, mecab_plugin_name); + if (path) { + GRN_FREE(path); + grn_plugin_unregister(ctx, mecab_plugin_name); + } + } +#endif /* defined(GRN_EMBEDDED) && defined(GRN_WITH_MECAB) */ + break; + default : + break; + } + return; +} + +#define DEF_TOKENIZER(name, init, next, fin, vars)\ + (grn_proc_create(ctx, (name), (sizeof(name) - 1),\ + GRN_PROC_TOKENIZER, (init), (next), (fin), 3, (vars))) + +grn_rc +grn_db_init_builtin_tokenizers(grn_ctx *ctx) +{ + grn_obj *obj; + grn_expr_var vars[] = { + {NULL, 0}, + {NULL, 0}, + {NULL, 0} + }; + GRN_TEXT_INIT(&vars[0].value, 0); + GRN_TEXT_INIT(&vars[1].value, 0); + GRN_UINT32_INIT(&vars[2].value, 0); + + { + char grn_ngram_tokenizer_remove_blank_disable_env[GRN_ENV_BUFFER_SIZE]; + + grn_getenv("GRN_NGRAM_TOKENIZER_REMOVE_BLANK_DISABLE", + grn_ngram_tokenizer_remove_blank_disable_env, + GRN_ENV_BUFFER_SIZE); + if (grn_ngram_tokenizer_remove_blank_disable_env[0]) { + grn_ngram_tokenizer_remove_blank_disable = GRN_TRUE; + } + } + + obj = DEF_TOKENIZER("TokenDelimit", + delimit_init, delimited_next, delimited_fin, vars); + if (!obj || ((grn_db_obj *)obj)->id != GRN_DB_DELIMIT) { return GRN_FILE_CORRUPT; } + obj = DEF_TOKENIZER("TokenUnigram", + unigram_init, ngram_next, ngram_fin, vars); + if (!obj || ((grn_db_obj *)obj)->id != GRN_DB_UNIGRAM) { return GRN_FILE_CORRUPT; } + obj = DEF_TOKENIZER("TokenBigram", + bigram_init, ngram_next, ngram_fin, vars); + if (!obj || ((grn_db_obj *)obj)->id != GRN_DB_BIGRAM) { return GRN_FILE_CORRUPT; } + obj = DEF_TOKENIZER("TokenTrigram", + trigram_init, ngram_next, ngram_fin, vars); + if (!obj || ((grn_db_obj *)obj)->id != GRN_DB_TRIGRAM) { return GRN_FILE_CORRUPT; } + + DEF_TOKENIZER("TokenBigramSplitSymbol", + bigrams_init, ngram_next, ngram_fin, vars); + DEF_TOKENIZER("TokenBigramSplitSymbolAlpha", + bigramsa_init, ngram_next, ngram_fin, vars); + DEF_TOKENIZER("TokenBigramSplitSymbolAlphaDigit", + bigramsad_init, ngram_next, ngram_fin, vars); + DEF_TOKENIZER("TokenBigramIgnoreBlank", + bigrami_init, ngram_next, ngram_fin, vars); + DEF_TOKENIZER("TokenBigramIgnoreBlankSplitSymbol", + bigramis_init, ngram_next, ngram_fin, vars); + DEF_TOKENIZER("TokenBigramIgnoreBlankSplitSymbolAlpha", + bigramisa_init, ngram_next, ngram_fin, vars); + DEF_TOKENIZER("TokenBigramIgnoreBlankSplitSymbolAlphaDigit", + bigramisad_init, ngram_next, ngram_fin, vars); + DEF_TOKENIZER("TokenDelimitNull", + delimit_null_init, delimited_next, delimited_fin, vars); + DEF_TOKENIZER("TokenRegexp", + regexp_init, regexp_next, regexp_fin, vars); + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/ts.c b/storage/mroonga/vendor/groonga/lib/ts.c new file mode 100644 index 00000000..909f4864 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts.c @@ -0,0 +1,906 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +/* TS is an acronym for "Turbo Selector". */ + +#include "grn_ts.h" + +#include "grn_output.h" +#include "grn_str.h" + +#include "ts/ts_buf.h" +#include "ts/ts_cursor.h" +#include "ts/ts_expr.h" +#include "ts/ts_expr_parser.h" +#include "ts/ts_log.h" +#include "ts/ts_sorter.h" +#include "ts/ts_str.h" +#include "ts/ts_types.h" +#include "ts/ts_util.h" + +#include + +/*------------------------------------------------------------- + * Miscellaneous. + */ + +enum { GRN_TS_BATCH_SIZE = 1024 }; + +/* grn_ts_bool_output() outputs a value. */ +static grn_rc +grn_ts_bool_output(grn_ctx *ctx, grn_ts_bool value) +{ + if (value) { + return grn_bulk_write(ctx, ctx->impl->output.buf, "true", 4); + } else { + return grn_bulk_write(ctx, ctx->impl->output.buf, "false", 5); + } +} + +/* grn_ts_int_output() outputs a value. */ +static grn_rc +grn_ts_int_output(grn_ctx *ctx, grn_ts_int value) +{ + return grn_text_lltoa(ctx, ctx->impl->output.buf, value); +} + +/* grn_ts_float_output() outputs a value. */ +static grn_rc +grn_ts_float_output(grn_ctx *ctx, grn_ts_float value) +{ + return grn_text_ftoa(ctx, ctx->impl->output.buf, value); +} + +/* grn_ts_time_output() outputs a value. */ +static grn_rc +grn_ts_time_output(grn_ctx *ctx, grn_ts_time value) +{ + return grn_text_ftoa(ctx, ctx->impl->output.buf, value * 0.000001); +} + +/* grn_ts_text_output() outputs a value. */ +static grn_rc +grn_ts_text_output(grn_ctx *ctx, grn_ts_text value) +{ + return grn_text_esc(ctx, ctx->impl->output.buf, value.ptr, value.size); +} + +/* grn_ts_geo_output() outputs a value. */ +static grn_rc +grn_ts_geo_output(grn_ctx *ctx, grn_ts_geo value) +{ + grn_rc rc = grn_bulk_write(ctx, ctx->impl->output.buf, "\"", 1); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_text_itoa(ctx, ctx->impl->output.buf, value.latitude); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_bulk_write(ctx, ctx->impl->output.buf, "x", 1); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_text_itoa(ctx, ctx->impl->output.buf, value.longitude); + if (rc != GRN_SUCCESS) { + return rc; + } + return grn_bulk_write(ctx, ctx->impl->output.buf, "\"", 1); +} + +#define GRN_TS_VECTOR_OUTPUT(kind)\ + size_t i;\ + grn_rc rc = grn_bulk_write(ctx, ctx->impl->output.buf, "[", 1);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + for (i = 0; i < value.size; ++i) {\ + if (i) {\ + rc = grn_bulk_write(ctx, ctx->impl->output.buf, ",", 1);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + rc = grn_ts_ ## kind ## _output(ctx, value.ptr[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + return grn_bulk_write(ctx, ctx->impl->output.buf, "]", 1); +/* grn_ts_bool_vector_output() outputs a value. */ +static grn_rc +grn_ts_bool_vector_output(grn_ctx *ctx, grn_ts_bool_vector value) +{ + GRN_TS_VECTOR_OUTPUT(bool) +} + +/* grn_ts_int_vector_output() outputs a value. */ +static grn_rc +grn_ts_int_vector_output(grn_ctx *ctx, grn_ts_int_vector value) +{ + GRN_TS_VECTOR_OUTPUT(int) +} + +/* grn_ts_float_vector_output() outputs a value. */ +static grn_rc +grn_ts_float_vector_output(grn_ctx *ctx, grn_ts_float_vector value) +{ + GRN_TS_VECTOR_OUTPUT(float) +} + +/* grn_ts_time_vector_output() outputs a value. */ +static grn_rc +grn_ts_time_vector_output(grn_ctx *ctx, grn_ts_time_vector value) +{ + GRN_TS_VECTOR_OUTPUT(time) +} + +/* grn_ts_text_vector_output() outputs a value. */ +static grn_rc +grn_ts_text_vector_output(grn_ctx *ctx, grn_ts_text_vector value) +{ + GRN_TS_VECTOR_OUTPUT(text) +} + +/* grn_ts_geo_vector_output() outputs a value. */ +static grn_rc +grn_ts_geo_vector_output(grn_ctx *ctx, grn_ts_geo_vector value) +{ + GRN_TS_VECTOR_OUTPUT(geo) +} +#undef GRN_TS_VECTOR_OUTPUT + +/*------------------------------------------------------------- + * grn_ts_writer. + */ + +typedef struct { + grn_ts_expr_parser *parser; + grn_ts_expr **exprs; + size_t n_exprs; + size_t max_n_exprs; + grn_obj name_buf; + grn_ts_str *names; + grn_ts_buf *bufs; +} grn_ts_writer; + +/* grn_ts_writer_init() initializes a writer. */ +static void +grn_ts_writer_init(grn_ctx *ctx, grn_ts_writer *writer) +{ + memset(writer, 0, sizeof(*writer)); + writer->parser = NULL; + writer->exprs = NULL; + GRN_TEXT_INIT(&writer->name_buf, GRN_OBJ_VECTOR); + writer->names = NULL; + writer->bufs = NULL; +} + +/* grn_ts_writer_fin() finalizes a writer. */ +static void +grn_ts_writer_fin(grn_ctx *ctx, grn_ts_writer *writer) +{ + size_t i; + if (writer->bufs) { + for (i = 0; i < writer->n_exprs; i++) { + grn_ts_buf_fin(ctx, &writer->bufs[i]); + } + GRN_FREE(writer->bufs); + } + if (writer->names) { + GRN_FREE(writer->names); + } + GRN_OBJ_FIN(ctx, &writer->name_buf); + if (writer->exprs) { + for (i = 0; i < writer->n_exprs; i++) { + grn_ts_expr_close(ctx, writer->exprs[i]); + } + GRN_FREE(writer->exprs); + } + if (writer->parser) { + grn_ts_expr_parser_close(ctx, writer->parser); + } +} + +/* grn_ts_writer_expand() expands a wildcard. */ +static grn_rc +grn_ts_writer_expand(grn_ctx *ctx, grn_ts_writer *writer, + grn_obj *table, grn_ts_str str) +{ + grn_rc rc = GRN_SUCCESS; + grn_hash_cursor *cursor; + grn_hash *hash = grn_hash_create(ctx, NULL, sizeof(grn_ts_id), 0, + GRN_OBJ_TABLE_HASH_KEY | GRN_HASH_TINY); + if (!hash) { + return GRN_INVALID_ARGUMENT; + } + grn_table_columns(ctx, table, str.ptr, str.size - 1, (grn_obj *)hash); + if (ctx->rc != GRN_SUCCESS) { + return ctx->rc; + } + cursor = grn_hash_cursor_open(ctx, hash, NULL, 0, NULL, 0, 0, -1, 0); + if (!cursor) { + rc = GRN_INVALID_ARGUMENT; + } else { + while (grn_hash_cursor_next(ctx, cursor) != GRN_ID_NIL) { + char name_buf[GRN_TABLE_MAX_KEY_SIZE]; + size_t name_size; + grn_obj *column; + grn_ts_id *column_id; + if (!grn_hash_cursor_get_key(ctx, cursor, (void **)&column_id)) { + rc = GRN_INVALID_ARGUMENT; + break; + } + column = grn_ctx_at(ctx, *column_id); + if (!column) { + rc = GRN_INVALID_ARGUMENT; + break; + } + name_size = grn_column_name(ctx, column, name_buf, sizeof(name_buf)); + grn_obj_unlink(ctx, column); + rc = grn_vector_add_element(ctx, &writer->name_buf, + name_buf, name_size, 0, GRN_DB_TEXT); + if (rc != GRN_SUCCESS) { + break; + } + } + grn_hash_cursor_close(ctx, cursor); + } + grn_hash_close(ctx, hash); + return rc; +} + +/* grn_ts_writer_parse() parses output expressions. */ +static grn_rc +grn_ts_writer_parse(grn_ctx *ctx, grn_ts_writer *writer, + grn_obj *table, grn_ts_str str) +{ + grn_rc rc; + grn_ts_str rest = str; + rc = grn_ts_expr_parser_open(ctx, table, &writer->parser); + for ( ; ; ) { + grn_ts_str first = { NULL, 0 }; + rc = grn_ts_expr_parser_split(ctx, writer->parser, rest, &first, &rest); + if (rc != GRN_SUCCESS) { + return (rc == GRN_END_OF_DATA) ? GRN_SUCCESS : rc; + } + if ((first.ptr[first.size - 1] == '*') && + grn_ts_str_is_name_prefix((grn_ts_str){ first.ptr, first.size - 1 })) { + rc = grn_ts_writer_expand(ctx, writer, table, first); + if (rc != GRN_SUCCESS) { + return rc; + } + } else if (grn_ts_str_is_key_name(first) && + !grn_ts_table_has_key(ctx, table)) { + /* + * Skip _key if the table has no _key, because the default output_columns + * option contains _key. + */ + GRN_TS_DEBUG("skip \"_key\" because the table has no _key"); + } else { + rc = grn_vector_add_element(ctx, &writer->name_buf, + first.ptr, first.size, 0, GRN_DB_TEXT); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + return GRN_SUCCESS; +} + +/* grn_ts_writer_build() builds output expresions. */ +static grn_rc +grn_ts_writer_build(grn_ctx *ctx, grn_ts_writer *writer, grn_obj *table) +{ + size_t i, n_names = grn_vector_size(ctx, &writer->name_buf); + if (!n_names) { + return GRN_SUCCESS; + } + writer->names = GRN_MALLOCN(grn_ts_str, n_names); + if (!writer->names) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x %" GRN_FMT_SIZE, + sizeof(grn_ts_str), n_names); + } + writer->exprs = GRN_MALLOCN(grn_ts_expr *, n_names); + if (!writer->exprs) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x %" GRN_FMT_SIZE, + sizeof(grn_ts_expr *), n_names); + } + for (i = 0; i < n_names; i++) { + grn_rc rc; + grn_ts_expr *new_expr; + const char *name_ptr; + size_t name_size = grn_vector_get_element(ctx, &writer->name_buf, i, + &name_ptr, NULL, NULL); + rc = grn_ts_expr_parser_parse(ctx, writer->parser, + (grn_ts_str){ name_ptr, name_size }, + &new_expr); + if (rc != GRN_SUCCESS) { + return rc; + } + writer->names[i].ptr = name_ptr; + writer->names[i].size = name_size; + writer->exprs[i] = new_expr; + writer->n_exprs++; + } + return GRN_SUCCESS; +} + +/* grn_ts_writer_open() creates a writer. */ +static grn_rc +grn_ts_writer_open(grn_ctx *ctx, grn_obj *table, grn_ts_str str, + grn_ts_writer **writer) +{ + grn_rc rc; + grn_ts_writer *new_writer = GRN_MALLOCN(grn_ts_writer, 1); + if (!new_writer) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_writer)); + } + grn_ts_writer_init(ctx, new_writer); + rc = grn_ts_writer_parse(ctx, new_writer, table, str); + if (rc == GRN_SUCCESS) { + rc = grn_ts_writer_build(ctx, new_writer, table); + } + if (rc != GRN_SUCCESS) { + grn_ts_writer_fin(ctx, new_writer); + GRN_FREE(new_writer); + return rc; + } + *writer = new_writer; + return GRN_SUCCESS; +} + +/* grn_ts_writer_close() destroys a writer. */ +static void +grn_ts_writer_close(grn_ctx *ctx, grn_ts_writer *writer) +{ + grn_ts_writer_fin(ctx, writer); + GRN_FREE(writer); +} + +/* TODO: Errors of output macros, such as GRN_TEXT_*(), are ignored. */ + +#define GRN_TS_WRITER_OUTPUT_HEADER_CASE(TYPE, name)\ + case GRN_DB_ ## TYPE: {\ + GRN_TEXT_PUTS(ctx, ctx->impl->output.buf, name);\ + break;\ + } +/* grn_ts_writer_output_header() outputs names and data types. */ +static grn_rc +grn_ts_writer_output_header(grn_ctx *ctx, grn_ts_writer *writer) +{ + grn_rc rc; + GRN_OUTPUT_ARRAY_OPEN("COLUMNS", writer->n_exprs); + for (size_t i = 0; i < writer->n_exprs; ++i) { + GRN_OUTPUT_ARRAY_OPEN("COLUMN", 2); + rc = grn_text_esc(ctx, ctx->impl->output.buf, + writer->names[i].ptr, writer->names[i].size); + if (rc != GRN_SUCCESS) { + return rc; + } + GRN_TEXT_PUT(ctx, ctx->impl->output.buf, ",\"", 2); + switch (writer->exprs[i]->data_type) { + case GRN_DB_VOID: { + if (writer->exprs[i]->data_kind == GRN_TS_GEO) { + GRN_TEXT_PUTS(ctx, ctx->impl->output.buf, "GeoPoint"); + } else { + GRN_TEXT_PUTS(ctx, ctx->impl->output.buf, "Void"); + } + break; + } + GRN_TS_WRITER_OUTPUT_HEADER_CASE(BOOL, "Bool") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(INT8, "Int8") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(INT16, "Int16") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(INT32, "Int32") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(INT64, "Int64") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(UINT8, "UInt8") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(UINT16, "UInt16") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(UINT32, "UInt32") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(UINT64, "UInt64") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(FLOAT, "Float") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(TIME, "Time") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(SHORT_TEXT, "ShortText") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(TEXT, "Text") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(LONG_TEXT, "LongText") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(TOKYO_GEO_POINT, "TokyoGeoPoint") + GRN_TS_WRITER_OUTPUT_HEADER_CASE(WGS84_GEO_POINT, "WGS84GeoPoint") + default: { + char name_buf[GRN_TABLE_MAX_KEY_SIZE]; + size_t name_size; + grn_obj *obj = grn_ctx_at(ctx, writer->exprs[i]->data_type); + if (!obj) { + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", + writer->exprs[i]->data_type); + } + if (!grn_ts_obj_is_table(ctx, obj)) { + grn_obj_unlink(ctx, obj); + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "not table: %d", + writer->exprs[i]->data_type); + } + name_size = grn_obj_name(ctx, obj, name_buf, sizeof(name_buf)); + GRN_TEXT_PUT(ctx, ctx->impl->output.buf, name_buf, name_size); + grn_obj_unlink(ctx, obj); + break; + } + } + GRN_TEXT_PUTC(ctx, ctx->impl->output.buf, '"'); + GRN_OUTPUT_ARRAY_CLOSE(); + } + GRN_OUTPUT_ARRAY_CLOSE(); /* COLUMNS. */ + return GRN_SUCCESS; +} +#undef GRN_TS_WRITER_OUTPUT_HEADER_CASE + +#define GRN_TS_WRITER_OUTPUT_BODY_CASE(KIND, kind)\ + case GRN_TS_ ## KIND: {\ + grn_ts_ ## kind *value = (grn_ts_ ## kind *)writer->bufs[j].ptr;\ + grn_ts_ ## kind ## _output(ctx, value[i]);\ + break;\ + } +#define GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(KIND, kind)\ + GRN_TS_WRITER_OUTPUT_BODY_CASE(KIND ## _VECTOR, kind ## _vector) +/* + * grn_ts_writer_output_body() evaluates expressions and outputs the results. + */ +static grn_rc +grn_ts_writer_output_body(grn_ctx *ctx, grn_ts_writer *writer, + const grn_ts_record *in, size_t n_in) +{ + size_t i, j, count = 0; + writer->bufs = GRN_MALLOCN(grn_ts_buf, writer->n_exprs); + if (!writer->bufs) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x %" GRN_FMT_SIZE, + sizeof(grn_ts_buf), writer->n_exprs); + } + for (i = 0; i < writer->n_exprs; i++) { + grn_ts_buf_init(ctx, &writer->bufs[i]); + } + while (count < n_in) { + size_t batch_size = GRN_TS_BATCH_SIZE; + if (batch_size > (n_in - count)) { + batch_size = n_in - count; + } + for (i = 0; i < writer->n_exprs; ++i) { + grn_rc rc = grn_ts_expr_evaluate_to_buf(ctx, writer->exprs[i], in + count, + batch_size, &writer->bufs[i]); + if (rc != GRN_SUCCESS) { + return rc; + } + } + for (i = 0; i < batch_size; ++i) { + GRN_OUTPUT_ARRAY_OPEN("HIT", writer->n_exprs); + for (j = 0; j < writer->n_exprs; ++j) { + if (j) { + GRN_TEXT_PUTC(ctx, ctx->impl->output.buf, ','); + } + switch (writer->exprs[j]->data_kind) { + GRN_TS_WRITER_OUTPUT_BODY_CASE(BOOL, bool); + GRN_TS_WRITER_OUTPUT_BODY_CASE(INT, int); + GRN_TS_WRITER_OUTPUT_BODY_CASE(FLOAT, float); + GRN_TS_WRITER_OUTPUT_BODY_CASE(TIME, time); + GRN_TS_WRITER_OUTPUT_BODY_CASE(TEXT, text); + GRN_TS_WRITER_OUTPUT_BODY_CASE(GEO, geo); + GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(BOOL, bool); + GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(INT, int); + GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(FLOAT, float); + GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(TIME, time); + GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(TEXT, text); + GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE(GEO, geo); + default: { + break; + } + } + } + GRN_OUTPUT_ARRAY_CLOSE(); /* HITS. */ + } + count += batch_size; + } + return GRN_SUCCESS; +} +#undef GRN_TS_WRITER_OUTPUT_BODY_VECTOR_CASE +#undef GRN_TS_WRITER_OUTPUT_BODY_CASE + +/* grn_ts_writer_output() outputs search results into the output buffer. */ +static grn_rc +grn_ts_writer_output(grn_ctx *ctx, grn_ts_writer *writer, + const grn_ts_record *in, size_t n_in, size_t n_hits) +{ + grn_rc rc; + GRN_OUTPUT_ARRAY_OPEN("RESULT", 1); + GRN_OUTPUT_ARRAY_OPEN("RESULTSET", 2 + n_in); + GRN_OUTPUT_ARRAY_OPEN("NHITS", 1); + rc = grn_text_ulltoa(ctx, ctx->impl->output.buf, n_hits); + if (rc != GRN_SUCCESS) { + return rc; + } + GRN_OUTPUT_ARRAY_CLOSE(); /* NHITS. */ + rc = grn_ts_writer_output_header(ctx, writer); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_writer_output_body(ctx, writer, in, n_in); + if (rc != GRN_SUCCESS) { + return rc; + } + GRN_OUTPUT_ARRAY_CLOSE(); /* RESULTSET. */ + GRN_OUTPUT_ARRAY_CLOSE(); /* RESET. */ + return GRN_SUCCESS; +} + +/* grn_ts_select_filter() applies a filter to all the records of a table. */ +static grn_rc +grn_ts_select_filter(grn_ctx *ctx, grn_obj *table, grn_ts_str str, + size_t offset, size_t limit, + grn_ts_record **out, size_t *n_out, size_t *n_hits) +{ + grn_rc rc; + grn_table_cursor *cursor_obj; + grn_ts_cursor *cursor; + grn_ts_expr *expr = NULL; + grn_ts_record *buf = NULL; + size_t buf_size = 0; + + *out = NULL; + *n_out = 0; + *n_hits = 0; + + cursor_obj = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, + GRN_CURSOR_ASCENDING | GRN_CURSOR_BY_ID); + if (!cursor_obj) { + return (ctx->rc != GRN_SUCCESS) ? ctx->rc : GRN_UNKNOWN_ERROR; + } + rc = grn_ts_obj_cursor_open(ctx, cursor_obj, &cursor); + if (rc != GRN_SUCCESS) { + grn_obj_close(ctx, cursor_obj); + return rc; + } + + if (str.size) { + rc = grn_ts_expr_parse(ctx, table, str, &expr); + } + if (rc == GRN_SUCCESS) { + for ( ; ; ) { + size_t batch_size; + grn_ts_record *batch; + + /* Extend the record buffer. */ + if (buf_size < (*n_out + GRN_TS_BATCH_SIZE)) { + size_t new_size = buf_size ? (buf_size * 2) : GRN_TS_BATCH_SIZE; + size_t n_bytes = sizeof(grn_ts_record) * new_size; + grn_ts_record *new_buf = (grn_ts_record *)GRN_REALLOC(buf, n_bytes); + if (!new_buf) { + GRN_TS_ERR(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, + n_bytes); + rc = ctx->rc; + break; + } + buf = new_buf; + buf_size = new_size; + } + + /* Read records from the cursor. */ + batch = buf + *n_out; + rc = grn_ts_cursor_read(ctx, cursor, batch, GRN_TS_BATCH_SIZE, + &batch_size); + if ((rc != GRN_SUCCESS) || !batch_size) { + break; + } + + /* Apply the filter. */ + if (expr) { + rc = grn_ts_expr_filter(ctx, expr, batch, batch_size, + batch, &batch_size); + if (rc != GRN_SUCCESS) { + break; + } + } + *n_hits += batch_size; + + /* Apply the offset and the limit. */ + if (offset) { + if (batch_size <= offset) { + offset -= batch_size; + batch_size = 0; + } else { + size_t n_bytes = sizeof(grn_ts_record) * (batch_size - offset); + grn_memmove(batch, batch + offset, n_bytes); + batch_size -= offset; + offset = 0; + } + } + if (batch_size <= limit) { + limit -= batch_size; + } else { + batch_size = limit; + limit = 0; + } + *n_out += batch_size; + } + /* Ignore a failure of destruction. */ + if (expr) { + grn_ts_expr_close(ctx, expr); + } + } + /* Ignore a failure of destruction. */ + grn_ts_cursor_close(ctx, cursor); + + if (rc != GRN_SUCCESS) { + if (buf) { + GRN_FREE(buf); + } + *n_out = 0; + *n_hits = 0; + return rc; + } + *out = buf; + return GRN_SUCCESS; +} + +/* grn_ts_select_scorer() adjust scores. */ +static grn_rc +grn_ts_select_scorer(grn_ctx *ctx, grn_obj *table, grn_ts_str str, + grn_ts_record *records, size_t n_records) +{ + grn_rc rc; + grn_ts_str rest; + grn_ts_expr *expr; + rest = grn_ts_str_trim_score_assignment(str); + if (!rest.size) { + return GRN_SUCCESS; + } + rc = grn_ts_expr_parse(ctx, table, rest, &expr); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_adjust(ctx, expr, records, n_records); + grn_ts_expr_close(ctx, expr); + return rc; +} + +/* grn_ts_select_output() outputs the results. */ +static grn_rc +grn_ts_select_output(grn_ctx *ctx, grn_obj *table, grn_ts_str str, + const grn_ts_record *in, size_t n_in, size_t n_hits) +{ + grn_ts_writer *writer= 0; + grn_rc rc = grn_ts_writer_open(ctx, table, str, &writer); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_writer_output(ctx, writer, in, n_in, n_hits); + grn_ts_writer_close(ctx, writer); + return rc; +} + +/* grn_ts_select_with_sortby() executes a select command with --sortby. */ +static grn_rc +grn_ts_select_with_sortby(grn_ctx *ctx, grn_obj *table, + grn_ts_str filter, grn_ts_str scorer, + grn_ts_str sortby, grn_ts_str output_columns, + size_t offset, size_t limit) +{ + grn_rc rc; + grn_ts_record *recs = NULL; + size_t n_recs = 0, max_n_recs = 0, n_hits = 0; + grn_table_cursor *cursor_obj; + grn_ts_cursor *cursor = NULL; + grn_ts_expr *filter_expr = NULL; + grn_ts_expr *scorer_expr = NULL; + grn_ts_sorter *sorter = NULL; + cursor_obj = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, + GRN_CURSOR_ASCENDING | GRN_CURSOR_BY_ID); + if (!cursor_obj) { + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_table_cursor_open failed"); + } + rc = grn_ts_obj_cursor_open(ctx, cursor_obj, &cursor); + if (rc != GRN_SUCCESS) { + grn_obj_close(ctx, cursor_obj); + return rc; + } + if (filter.size) { + rc = grn_ts_expr_parse(ctx, table, filter, &filter_expr); + } + if (rc == GRN_SUCCESS) { + scorer = grn_ts_str_trim_score_assignment(scorer); + if (scorer.size) { + rc = grn_ts_expr_parse(ctx, table, scorer, &scorer_expr); + } + if (rc == GRN_SUCCESS) { + rc = grn_ts_sorter_parse(ctx, table, sortby, offset, limit, &sorter); + } + } + if (rc == GRN_SUCCESS) { + size_t n_pending_recs = 0; + for ( ; ; ) { + size_t batch_size; + grn_ts_record *batch; + /* Extend a buffer for records. */ + if (max_n_recs < (n_recs + GRN_TS_BATCH_SIZE)) { + size_t n_bytes, new_max_n_recs = max_n_recs * 2; + grn_ts_record *new_recs; + if (!new_max_n_recs) { + new_max_n_recs = GRN_TS_BATCH_SIZE; + } + n_bytes = sizeof(grn_ts_record) * new_max_n_recs; + new_recs = (grn_ts_record *)GRN_REALLOC(recs, n_bytes); + if (!new_recs) { + GRN_TS_ERR(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, + n_bytes); + rc = ctx->rc; + break; + } + recs = new_recs; + max_n_recs = new_max_n_recs; + } + /* Read records from a cursor. */ + batch = recs + n_recs; + rc = grn_ts_cursor_read(ctx, cursor, batch, GRN_TS_BATCH_SIZE, + &batch_size); + if (rc != GRN_SUCCESS) { + break; + } else if (!batch_size) { + /* Apply a scorer and complete sorting. */ + if (scorer_expr) { + rc = grn_ts_expr_adjust(ctx, scorer_expr, + recs + n_recs - n_pending_recs, + n_pending_recs); + if (rc != GRN_SUCCESS) { + break; + } + } + if (n_pending_recs) { + rc = grn_ts_sorter_progress(ctx, sorter, recs, n_recs, &n_recs); + if (rc != GRN_SUCCESS) { + break; + } + } + rc = grn_ts_sorter_complete(ctx, sorter, recs, n_recs, &n_recs); + break; + } + /* Apply a filter. */ + if (filter_expr) { + rc = grn_ts_expr_filter(ctx, filter_expr, batch, batch_size, + batch, &batch_size); + if (rc != GRN_SUCCESS) { + break; + } + } + n_hits += batch_size; + n_recs += batch_size; + n_pending_recs += batch_size; + /* + * Apply a scorer and progress sorting if there are enough pending + * records. + */ + if (n_pending_recs >= GRN_TS_BATCH_SIZE) { + if (scorer_expr) { + rc = grn_ts_expr_adjust(ctx, scorer_expr, + recs + n_recs - n_pending_recs, + n_pending_recs); + if (rc != GRN_SUCCESS) { + break; + } + } + rc = grn_ts_sorter_progress(ctx, sorter, recs, n_recs, &n_recs); + if (rc != GRN_SUCCESS) { + break; + } + n_pending_recs = 0; + } + } + } + if (rc == GRN_SUCCESS) { + rc = grn_ts_select_output(ctx, table, output_columns, + recs, n_recs, n_hits); + } + if (cursor) { + grn_ts_cursor_close(ctx, cursor); + } + if (recs) { + GRN_FREE(recs); + } + if (sorter) { + grn_ts_sorter_close(ctx, sorter); + } + if (scorer_expr) { + grn_ts_expr_close(ctx, scorer_expr); + } + if (filter_expr) { + grn_ts_expr_close(ctx, filter_expr); + } + return rc; +} + +/* + * grn_ts_select_without_sortby() executes a select command without --sortby. + */ +static grn_rc +grn_ts_select_without_sortby(grn_ctx *ctx, grn_obj *table, + grn_ts_str filter, grn_ts_str scorer, + grn_ts_str output_columns, + size_t offset, size_t limit) +{ + grn_rc rc; + grn_ts_record *records = NULL; + size_t n_records, n_hits; + rc = grn_ts_select_filter(ctx, table, filter, offset, limit, + &records, &n_records, &n_hits); + if (rc == GRN_SUCCESS) { + rc = grn_ts_select_scorer(ctx, table, scorer, records, n_records); + if (rc == GRN_SUCCESS) { + rc = grn_ts_select_output(ctx, table, output_columns, + records, n_records, n_hits); + } + } + if (records) { + GRN_FREE(records); + } + return rc; +} + +/*------------------------------------------------------------- + * API. + */ + +grn_rc +grn_ts_select(grn_ctx *ctx, grn_obj *table, + const char *filter_ptr, size_t filter_len, + const char *scorer_ptr, size_t scorer_len, + const char *sortby_ptr, size_t sortby_len, + const char *output_columns_ptr, size_t output_columns_len, + size_t offset, size_t limit) +{ + grn_rc rc; + grn_ts_str filter = { filter_ptr, filter_len }; + grn_ts_str scorer = { scorer_ptr, scorer_len }; + grn_ts_str sortby = { sortby_ptr, sortby_len }; + grn_ts_str output_columns = { output_columns_ptr, output_columns_len }; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || + (!filter_ptr && filter_len) || (!scorer_ptr && scorer_len) || + (!sortby_ptr && sortby_len) || + (!output_columns_ptr && output_columns_len)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + filter = grn_ts_str_trim_left(filter); + if (sortby_len) { + rc = grn_ts_select_with_sortby(ctx, table, filter, scorer, sortby, + output_columns, offset, limit); + } else { + rc = grn_ts_select_without_sortby(ctx, table, filter, scorer, + output_columns, offset, limit); + } + if (rc != GRN_SUCCESS) { + GRN_BULK_REWIND(ctx->impl->output.buf); + if ((ctx->rc == GRN_SUCCESS) || !ctx->errbuf[0]) { + ERR(rc, "error message is missing"); + } else if (ctx->errlvl < GRN_LOG_ERROR) { + ctx->errlvl = GRN_LOG_ERROR; + } + } + return rc; +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/Makefile.am b/storage/mroonga/vendor/groonga/lib/ts/Makefile.am new file mode 100644 index 00000000..f1f21df4 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/Makefile.am @@ -0,0 +1,20 @@ +BUNDLED_LIBRARIES_CFLAGS = \ + $(MRUBY_CFLAGS) \ + $(ONIGMO_CFLAGS) + +DEFAULT_INCLUDES = \ + -I$(top_builddir) \ + -I$(top_srcdir)/include \ + $(BUNDLED_LIBRARIES_CFLAGS) + +AM_CFLAGS = \ + $(NO_STRICT_ALIASING_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(GRN_CFLAGS) \ + $(MESSAGE_PACK_CFLAGS) + +noinst_LTLIBRARIES = libgrnts.la + +include sources.am + +CLEANFILES = *.gcno *.gcda diff --git a/storage/mroonga/vendor/groonga/lib/ts/sources.am b/storage/mroonga/vendor/groonga/lib/ts/sources.am new file mode 100644 index 00000000..5d89b059 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/sources.am @@ -0,0 +1,25 @@ +libgrnts_la_SOURCES = \ + ts_buf.c \ + ts_buf.h \ + ts_cursor.c \ + ts_cursor.h \ + ts_expr.c \ + ts_expr.h \ + ts_expr_builder.c \ + ts_expr_builder.h \ + ts_expr_node.c \ + ts_expr_node.h \ + ts_expr_parser.c \ + ts_expr_parser.h \ + ts_log.h \ + ts_op.c \ + ts_op.h \ + ts_plan.c \ + ts_plan.h \ + ts_sorter.c \ + ts_sorter.h \ + ts_str.c \ + ts_str.h \ + ts_types.h \ + ts_util.c \ + ts_util.h diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_buf.c b/storage/mroonga/vendor/groonga/lib/ts/ts_buf.c new file mode 100644 index 00000000..65521d71 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_buf.c @@ -0,0 +1,244 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_buf.h" + +#include "../grn_ctx.h" + +#include "ts_log.h" + +#include + +/*------------------------------------------------------------- + * grn_ts_buf + */ + +void +grn_ts_buf_init(grn_ctx *ctx, grn_ts_buf *buf) +{ + buf->ptr = NULL; + buf->size = 0; + buf->pos = 0; +} + +/* +grn_rc +grn_ts_buf_open(grn_ctx *ctx, grn_ts_buf **buf) +{ + grn_ts_buf *new_buf = GRN_MALLOCN(grn_ts_buf, 1); + if (!new_buf) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_buf)); + } + grn_ts_buf_init(ctx, new_buf); + *buf = new_buf; + return GRN_SUCCESS; +} +*/ + +void +grn_ts_buf_fin(grn_ctx *ctx, grn_ts_buf *buf) +{ + if (buf->ptr) { + GRN_FREE(buf->ptr); + } +} + +/* +void +grn_ts_buf_close(grn_ctx *ctx, grn_ts_buf *buf) +{ + if (buf) { + grn_ts_buf_fin(ctx, buf); + } +} +*/ + +grn_rc +grn_ts_buf_reserve(grn_ctx *ctx, grn_ts_buf *buf, size_t min_size) +{ + void *new_ptr; + size_t enough_size; + if (min_size <= buf->size) { + return GRN_SUCCESS; + } + enough_size = buf->size ? (buf->size << 1) : 1; + while (enough_size < min_size) { + if ((enough_size << 1) < enough_size) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "size overflow: %" GRN_FMT_SIZE, + min_size); + } + enough_size <<= 1; + } + new_ptr = GRN_REALLOC(buf->ptr, enough_size); + if (!new_ptr) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, + enough_size); + } + buf->ptr = new_ptr; + buf->size = enough_size; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_buf_resize(grn_ctx *ctx, grn_ts_buf *buf, size_t new_size) +{ + void *new_ptr; + if (new_size == buf->size) { + return GRN_SUCCESS; + } + if (!new_size) { + if (buf->ptr) { + GRN_FREE(buf->ptr); + buf->ptr = NULL; + buf->size = new_size; + } + return GRN_SUCCESS; + } + new_ptr = GRN_REALLOC(buf->ptr, new_size); + if (!new_ptr) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, + new_size); + } + buf->ptr = new_ptr; + buf->size = new_size; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_buf_write(grn_ctx *ctx, grn_ts_buf *buf, const void *ptr, size_t size) +{ + size_t new_pos = buf->pos + size; + if (new_pos < buf->pos) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "size overflow: %" GRN_FMT_SIZE " + %" GRN_FMT_SIZE, + buf->pos, size); + } + if (new_pos > buf->size) { + grn_rc rc = grn_ts_buf_reserve(ctx, buf, new_pos); + if (rc != GRN_SUCCESS) { + return rc; + } + } + grn_memcpy((char *)buf->ptr + buf->pos, ptr, size); + buf->pos += size; + return GRN_SUCCESS; +} + +/*------------------------------------------------------------- + * grn_ts_rbuf + */ + +void +grn_ts_rbuf_init(grn_ctx *ctx, grn_ts_rbuf *rbuf) +{ + rbuf->recs = NULL; + rbuf->n_recs = 0; + rbuf->max_n_recs = 0; +} + +void +grn_ts_rbuf_fin(grn_ctx *ctx, grn_ts_rbuf *rbuf) +{ + if (rbuf->recs) { + GRN_FREE(rbuf->recs); + } +} + +grn_rc +grn_ts_rbuf_open(grn_ctx *ctx, grn_ts_rbuf **rbuf) +{ + grn_ts_rbuf *new_rbuf = GRN_MALLOCN(grn_ts_rbuf, 1); + if (!new_rbuf) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_rbuf)); + } + grn_ts_rbuf_init(ctx, new_rbuf); + *rbuf = new_rbuf; + return GRN_SUCCESS; +} + +void +grn_ts_rbuf_close(grn_ctx *ctx, grn_ts_rbuf *rbuf) +{ + if (rbuf) { + grn_ts_rbuf_fin(ctx, rbuf); + } +} + +grn_rc +grn_ts_rbuf_reserve(grn_ctx *ctx, grn_ts_rbuf *rbuf, size_t min_max_n_recs) +{ + size_t n_bytes, enough_max_n_recs; + grn_ts_record *new_recs; + if (min_max_n_recs <= rbuf->max_n_recs) { + return GRN_SUCCESS; + } + enough_max_n_recs = rbuf->max_n_recs ? (rbuf->max_n_recs << 1) : 1; + while (enough_max_n_recs < min_max_n_recs) { + if ((enough_max_n_recs << 1) < enough_max_n_recs) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "size overflow: %" GRN_FMT_SIZE, + min_max_n_recs); + } + enough_max_n_recs <<= 1; + } + n_bytes = sizeof(grn_ts_record) * enough_max_n_recs; + new_recs = GRN_REALLOC(rbuf->recs, n_bytes); + if (!new_recs) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, + n_bytes); + } + rbuf->recs = new_recs; + rbuf->max_n_recs = enough_max_n_recs; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_rbuf_resize(grn_ctx *ctx, grn_ts_rbuf *rbuf, size_t new_max_n_recs) +{ + size_t n_bytes; + grn_ts_record *new_recs; + if (new_max_n_recs == rbuf->max_n_recs) { + return GRN_SUCCESS; + } + if (!new_max_n_recs) { + if (rbuf->recs) { + GRN_FREE(rbuf->recs); + rbuf->recs = NULL; + rbuf->max_n_recs = new_max_n_recs; + } + return GRN_SUCCESS; + } + n_bytes = sizeof(grn_ts_record) * new_max_n_recs; + new_recs = GRN_REALLOC(rbuf->recs, n_bytes); + if (!new_recs) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, + new_max_n_recs); + } + rbuf->recs = new_recs; + rbuf->max_n_recs = new_max_n_recs; + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_buf.h b/storage/mroonga/vendor/groonga/lib/ts/ts_buf.h new file mode 100644 index 00000000..f8077f0f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_buf.h @@ -0,0 +1,111 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*------------------------------------------------------------- + * grn_ts_buf + */ + +/* grn_ts_buf works as a buffer for arbitrary data. */ + +typedef struct { + void *ptr; /* The starting address. */ + size_t size; /* The size in bytes. */ + size_t pos; /* The current position for grn_ts_buf_write(). */ +} grn_ts_buf; + +/* grn_ts_buf_init() initializes a buffer. */ +void grn_ts_buf_init(grn_ctx *ctx, grn_ts_buf *buf); + +/* grn_ts_buf_fin() finalizes a buffer. */ +void grn_ts_buf_fin(grn_ctx *ctx, grn_ts_buf *buf); + +#if 0 +/* grn_ts_buf_open() creates a buffer. */ +grn_rc grn_ts_buf_open(grn_ctx *ctx, grn_ts_buf **buf); + +/* grn_ts_buf_close() destroys a buffer. */ +void grn_ts_buf_close(grn_ctx *ctx, grn_ts_buf *buf); +#endif + +/* + * grn_ts_buf_reserve() reserves enough memory to store `min_size` bytes. + * Note that this function never shrinks a buffer and does nothing if + * `min_size` is not greater than `buf->size`. + */ +grn_rc grn_ts_buf_reserve(grn_ctx *ctx, grn_ts_buf *buf, size_t min_size); + +/* grn_ts_buf_resize() resizes a buffer. */ +grn_rc grn_ts_buf_resize(grn_ctx *ctx, grn_ts_buf *buf, size_t new_size); + +/* + * grn_ts_buf_write() writes data into a buffer. `buf->pos` specifies the + * position and it will be modified on success. + * Note that this function resizes a buffer if required. + */ +grn_rc grn_ts_buf_write(grn_ctx *ctx, grn_ts_buf *buf, + const void *ptr, size_t size); + +/*------------------------------------------------------------- + * grn_ts_rbuf + */ + +/* grn_ts_rbuf works as a buffer for records. */ + +typedef struct { + grn_ts_record *recs; /* Pointer to records. */ + size_t n_recs; /* The number of records. */ + size_t max_n_recs; /* The maximum number of records. */ +} grn_ts_rbuf; + +/* grn_ts_rbuf_init() initializes a buffer. */ +void grn_ts_rbuf_init(grn_ctx *ctx, grn_ts_rbuf *rbuf); + +/* grn_ts_rbuf_fin() finalizes a buffer. */ +void grn_ts_rbuf_fin(grn_ctx *ctx, grn_ts_rbuf *rbuf); + +/* grn_ts_rbuf_open() creates a buffer. */ +/*grn_rc grn_ts_rbuf_open(grn_ctx *ctx, grn_ts_rbuf **rbuf);*/ + +/* grn_ts_rbuf_close() destroys a buffer. */ +/*void grn_ts_rbuf_close(grn_ctx *ctx, grn_ts_rbuf *rbuf);*/ + +/* + * grn_ts_rbuf_reserve() reserves enough memory to store `n_recs` records. + * Note that this function never shrinks a buffer and does nothing if `n_recs` + * is not greater than the `rbuf->max_n_recs`. + */ +grn_rc grn_ts_rbuf_reserve(grn_ctx *ctx, grn_ts_rbuf *rbuf, size_t n_recs); + +/* grn_ts_rbuf_resize() resizes a buffer. */ +grn_rc grn_ts_rbuf_resize(grn_ctx *ctx, grn_ts_rbuf *rbuf, + size_t new_max_n_recs); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_cursor.c b/storage/mroonga/vendor/groonga/lib/ts/ts_cursor.c new file mode 100644 index 00000000..779e4cae --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_cursor.c @@ -0,0 +1,163 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_cursor.h" + +#include "../grn_ctx.h" +#include "../grn_dat.h" +#include "../grn_hash.h" +#include "../grn_pat.h" + +#include "ts_log.h" +#include "ts_util.h" + +/*------------------------------------------------------------- + * grn_ts_obj_cursor. + */ + +typedef struct { + GRN_TS_CURSOR_COMMON_MEMBERS + grn_obj *obj; /* Wrapped cursor object. */ +} grn_ts_obj_cursor; + +grn_rc +grn_ts_obj_cursor_open(grn_ctx *ctx, grn_obj *obj, grn_ts_cursor **cursor) +{ + grn_ts_obj_cursor *new_cursor; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!obj || !cursor) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + switch (obj->header.type) { + case GRN_CURSOR_TABLE_HASH_KEY: + case GRN_CURSOR_TABLE_PAT_KEY: + case GRN_CURSOR_TABLE_DAT_KEY: + case GRN_CURSOR_TABLE_NO_KEY: { + break; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + } + new_cursor = GRN_MALLOCN(grn_ts_obj_cursor, 1); + if (!new_cursor) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_obj_cursor)); + } + new_cursor->type = GRN_TS_OBJ_CURSOR; + new_cursor->obj = obj; + *cursor = (grn_ts_cursor *)new_cursor; + return GRN_SUCCESS; +} + +/* grn_ts_obj_cursor_close() destroys a wrapper cursor. */ +static grn_rc +grn_ts_obj_cursor_close(grn_ctx *ctx, grn_ts_obj_cursor *cursor) +{ + if (cursor->obj) { + grn_obj_close(ctx, cursor->obj); + } + GRN_FREE(cursor); + return GRN_SUCCESS; +} + +#define GRN_TS_OBJ_CURSOR_READ(type)\ + size_t i;\ + grn_ ## type ## _cursor *obj = (grn_ ## type ## _cursor *)cursor->obj;\ + for (i = 0; i < max_n_recs; i++) {\ + recs[i].id = grn_ ## type ## _cursor_next(ctx, obj);\ + if (!recs[i].id) {\ + break;\ + }\ + recs[i].score = 0;\ + }\ + *n_recs = i;\ + return GRN_SUCCESS; +/* grn_ts_obj_cursor_read() reads records from a wrapper cursor. */ +static grn_rc +grn_ts_obj_cursor_read(grn_ctx *ctx, grn_ts_obj_cursor *cursor, + grn_ts_record *recs, size_t max_n_recs, size_t *n_recs) +{ + switch (cursor->obj->header.type) { + case GRN_CURSOR_TABLE_HASH_KEY: { + GRN_TS_OBJ_CURSOR_READ(hash) + } + case GRN_CURSOR_TABLE_PAT_KEY: { + GRN_TS_OBJ_CURSOR_READ(pat) + } + case GRN_CURSOR_TABLE_DAT_KEY: { + GRN_TS_OBJ_CURSOR_READ(dat) + } + case GRN_CURSOR_TABLE_NO_KEY: { + GRN_TS_OBJ_CURSOR_READ(array) + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + } + return GRN_SUCCESS; +} + +/*------------------------------------------------------------- + * grn_ts_cursor. + */ + +grn_rc +grn_ts_cursor_close(grn_ctx *ctx, grn_ts_cursor *cursor) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!cursor) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + switch (cursor->type) { + case GRN_TS_OBJ_CURSOR: { + return grn_ts_obj_cursor_close(ctx, (grn_ts_obj_cursor *)cursor); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid cursor type: %d", + cursor->type); + } + } +} + +grn_rc +grn_ts_cursor_read(grn_ctx *ctx, grn_ts_cursor *cursor, + grn_ts_record *out, size_t max_n_out, size_t *n_out) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!cursor || (!out && max_n_out) || !n_out) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + switch (cursor->type) { + case GRN_TS_OBJ_CURSOR: { + return grn_ts_obj_cursor_read(ctx, (grn_ts_obj_cursor *)cursor, + out, max_n_out, n_out); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid cursor type: %d", + cursor->type); + } + } +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_cursor.h b/storage/mroonga/vendor/groonga/lib/ts/ts_cursor.h new file mode 100644 index 00000000..f12034f7 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_cursor.h @@ -0,0 +1,59 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + GRN_TS_OBJ_CURSOR /* Wrapper cursor. */ +} grn_ts_cursor_type; + +#define GRN_TS_CURSOR_COMMON_MEMBERS\ + grn_ts_cursor_type type; /* Cursor type. */ + +typedef struct { + GRN_TS_CURSOR_COMMON_MEMBERS +} grn_ts_cursor; + +/* + * grn_ts_obj_cursor_open() creates a wrapper cursor. + * The new cursor will be a wrapper for a Groonga cursor specified by `obj`. + * On success, `obj` will be closed in grn_ts_cursor_close(). + * On failure, `obj` is left as is. + */ +grn_rc grn_ts_obj_cursor_open(grn_ctx *ctx, grn_obj *obj, + grn_ts_cursor **cursor); + +/* grn_ts_cursor_close() destroys a cursor. */ +grn_rc grn_ts_cursor_close(grn_ctx *ctx, grn_ts_cursor *cursor); + +/* grn_ts_cursor_read() reads records from a cursor. */ +grn_rc grn_ts_cursor_read(grn_ctx *ctx, grn_ts_cursor *cursor, + grn_ts_record *out, size_t max_n_out, size_t *n_out); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_expr.c b/storage/mroonga/vendor/groonga/lib/ts/ts_expr.c new file mode 100644 index 00000000..16576fbc --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_expr.c @@ -0,0 +1,219 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_expr.h" + +#include + +#include "../grn_ctx.h" + +#include "ts_log.h" +#include "ts_str.h" +#include "ts_util.h" +#include "ts_expr_parser.h" + +/* grn_ts_expr_init() initializes an expression. */ +static void +grn_ts_expr_init(grn_ctx *ctx, grn_ts_expr *expr) +{ + memset(expr, 0, sizeof(*expr)); + expr->table = NULL; + expr->root = NULL; +} + +/* grn_ts_expr_fin() finalizes an expression. */ +static void +grn_ts_expr_fin(grn_ctx *ctx, grn_ts_expr *expr) +{ + if (expr->root) { + grn_ts_expr_node_close(ctx, expr->root); + } + if (expr->table) { + grn_obj_unlink(ctx, expr->table); + } +} + +grn_rc +grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_node *root, + grn_ts_expr **expr) +{ + grn_rc rc; + grn_ts_expr *new_expr; + grn_ts_expr_type type; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || !root || !expr) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + switch (root->type) { + case GRN_TS_EXPR_ID_NODE: { + type = GRN_TS_EXPR_ID; + break; + } + case GRN_TS_EXPR_SCORE_NODE: { + type = GRN_TS_EXPR_SCORE; + break; + } + case GRN_TS_EXPR_KEY_NODE: + case GRN_TS_EXPR_VALUE_NODE: { + type = GRN_TS_EXPR_VARIABLE; + break; + } + case GRN_TS_EXPR_CONST_NODE: { + type = GRN_TS_EXPR_CONST; + break; + } + case GRN_TS_EXPR_COLUMN_NODE: + case GRN_TS_EXPR_OP_NODE: + case GRN_TS_EXPR_BRIDGE_NODE: { + type = GRN_TS_EXPR_VARIABLE; + break; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + } + new_expr = GRN_MALLOCN(grn_ts_expr, 1); + if (!new_expr) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE, + sizeof(grn_ts_expr)); + } + rc = grn_ts_obj_increment_ref_count(ctx, table); + if (rc != GRN_SUCCESS) { + GRN_FREE(new_expr); + return rc; + } + grn_ts_expr_init(ctx, new_expr); + new_expr->table = table; + new_expr->type = type; + new_expr->data_kind = root->data_kind; + new_expr->data_type = root->data_type; + new_expr->root = root; + *expr = new_expr; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, grn_ts_str str, + grn_ts_expr **expr) +{ + grn_rc rc; + grn_ts_expr *new_expr; + grn_ts_expr_parser *parser; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || + (!str.ptr && str.size) || !expr) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_parser_open(ctx, table, &parser); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_parser_parse(ctx, parser, str, &new_expr); + grn_ts_expr_parser_close(ctx, parser); + if (rc != GRN_SUCCESS) { + return rc; + } + *expr = new_expr; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_close(grn_ctx *ctx, grn_ts_expr *expr) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!expr) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + grn_ts_expr_fin(ctx, expr); + GRN_FREE(expr); + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr *expr, + const grn_ts_record *in, size_t n_in, + grn_ts_buf *out) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!expr || (!in && n_in) || !out) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + if (!n_in) { + return GRN_SUCCESS; + } + return grn_ts_expr_node_evaluate_to_buf(ctx, expr->root, in, n_in, out); +} + +grn_rc +grn_ts_expr_evaluate(grn_ctx *ctx, grn_ts_expr *expr, + const grn_ts_record *in, size_t n_in, void *out) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!expr || (!in && n_in) || (n_in && !out)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + if (!n_in) { + return GRN_SUCCESS; + } + return grn_ts_expr_node_evaluate(ctx, expr->root, in, n_in, out); +} + +grn_rc +grn_ts_expr_filter(grn_ctx *ctx, grn_ts_expr *expr, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!expr || (!in && n_in) || !out || !n_out) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + if (!n_in) { + *n_out = 0; + return GRN_SUCCESS; + } + return grn_ts_expr_node_filter(ctx, expr->root, in, n_in, out, n_out); +} + +grn_rc +grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr, + grn_ts_record *io, size_t n_io) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!expr || (!io && n_io)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + if (!n_io) { + return GRN_SUCCESS; + } + return grn_ts_expr_node_adjust(ctx, expr->root, io, n_io); +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_expr.h b/storage/mroonga/vendor/groonga/lib/ts/ts_expr.h new file mode 100644 index 00000000..b50e886d --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_expr.h @@ -0,0 +1,87 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#include "ts_buf.h" +#include "ts_expr_node.h" +#include "ts_str.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*------------------------------------------------------------- + * Enumeration types. + */ + +typedef enum { + GRN_TS_EXPR_ID, /* IDs (_id). */ + GRN_TS_EXPR_SCORE, /* Scores (_score). */ + GRN_TS_EXPR_CONST, /* A const. */ + GRN_TS_EXPR_VARIABLE /* An expression that contains a variable. */ +} grn_ts_expr_type; + +/*------------------------------------------------------------- + * Expression components. + */ + +typedef struct { + grn_obj *table; /* Associated table. */ + grn_ts_expr_type type; /* Expression type. */ + grn_ts_data_kind data_kind; /* Abstract data type. */ + grn_ts_data_type data_type; /* Detailed data type. */ + grn_ts_expr_node *root; /* Root node. */ +} grn_ts_expr; + +/* grn_ts_expr_open() creates an expression. */ +grn_rc grn_ts_expr_open(grn_ctx *ctx, grn_obj *table, grn_ts_expr_node *root, + grn_ts_expr **expr); + +/* grn_ts_expr_parse() parses a string and creates an expression. */ +grn_rc grn_ts_expr_parse(grn_ctx *ctx, grn_obj *table, grn_ts_str str, + grn_ts_expr **expr); + +/* grn_ts_expr_close() destroys an expression. */ +grn_rc grn_ts_expr_close(grn_ctx *ctx, grn_ts_expr *expr); + +/* grn_ts_expr_evaluate() evaluates an expression. */ +grn_rc grn_ts_expr_evaluate(grn_ctx *ctx, grn_ts_expr *expr, + const grn_ts_record *in, size_t n_in, void *out); + +/* grn_ts_expr_evaluate_to_buf() evaluates an expression. */ +grn_rc grn_ts_expr_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr *expr, + const grn_ts_record *in, size_t n_in, + grn_ts_buf *out); + +/* grn_ts_expr_filter() filters records. */ +grn_rc grn_ts_expr_filter(grn_ctx *ctx, grn_ts_expr *expr, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out); + +/* grn_ts_expr_adjust() updates scores. */ +grn_rc grn_ts_expr_adjust(grn_ctx *ctx, grn_ts_expr *expr, + grn_ts_record *io, size_t n_io); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_expr_builder.c b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_builder.c new file mode 100644 index 00000000..a742e062 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_builder.c @@ -0,0 +1,757 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_expr_builder.h" + +#include + +#include "../grn_ctx.h" +#include "../grn_db.h" + +#include "ts_log.h" +#include "ts_util.h" + +/*------------------------------------------------------------- + * grn_ts_expr_bridge. + */ + +/* grn_ts_expr_bridge_init() initializes a bridge. */ +static void +grn_ts_expr_bridge_init(grn_ctx *ctx, grn_ts_expr_bridge *bridge) +{ + memset(bridge, 0, sizeof(*bridge)); + bridge->src_table = NULL; + bridge->dest_table = NULL; +} + +/* grn_ts_expr_bridge_fin() finalizes a bridge. */ +static void +grn_ts_expr_bridge_fin(grn_ctx *ctx, grn_ts_expr_bridge *bridge) +{ + if (bridge->dest_table) { + grn_obj_unlink(ctx, bridge->dest_table); + } + /* Note: bridge->src_table does not increment a reference count. */ +} + +/*------------------------------------------------------------- + * grn_ts_expr_builder. + */ + +/* grn_ts_expr_builder_init() initializes an expression builder. */ +static void +grn_ts_expr_builder_init(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + memset(builder, 0, sizeof(*builder)); + builder->table = NULL; + builder->curr_table = NULL; + builder->nodes = NULL; + builder->bridges = NULL; +} + +/* grn_ts_expr_builder_fin() finalizes an expression builder. */ +static void +grn_ts_expr_builder_fin(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + size_t i; + if (builder->bridges) { + for (i = 0; i < builder->n_bridges; i++) { + grn_ts_expr_bridge_fin(ctx, &builder->bridges[i]); + } + GRN_FREE(builder->bridges); + } + if (builder->nodes) { + for (i = 0; i < builder->n_nodes; i++) { + if (builder->nodes[i]) { + grn_ts_expr_node_close(ctx, builder->nodes[i]); + } + } + GRN_FREE(builder->nodes); + } + /* Note: builder->curr_table does not increment a reference count. */ + if (builder->table) { + grn_obj_unlink(ctx, builder->table); + } +} + +grn_rc +grn_ts_expr_builder_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_builder **builder) +{ + grn_rc rc; + grn_ts_expr_builder *new_builder; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || !builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + new_builder = GRN_MALLOCN(grn_ts_expr_builder, 1); + if (!new_builder) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE, + sizeof(grn_ts_expr_builder)); + } + rc = grn_ts_obj_increment_ref_count(ctx, table); + if (rc != GRN_SUCCESS) { + GRN_FREE(new_builder); + return rc; + } + grn_ts_expr_builder_init(ctx, new_builder); + new_builder->table = table; + new_builder->curr_table = table; + *builder = new_builder; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_close(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + grn_ts_expr_builder_fin(ctx, builder); + GRN_FREE(builder); + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_complete(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_expr **expr) +{ + grn_rc rc; + grn_ts_expr *new_expr; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || (builder->n_nodes != 1) || builder->n_bridges || !expr) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_node_deref(ctx, &builder->nodes[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_open(ctx, builder->table, builder->nodes[0], &new_expr); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->n_nodes = 0; + *expr = new_expr; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_clear(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + size_t i; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + if (builder->bridges) { + for (i = 0; i < builder->n_bridges; i++) { + grn_ts_expr_bridge_fin(ctx, &builder->bridges[i]); + } + builder->n_bridges = 0; + } + if (builder->nodes) { + for (i = 0; i < builder->n_nodes; i++) { + if (builder->nodes[i]) { + grn_ts_expr_node_close(ctx, builder->nodes[i]); + } + } + builder->n_nodes = 0; + } + builder->curr_table = builder->table; + return GRN_SUCCESS; +} + +/* + * grn_ts_expr_builder_push_node() pushes a node. + * The given node will be closed on failure. + */ +static grn_rc +grn_ts_expr_builder_push_node(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_expr_node *node) +{ + if (builder->n_nodes == builder->max_n_nodes) { + size_t n_bytes, new_max_n_nodes; + grn_ts_expr_node **new_nodes; + new_max_n_nodes = builder->n_nodes ? (builder->n_nodes * 2) : 1; + n_bytes = sizeof(grn_ts_expr_node *) * new_max_n_nodes; + new_nodes = (grn_ts_expr_node **)GRN_REALLOC(builder->nodes, n_bytes); + if (!new_nodes) { + grn_ts_expr_node_close(ctx, node); + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, n_bytes); + } + builder->nodes = new_nodes; + builder->max_n_nodes = new_max_n_nodes; + } + builder->nodes[builder->n_nodes++] = node; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_push_name(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_str name) +{ + grn_obj *column; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || !grn_ts_str_is_name(name)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + if (grn_ts_str_is_id_name(name)) { + return grn_ts_expr_builder_push_id(ctx, builder); + } + if (grn_ts_str_is_score_name(name)) { + return grn_ts_expr_builder_push_score(ctx, builder); + } + if (grn_ts_str_is_key_name(name)) { + return grn_ts_expr_builder_push_key(ctx, builder); + } + if (grn_ts_str_is_value_name(name)) { + return grn_ts_expr_builder_push_value(ctx, builder); + } + /* grn_obj_column() returns a column or accessor. */ + column = grn_obj_column(ctx, builder->curr_table, name.ptr, name.size); + if (!column) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "object not found: \"%.*s\"", + (int)name.size, name.ptr); + } + return grn_ts_expr_builder_push_obj(ctx, builder, column); +} + +#define GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(TYPE, KIND, kind)\ + case GRN_DB_ ## TYPE: {\ + value.as_ ## kind = (grn_ts_ ## kind)GRN_ ## TYPE ## _VALUE(obj);\ + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_ ## KIND,\ + obj->header.domain, value);\ + } +/* grn_ts_expr_push_builder_bulk() pushes a scalar const. */ +static grn_rc +grn_ts_expr_builder_push_bulk(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj) +{ + grn_ts_any value; + switch (obj->header.domain) { + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(BOOL, BOOL, bool) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(INT8, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(INT16, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(INT32, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(INT64, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(UINT8, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(UINT16, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(UINT32, INT, int) + /* The behavior is undefined if a value is greater than 2^63 - 1. */ + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(UINT64, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(FLOAT, FLOAT, float) + GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE(TIME, TIME, time) + case GRN_DB_SHORT_TEXT: + case GRN_DB_TEXT: + case GRN_DB_LONG_TEXT: { + value.as_text.ptr = GRN_TEXT_VALUE(obj); + value.as_text.size = GRN_TEXT_LEN(obj); + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_TEXT, + obj->header.domain, value); + } + case GRN_DB_TOKYO_GEO_POINT: + case GRN_DB_WGS84_GEO_POINT: { + GRN_GEO_POINT_VALUE(obj, value.as_geo.latitude, value.as_geo.longitude); + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_GEO, + obj->header.domain, value); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "not bulk"); + } + } +} +#undef GRN_TS_EXPR_BUILDER_PUSH_BULK_CASE + +#define GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(TYPE, KIND, kind)\ + case GRN_DB_ ## TYPE: {\ + value.as_ ## kind ## _vector.ptr = (grn_ts_ ## kind *)GRN_BULK_HEAD(obj);\ + value.as_ ## kind ## _vector.size = grn_uvector_size(ctx, obj);\ + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_ ## KIND,\ + obj->header.domain, value);\ + } +#define GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(TYPE, KIND, kind)\ + case GRN_DB_ ## TYPE: {\ + size_t i;\ + grn_rc rc;\ + grn_ts_ ## kind *buf;\ + grn_ts_ ## kind ## _vector vector = { NULL, grn_uvector_size(ctx, obj) };\ + if (!vector.size) {\ + value.as_ ## kind ## _vector = vector;\ + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_ ## KIND,\ + obj->header.domain, value);\ + }\ + buf = GRN_MALLOCN(grn_ts_ ## kind, vector.size);\ + if (!buf) {\ + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE,\ + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1",\ + sizeof(grn_ts_ ## kind));\ + }\ + for (i = 0; i < vector.size; i++) {\ + buf[i] = GRN_ ## TYPE ##_VALUE_AT(obj, i);\ + }\ + vector.ptr = buf;\ + value.as_ ## kind ## _vector = vector;\ + rc = grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_ ## KIND,\ + obj->header.domain, value);\ + GRN_FREE(buf);\ + return rc;\ + } +/* grn_ts_expr_builder_push_uvector() pushes an array of fixed-size values. */ +static grn_rc +grn_ts_expr_builder_push_uvector(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj) +{ + grn_ts_any value; + switch (obj->header.domain) { + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(BOOL, BOOL, bool) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT8, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT16, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(INT32, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(INT64, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT8, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT16, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST(UINT32, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(UINT64, INT, int) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(TIME, TIME, time) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(TOKYO_GEO_POINT, GEO, geo) + GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE(WGS84_GEO_POINT, GEO, geo) + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", + obj->header.domain); + } + } +} +#undef GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE_WITH_TYPECAST +#undef GRN_TS_EXPR_BUILDER_PUSH_UVECTOR_CASE + +/* grn_ts_expr_builder_push_vector() pushes a Text vector. */ +static grn_rc +grn_ts_expr_builder_push_vector(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj) +{ + switch (obj->header.domain) { + case GRN_DB_SHORT_TEXT: + case GRN_DB_TEXT: + case GRN_DB_LONG_TEXT: { + size_t i; + grn_rc rc; + grn_ts_any value; + grn_ts_text *buf; + grn_ts_text_vector vector = { NULL, grn_vector_size(ctx, obj) }; + if (!vector.size) { + value.as_text_vector = vector; + return grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_TEXT_VECTOR, + obj->header.domain, value); + } + buf = GRN_MALLOCN(grn_ts_text, vector.size); + if (!buf) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: " + "%" GRN_FMT_SIZE " x %" GRN_FMT_SIZE, + sizeof(grn_ts_text), vector.size); + } + for (i = 0; i < vector.size; i++) { + buf[i].size = grn_vector_get_element(ctx, obj, i, &buf[i].ptr, + NULL, NULL); + } + vector.ptr = buf; + value.as_text_vector = vector; + rc = grn_ts_expr_builder_push_const(ctx, builder, GRN_TS_TEXT_VECTOR, + obj->header.domain, value); + GRN_FREE(buf); + return rc; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data type: %d", + obj->header.domain); + } + } +} + +static grn_rc +grn_ts_expr_builder_push_single_accessor(grn_ctx *ctx, + grn_ts_expr_builder *builder, + grn_accessor *accessor) +{ + switch (accessor->action) { + case GRN_ACCESSOR_GET_ID: { + return grn_ts_expr_builder_push_id(ctx, builder); + } + case GRN_ACCESSOR_GET_SCORE: { + return grn_ts_expr_builder_push_score(ctx, builder); + } + case GRN_ACCESSOR_GET_KEY: { + if (accessor->obj != builder->curr_table) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); + } + return grn_ts_expr_builder_push_key(ctx, builder); + } + case GRN_ACCESSOR_GET_VALUE: { + if (accessor->obj != builder->curr_table) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table conflict"); + } + return grn_ts_expr_builder_push_value(ctx, builder); + } + case GRN_ACCESSOR_GET_COLUMN_VALUE: { + return grn_ts_expr_builder_push_column(ctx, builder, accessor->obj); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid accessor action: %d", + accessor->action); + } + } +} + +static grn_rc +grn_ts_expr_builder_push_accessor(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_accessor *accessor) +{ + grn_rc rc = grn_ts_expr_builder_push_single_accessor(ctx, builder, accessor); + if (rc != GRN_SUCCESS) { + return rc; + } + for (accessor = accessor->next; accessor; accessor = accessor->next) { + rc = grn_ts_expr_builder_begin_subexpr(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_builder_push_single_accessor(ctx, builder, accessor); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_builder_end_subexpr(ctx, builder); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_push_obj(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || !obj) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + switch (obj->header.type) { + case GRN_BULK: { + return grn_ts_expr_builder_push_bulk(ctx, builder, obj); + } + case GRN_UVECTOR: { + return grn_ts_expr_builder_push_uvector(ctx, builder, obj); + } + case GRN_VECTOR: { + return grn_ts_expr_builder_push_vector(ctx, builder, obj); + } + case GRN_ACCESSOR: { + return grn_ts_expr_builder_push_accessor(ctx, builder, + (grn_accessor *)obj); + } + case GRN_COLUMN_FIX_SIZE: + case GRN_COLUMN_VAR_SIZE: { + return grn_ts_expr_builder_push_column(ctx, builder, obj); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid object type: %d", + obj->header.type); + } + } +} + +grn_rc +grn_ts_expr_builder_push_id(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_id_node_open(ctx, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_score(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_score_node_open(ctx, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_key(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_key_node_open(ctx, builder->curr_table, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_value(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_value_node_open(ctx, builder->curr_table, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_const(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_data_kind kind, grn_ts_data_type type, + grn_ts_any value) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_const_node_open(ctx, kind, type, value, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +grn_rc +grn_ts_expr_builder_push_column(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *column) +{ + grn_rc rc; + grn_ts_expr_node *node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || !column || !grn_ts_obj_is_column(ctx, column) || + (DB_OBJ(builder->curr_table)->id != column->header.domain)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_column_node_open(ctx, column, &node); + if (rc == GRN_SUCCESS) { + rc = grn_ts_expr_builder_push_node(ctx, builder, node); + } + return rc; +} + +/* + * grn_ts_expr_builder_get_max_n_args() returns the number of nodes in the + * current subexpression. + */ +static size_t +grn_ts_expr_builder_get_max_n_args(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + size_t max_n_args = builder->n_nodes; + if (builder->n_bridges) { + max_n_args -= builder->bridges[builder->n_bridges - 1].n_nodes; + } + return max_n_args; +} + +grn_rc +grn_ts_expr_builder_push_op(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_op_type op_type) +{ + grn_rc rc; + grn_ts_expr_node **args, *node; + size_t n_args, max_n_args; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + n_args = grn_ts_op_get_n_args(op_type); + if (!n_args) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "invalid #arguments: %" GRN_FMT_SIZE, + n_args); + } + max_n_args = grn_ts_expr_builder_get_max_n_args(ctx, builder); + if (n_args > max_n_args) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "invalid #arguments: %" GRN_FMT_SIZE ", %" GRN_FMT_SIZE, + n_args, builder->n_nodes); + } + /* Arguments are the top n_args nodes in the stack. */ + args = &builder->nodes[builder->n_nodes - n_args]; + builder->n_nodes -= n_args; + rc = grn_ts_expr_op_node_open(ctx, op_type, args, n_args, &node); + if (rc == GRN_SUCCESS) { + builder->nodes[builder->n_nodes++] = node; + } + return rc; +} + +/* grn_ts_expr_builder_push_bridge() pushes a bridge. */ +static grn_rc +grn_ts_expr_builder_push_bridge(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_expr_bridge *bridge) +{ + if (builder->n_bridges == builder->max_n_bridges) { + size_t n_bytes, new_max_n_bridges; + grn_ts_expr_bridge *new_bridges; + new_max_n_bridges = builder->n_bridges ? (builder->n_bridges * 2) : 1; + n_bytes = sizeof(grn_ts_expr_bridge) * new_max_n_bridges; + new_bridges = (grn_ts_expr_bridge *)GRN_REALLOC(builder->bridges, n_bytes); + if (!new_bridges) { + grn_ts_expr_bridge_fin(ctx, bridge); + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, n_bytes); + } + builder->bridges = new_bridges; + builder->max_n_bridges = new_max_n_bridges; + } + builder->bridges[builder->n_bridges++] = *bridge; + builder->curr_table = bridge->dest_table; + return GRN_SUCCESS; +} + +/* grn_ts_expr_builder_pop_bridge() pops a bridge. */ +static void +grn_ts_expr_builder_pop_bridge(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_ts_expr_bridge *bridge = &builder->bridges[builder->n_bridges - 1]; + builder->curr_table = bridge->src_table; + grn_ts_expr_bridge_fin(ctx, bridge); + builder->n_bridges--; +} + +grn_rc +grn_ts_expr_builder_begin_subexpr(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + size_t max_n_args; + grn_obj *obj; + grn_ts_expr_node *node; + grn_ts_expr_bridge bridge; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + max_n_args = grn_ts_expr_builder_get_max_n_args(ctx, builder); + if (!max_n_args) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + /* Check whehter or not the latest node refers to a table. */ + node = builder->nodes[builder->n_nodes - 1]; + if ((node->data_kind & ~GRN_TS_VECTOR_FLAG) != GRN_TS_REF) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->data_kind); + } + obj = grn_ctx_at(ctx, node->data_type); + if (!obj) { + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", + node->data_type); + } + if (!grn_ts_obj_is_table(ctx, obj)) { + grn_obj_unlink(ctx, obj); + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "not table: %d", node->data_type); + } + /* Creates a bridge to a subexpression. */ + grn_ts_expr_bridge_init(ctx, &bridge); + bridge.src_table = builder->curr_table; + bridge.dest_table = obj; + bridge.n_nodes = builder->n_nodes; + rc = grn_ts_expr_builder_push_bridge(ctx, builder, &bridge); + if (rc != GRN_SUCCESS) { + grn_obj_unlink(ctx, obj); + return rc; + } + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_builder_end_subexpr(grn_ctx *ctx, grn_ts_expr_builder *builder) +{ + grn_rc rc; + grn_ts_expr_node **args, *node; + if (!ctx || !builder || (builder->n_nodes < 2) || !builder->n_bridges) { + return GRN_INVALID_ARGUMENT; + } + /* Check whehter or not the subexpression is complete.*/ + if (grn_ts_expr_builder_get_max_n_args(ctx, builder) != 1) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + /* Creates a bridge node. */ + args = &builder->nodes[builder->n_nodes - 2]; + rc = grn_ts_expr_bridge_node_open(ctx, args[0], args[1], &node); + if (rc != GRN_SUCCESS) { + return rc; + } + /* Note: The following grn_ts_expr_push_node() must not fail. */ + builder->n_nodes -= 2; + grn_ts_expr_builder_push_node(ctx, builder, node); + grn_ts_expr_builder_pop_bridge(ctx, builder); + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_expr_builder.h b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_builder.h new file mode 100644 index 00000000..f9795ed1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_builder.h @@ -0,0 +1,128 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#include "ts_buf.h" +#include "ts_expr.h" +#include "ts_expr_node.h" +#include "ts_op.h" +#include "ts_str.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + grn_obj *src_table; /* The source table of a bridge (no ref. count). */ + grn_obj *dest_table; /* The destination table of a bridge. */ + size_t n_nodes; /* The stack depth (position) of a bridge. */ +} grn_ts_expr_bridge; + +typedef struct { + grn_obj *table; /* Associated table. */ + grn_obj *curr_table; /* Current table (no ref. count). */ + grn_ts_expr_node **nodes; /* Node stack. */ + size_t n_nodes; /* Number of nodes (stack depth). */ + size_t max_n_nodes; /* Maximum number of nodes (stack capacity). */ + grn_ts_expr_bridge *bridges; /* Bridges to subexpressions. */ + size_t n_bridges; /* Number of bridges (subexpression depth). */ + size_t max_n_bridges; /* Max. number (capacity) of bridges. */ +} grn_ts_expr_builder; + +/* grn_ts_expr_builder_open() creates an expression builder. */ +grn_rc grn_ts_expr_builder_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_builder **builder); + +/* grn_ts_expr_builder_close() destroys an expression builder. */ +grn_rc grn_ts_expr_builder_close(grn_ctx *ctx, grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_complete() completes an expression. */ +grn_rc grn_ts_expr_builder_complete(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_expr **expr); + +/* grn_ts_expr_builder_clear() clears the internal states. */ +grn_rc grn_ts_expr_builder_clear(grn_ctx *ctx, grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_push_name() pushes a named object. */ +grn_rc grn_ts_expr_builder_push_name(grn_ctx *ctx, + grn_ts_expr_builder *builder, + grn_ts_str name); + +/* + * grn_ts_expr_builder_push_obj() pushes an object. + * + * Acceptable objects are as follows: + * - Consts + * - GRN_BULK: GRN_DB_*. + * - GRN_UVECTOR: GRN_DB_* except GRN_DB_[SHORT/LONG_]TEXT. + * - GRN_VECTOR: GRN_DB_[SHORT/LONG_]TEXT. + * - Columns + * - GRN_ACCESSOR: _id, _score, _key, _value, and columns. + * - GRN_COLUMN_FIX_SIZE: GRN_DB_* except GRN_DB_[SHORT/LONG_]TEXT. + * - GRN_COLUMN_VAR_SIZE: GRN_DB_[SHORT/LONG_]TEXT. + */ +grn_rc grn_ts_expr_builder_push_obj(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_obj *obj); + +/* grn_ts_expr_builder_push_id() pushes "_id". */ +grn_rc grn_ts_expr_builder_push_id(grn_ctx *ctx, grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_push_score() pushes "_score". */ +grn_rc grn_ts_expr_builder_push_score(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_push_key() pushes "_key". */ +grn_rc grn_ts_expr_builder_push_key(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_push_value() pushes "_value". */ +grn_rc grn_ts_expr_builder_push_value(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_push_const() pushes a const. */ +grn_rc grn_ts_expr_builder_push_const(grn_ctx *ctx, + grn_ts_expr_builder *builder, + grn_ts_data_kind kind, + grn_ts_data_type type, + grn_ts_any value); + +/* grn_ts_expr_builder_push_column() pushes a column. */ +grn_rc grn_ts_expr_builder_push_column(grn_ctx *ctx, + grn_ts_expr_builder *builder, + grn_obj *column); + +/* grn_ts_expr_builder_push_op() pushes an operator. */ +grn_rc grn_ts_expr_builder_push_op(grn_ctx *ctx, grn_ts_expr_builder *builder, + grn_ts_op_type op_type); + +/* grn_ts_expr_builder_begin_subexpr() begins a subexpression. */ +grn_rc grn_ts_expr_builder_begin_subexpr(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +/* grn_ts_expr_builder_end_subexpr() ends a subexpression. */ +grn_rc grn_ts_expr_builder_end_subexpr(grn_ctx *ctx, + grn_ts_expr_builder *builder); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.c b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.c new file mode 100644 index 00000000..4ae90003 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.c @@ -0,0 +1,5325 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_expr_node.h" + +#include +#include + +#include "../grn_ctx.h" +#include "../grn_dat.h" +#include "../grn_db.h" +#include "../grn_geo.h" +#include "../grn_hash.h" +#include "../grn_pat.h" +#include "../grn_store.h" + +#include "ts_log.h" +#include "ts_str.h" +#include "ts_util.h" + +/*------------------------------------------------------------- + * Built-in data kinds. + */ + +/* grn_ts_bool_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_bool_is_valid(grn_ts_bool value) +{ + return GRN_TRUE; +} + +/* grn_ts_int_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_int_is_valid(grn_ts_int value) +{ + return GRN_TRUE; +} + +/* grn_ts_float_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_float_is_valid(grn_ts_float value) +{ + return isfinite(value); +} + +/* grn_ts_time_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_time_is_valid(grn_ts_time value) +{ + return GRN_TRUE; +} + +/* grn_ts_text_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_text_is_valid(grn_ts_text value) +{ + return value.ptr || !value.size; +} + +/* grn_ts_geo_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_geo_is_valid(grn_ts_geo value) +{ + return ((value.latitude >= GRN_GEO_MIN_LATITUDE) && + (value.latitude <= GRN_GEO_MAX_LATITUDE)) && + ((value.longitude >= GRN_GEO_MIN_LONGITUDE) && + (value.longitude <= GRN_GEO_MAX_LONGITUDE)); +} + +#define GRN_TS_VECTOR_IS_VALID(type)\ + if (value.size) {\ + size_t i;\ + if (!value.ptr) {\ + return GRN_FALSE;\ + }\ + for (i = 0; i < value.size; i++) {\ + if (!grn_ts_ ## type ## _is_valid(value.ptr[i])) {\ + return GRN_FALSE;\ + }\ + }\ + }\ + return GRN_TRUE; +/* grn_ts_bool_vector_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_bool_vector_is_valid(grn_ts_bool_vector value) +{ + GRN_TS_VECTOR_IS_VALID(bool) +} + +/* grn_ts_int_vector_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_int_vector_is_valid(grn_ts_int_vector value) +{ + GRN_TS_VECTOR_IS_VALID(int) +} + +/* grn_ts_float_vector_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_float_vector_is_valid(grn_ts_float_vector value) +{ + GRN_TS_VECTOR_IS_VALID(float) +} + +/* grn_ts_time_vector_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_time_vector_is_valid(grn_ts_time_vector value) +{ + GRN_TS_VECTOR_IS_VALID(time) +} + +/* grn_ts_text_vector_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_text_vector_is_valid(grn_ts_text_vector value) +{ + GRN_TS_VECTOR_IS_VALID(text) +} + +/* grn_ts_geo_vector_is_valid() returns whether a value is valid or not. */ +inline static grn_ts_bool +grn_ts_geo_vector_is_valid(grn_ts_geo_vector value) +{ + GRN_TS_VECTOR_IS_VALID(geo) +} +#undef GRN_TS_VECTOR_IS_VALID + +/* grn_ts_bool_zero() returns a zero. */ +inline static grn_ts_bool +grn_ts_bool_zero(void) +{ + return GRN_FALSE; +} + +/* grn_ts_int_zero() returns a zero. */ +inline static grn_ts_int +grn_ts_int_zero(void) +{ + return 0; +} + +/* grn_ts_float_zero() returns a zero. */ +inline static grn_ts_float +grn_ts_float_zero(void) +{ + return 0.0; +} + +/* grn_ts_time_zero() returns a zero. */ +inline static grn_ts_time +grn_ts_time_zero(void) +{ + return 0; +} + +/* grn_ts_text_zero() returns a zero. */ +inline static grn_ts_text +grn_ts_text_zero(void) +{ + return (grn_ts_text){ NULL, 0 }; +} + +/* grn_ts_geo_zero() returns a zero. */ +inline static grn_ts_geo +grn_ts_geo_zero(void) +{ + return (grn_ts_geo){ 0, 0 }; +} + +/* grn_ts_ref_zero() returns a zero. */ +inline static grn_ts_ref +grn_ts_ref_zero(void) +{ + return (grn_ts_ref){ 0, 0.0 }; +} + +/* grn_ts_data_type_to_kind() returns a kind associated with a type. */ +static grn_ts_data_kind +grn_ts_data_type_to_kind(grn_ts_data_type type) +{ + switch (type) { + case GRN_DB_VOID: { + return GRN_TS_VOID; + } + case GRN_DB_BOOL: { + return GRN_TS_BOOL; + } + case GRN_DB_INT8: + case GRN_DB_INT16: + case GRN_DB_INT32: + case GRN_DB_INT64: + case GRN_DB_UINT8: + case GRN_DB_UINT16: + case GRN_DB_UINT32: + case GRN_DB_UINT64: { + return GRN_TS_INT; + } + case GRN_DB_FLOAT: { + return GRN_TS_FLOAT; + } + case GRN_DB_TIME: { + return GRN_TS_TIME; + } + case GRN_DB_SHORT_TEXT: + case GRN_DB_TEXT: + case GRN_DB_LONG_TEXT: { + return GRN_TS_TEXT; + } + case GRN_DB_TOKYO_GEO_POINT: + case GRN_DB_WGS84_GEO_POINT: { + return GRN_TS_GEO; + } + default: { + return GRN_TS_REF; + } + } +} + +/* grn_ts_data_kind_to_type() returns a type associated with a kind. */ +static grn_ts_data_type +grn_ts_data_kind_to_type(grn_ts_data_kind kind) +{ + switch (kind & ~GRN_TS_VECTOR_FLAG) { + case GRN_TS_BOOL: { + return GRN_DB_BOOL; + } + case GRN_TS_INT: { + return GRN_DB_INT64; + } + case GRN_TS_FLOAT: { + return GRN_DB_FLOAT; + } + case GRN_TS_TIME: { + return GRN_DB_TIME; + } + case GRN_TS_TEXT: { + return GRN_DB_TEXT; + } + case GRN_TS_GEO: { + /* GRN_DB_TOKYO_GEO_POINT or GRN_DB_WGS84_GEO_POINT. */ + return GRN_DB_VOID; + } + case GRN_TS_REF: { + /* + * grn_ts_data_kind does not have enough information to get a correct + * table ID. + */ + return GRN_DB_VOID; + } + default: { + return GRN_DB_VOID; + } + } +} + +/*------------------------------------------------------------- + * Operators. + */ + +/* grn_ts_op_logical_not_bool() returns !arg. */ +inline static grn_ts_bool +grn_ts_op_logical_not_bool(grn_ts_bool arg) +{ + return !arg; +} + +/* grn_ts_op_bitwise_not_bool() returns ~arg. */ +inline static grn_ts_bool +grn_ts_op_bitwise_not_bool(grn_ts_bool arg) +{ + return !arg; +} + +/* grn_ts_op_bitwise_not_int() returns ~arg. */ +inline static grn_ts_int +grn_ts_op_bitwise_not_int(grn_ts_int arg) +{ + return ~arg; +} + +/* grn_ts_op_positive_int() returns +arg. */ +inline static grn_ts_int +grn_ts_op_positive_int(grn_ts_int arg) +{ + return arg; +} + +/* grn_ts_op_positive_float() returns +arg. */ +inline static grn_ts_float +grn_ts_op_positive_float(grn_ts_float arg) +{ + return arg; +} + +/* grn_ts_op_negative_int() returns -arg. */ +inline static grn_ts_int +grn_ts_op_negative_int(grn_ts_int arg) +{ + return -arg; +} + +/* grn_ts_op_negative_float() returns -arg. */ +inline static grn_ts_float +grn_ts_op_negative_float(grn_ts_float arg) +{ + return -arg; +} + +/* grn_ts_op_float() returns (Float)arg. */ +static grn_rc +grn_ts_op_float(grn_ctx *ctx, grn_ts_int arg, grn_ts_float *out) +{ + *out = (grn_ts_float)arg; + return GRN_SUCCESS; +} + +/* grn_ts_op_time() returns (Time)arg. */ +static grn_rc +grn_ts_op_time(grn_ctx *ctx, grn_ts_text arg, grn_ts_time *out) +{ + grn_timeval value; + grn_rc rc = grn_str2timeval(arg.ptr, arg.size, &value); + if (rc != GRN_SUCCESS) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "grn_str2timeval failed"); + } + *out = (grn_ts_time)((value.tv_sec * 1000000) + (value.tv_nsec / 1000)); + return GRN_SUCCESS; +} + +/* grn_ts_op_bitwise_and_bool() returns lhs & rhs. */ +inline static grn_ts_bool +grn_ts_op_bitwise_and_bool(grn_ts_bool lhs, grn_ts_bool rhs) +{ + return lhs & rhs; +} + +/* grn_ts_op_bitwise_and_int() returns lhs & rhs. */ +inline static grn_ts_int +grn_ts_op_bitwise_and_int(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs & rhs; +} + +/* grn_ts_op_bitwise_or_bool() returns lhs | rhs. */ +inline static grn_ts_bool +grn_ts_op_bitwise_or_bool(grn_ts_bool lhs, grn_ts_bool rhs) +{ + return lhs | rhs; +} + +/* grn_ts_op_bitwise_or_int() returns lhs | rhs. */ +inline static grn_ts_int +grn_ts_op_bitwise_or_int(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs | rhs; +} + +/* grn_ts_op_bitwise_xor_bool() returns lhs ^ rhs. */ +inline static grn_ts_bool +grn_ts_op_bitwise_xor_bool(grn_ts_bool lhs, grn_ts_bool rhs) +{ + return lhs ^ rhs; +} + +/* grn_ts_op_bitwise_xor_int() returns lhs ^ rhs. */ +inline static grn_ts_int +grn_ts_op_bitwise_xor_int(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs ^ rhs; +} + +/* grn_ts_op_equal_bool() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_bool(grn_ts_bool lhs, grn_ts_bool rhs) +{ + return lhs == rhs; +} + +/* grn_ts_op_equal_int() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_int(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs == rhs; +} + +/* grn_ts_op_equal_float() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_float(grn_ts_float lhs, grn_ts_float rhs) +{ + /* To suppress warnings, "lhs == rhs" is not used. */ + return (lhs <= rhs) && (lhs >= rhs); +} + +/* grn_ts_op_equal_time() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_time(grn_ts_time lhs, grn_ts_time rhs) +{ + return lhs == rhs; +} + +/* grn_ts_op_equal_text() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_text(grn_ts_text lhs, grn_ts_text rhs) +{ + return (lhs.size == rhs.size) && !memcmp(lhs.ptr, rhs.ptr, lhs.size); +} + +/* grn_ts_op_equal_geo() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_geo(grn_ts_geo lhs, grn_ts_geo rhs) +{ + return (lhs.latitude == rhs.latitude) && (lhs.longitude == rhs.longitude); +} + +/* grn_ts_op_equal_ref() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_ref(grn_ts_ref lhs, grn_ts_ref rhs) +{ + /* Ignore scores. */ + return lhs.id == rhs.id; +} + +#define GRN_TS_OP_EQUAL_VECTOR(kind)\ + size_t i;\ + if (lhs.size != rhs.size) {\ + return GRN_FALSE;\ + }\ + for (i = 0; i < lhs.size; i++) {\ + if (!grn_ts_op_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + return GRN_FALSE;\ + }\ + }\ + return GRN_TRUE; +/* grn_ts_op_equal_bool_vector() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_bool_vector(grn_ts_bool_vector lhs, grn_ts_bool_vector rhs) +{ + GRN_TS_OP_EQUAL_VECTOR(bool) +} + +/* grn_ts_op_equal_int_vector() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) +{ + GRN_TS_OP_EQUAL_VECTOR(int) +} + +/* grn_ts_op_equal_float_vector() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_float_vector(grn_ts_float_vector lhs, grn_ts_float_vector rhs) +{ + GRN_TS_OP_EQUAL_VECTOR(float) +} + +/* grn_ts_op_equal_time_vector() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) +{ + GRN_TS_OP_EQUAL_VECTOR(time) +} + +/* grn_ts_op_equal_text_vector() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) +{ + GRN_TS_OP_EQUAL_VECTOR(text) +} + +/* grn_ts_op_equal_geo_vector() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_geo_vector(grn_ts_geo_vector lhs, grn_ts_geo_vector rhs) +{ + GRN_TS_OP_EQUAL_VECTOR(geo) +} + +/* grn_ts_op_equal_ref_vector() returns lhs == rhs. */ +inline static grn_ts_bool +grn_ts_op_equal_ref_vector(grn_ts_ref_vector lhs, grn_ts_ref_vector rhs) +{ + GRN_TS_OP_EQUAL_VECTOR(ref) +} +#undef GRN_TS_OP_EQUAL_VECTOR + +/* grn_ts_op_not_equal_bool() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_bool(grn_ts_bool lhs, grn_ts_bool rhs) +{ + return lhs != rhs; +} + +/* grn_ts_op_not_equal_int() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_int(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs != rhs; +} + +/* grn_ts_op_not_equal_float() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_float(grn_ts_float lhs, grn_ts_float rhs) +{ + /* To suppress warnings, "lhs != rhs" is not used. */ + return !grn_ts_op_equal_float(lhs, rhs); +} + +/* grn_ts_op_not_equal_time() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_time(grn_ts_time lhs, grn_ts_time rhs) +{ + return lhs != rhs; +} + +/* grn_ts_op_not_equal_text() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_text(grn_ts_text lhs, grn_ts_text rhs) +{ + return (lhs.size != rhs.size) || memcmp(lhs.ptr, rhs.ptr, lhs.size); +} + +/* grn_ts_op_not_equal_geo() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_geo(grn_ts_geo lhs, grn_ts_geo rhs) +{ + return (lhs.latitude != rhs.latitude) || (lhs.longitude != rhs.longitude); +} + +/* grn_ts_op_not_equal_ref() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_ref(grn_ts_ref lhs, grn_ts_ref rhs) +{ + /* Ignore scores. */ + return lhs.id != rhs.id; +} + +#define GRN_TS_OP_NOT_EQUAL_VECTOR(kind)\ + size_t i;\ + if (lhs.size != rhs.size) {\ + return GRN_TRUE;\ + }\ + for (i = 0; i < lhs.size; i++) {\ + if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + return GRN_TRUE;\ + }\ + }\ + return GRN_FALSE; +/* grn_ts_op_not_equal_bool_vector() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_bool_vector(grn_ts_bool_vector lhs, grn_ts_bool_vector rhs) +{ + GRN_TS_OP_NOT_EQUAL_VECTOR(bool) +} + +/* grn_ts_op_not_equal_int_vector() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) +{ + GRN_TS_OP_NOT_EQUAL_VECTOR(int) +} + +/* grn_ts_op_not_equal_float_vector() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_float_vector(grn_ts_float_vector lhs, + grn_ts_float_vector rhs) +{ + GRN_TS_OP_NOT_EQUAL_VECTOR(float) +} + +/* grn_ts_op_not_equal_time_vector() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) +{ + GRN_TS_OP_NOT_EQUAL_VECTOR(time) +} + +/* grn_ts_op_not_equal_text_vector() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) +{ + GRN_TS_OP_NOT_EQUAL_VECTOR(text) +} + +/* grn_ts_op_not_equal_geo_vector() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_geo_vector(grn_ts_geo_vector lhs, grn_ts_geo_vector rhs) +{ + GRN_TS_OP_NOT_EQUAL_VECTOR(geo) +} + +/* grn_ts_op_not_equal_ref_vector() returns lhs != rhs. */ +inline static grn_ts_bool +grn_ts_op_not_equal_ref_vector(grn_ts_ref_vector lhs, grn_ts_ref_vector rhs) +{ + GRN_TS_OP_NOT_EQUAL_VECTOR(ref) +} +#undef GRN_TS_OP_NOT_EQUAL_VECTOR + +/* grn_ts_op_less_int() returns lhs < rhs. */ +inline static grn_ts_bool +grn_ts_op_less_int(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs < rhs; +} + +/* grn_ts_op_less_float() returns lhs < rhs. */ +inline static grn_ts_bool +grn_ts_op_less_float(grn_ts_float lhs, grn_ts_float rhs) +{ + return lhs < rhs; +} + +/* grn_ts_op_less_time() returns lhs < rhs. */ +inline static grn_ts_bool +grn_ts_op_less_time(grn_ts_time lhs, grn_ts_time rhs) +{ + return lhs < rhs; +} + +/* grn_ts_op_less_text() returns lhs < rhs. */ +inline static grn_ts_bool +grn_ts_op_less_text(grn_ts_text lhs, grn_ts_text rhs) +{ + size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; + int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); + return cmp ? (cmp < 0) : (lhs.size < rhs.size); +} + +#define GRN_TS_OP_LESS_VECTOR(kind)\ + size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ + for (i = 0; i < min_size; i++) {\ + if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + if (grn_ts_op_less_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + return GRN_TRUE;\ + }\ + }\ + }\ + return lhs.size < rhs.size; +/* grn_ts_op_less_int_vector() returns lhs < rhs. */ +inline static grn_ts_bool +grn_ts_op_less_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) +{ + GRN_TS_OP_LESS_VECTOR(int) +} + +/* grn_ts_op_less_float_vector() returns lhs < rhs. */ +inline static grn_ts_bool +grn_ts_op_less_float_vector(grn_ts_float_vector lhs, grn_ts_float_vector rhs) +{ + GRN_TS_OP_LESS_VECTOR(float) +} + +/* grn_ts_op_less_time_vector() returns lhs < rhs. */ +inline static grn_ts_bool +grn_ts_op_less_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) +{ + GRN_TS_OP_LESS_VECTOR(time) +} + +/* grn_ts_op_less_text_vector() returns lhs < rhs. */ +inline static grn_ts_bool +grn_ts_op_less_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) +{ + GRN_TS_OP_LESS_VECTOR(text) +} +#undef GRN_TS_OP_LESS_VECTOR + +/* grn_ts_op_less_equal_int() returns lhs <= rhs. */ +inline static grn_ts_bool +grn_ts_op_less_equal_int(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs <= rhs; +} + +/* grn_ts_op_less_equal_float() returns lhs <= rhs. */ +inline static grn_ts_bool +grn_ts_op_less_equal_float(grn_ts_float lhs, grn_ts_float rhs) +{ + return lhs <= rhs; +} + +/* grn_ts_op_less_equal_time() returns lhs <= rhs. */ +inline static grn_ts_bool +grn_ts_op_less_equal_time(grn_ts_time lhs, grn_ts_time rhs) +{ + return lhs <= rhs; +} + +/* grn_ts_op_less_equal_text() returns lhs <= rhs. */ +inline static grn_ts_bool +grn_ts_op_less_equal_text(grn_ts_text lhs, grn_ts_text rhs) +{ + size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; + int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); + return cmp ? (cmp < 0) : (lhs.size <= rhs.size); +} + +#define GRN_TS_OP_LESS_EQUAL_VECTOR(kind)\ + size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ + for (i = 0; i < min_size; i++) {\ + if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + if (grn_ts_op_less_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + return GRN_TRUE;\ + }\ + }\ + }\ + return lhs.size <= rhs.size; +/* grn_ts_op_less_equal_int_vector() returns lhs <= rhs. */ +inline static grn_ts_bool +grn_ts_op_less_equal_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) +{ + GRN_TS_OP_LESS_EQUAL_VECTOR(int) +} + +/* grn_ts_op_less_equal_float_vector() returns lhs <= rhs. */ +inline static grn_ts_bool +grn_ts_op_less_equal_float_vector(grn_ts_float_vector lhs, + grn_ts_float_vector rhs) +{ + GRN_TS_OP_LESS_EQUAL_VECTOR(float) +} + +/* grn_ts_op_less_equal_time_vector() returns lhs <= rhs. */ +inline static grn_ts_bool +grn_ts_op_less_equal_time_vector(grn_ts_time_vector lhs, + grn_ts_time_vector rhs) +{ + GRN_TS_OP_LESS_EQUAL_VECTOR(time) +} + +/* grn_ts_op_less_equal_text_vector() returns lhs <= rhs. */ +inline static grn_ts_bool +grn_ts_op_less_equal_text_vector(grn_ts_text_vector lhs, + grn_ts_text_vector rhs) +{ + GRN_TS_OP_LESS_EQUAL_VECTOR(text) +} +#undef GRN_TS_OP_LESS_EQUAL_VECTOR + +/* grn_ts_op_greater_int() returns lhs > rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_int(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs > rhs; +} + +/* grn_ts_op_greater_float() returns lhs > rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_float(grn_ts_float lhs, grn_ts_float rhs) +{ + return lhs > rhs; +} + +/* grn_ts_op_greater_time() returns lhs > rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_time(grn_ts_time lhs, grn_ts_time rhs) +{ + return lhs > rhs; +} + +/* grn_ts_op_greater_text() returns lhs > rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_text(grn_ts_text lhs, grn_ts_text rhs) +{ + size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; + int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); + return cmp ? (cmp > 0) : (lhs.size > rhs.size); +} + +#define GRN_TS_OP_GREATER_VECTOR(kind)\ + size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ + for (i = 0; i < min_size; i++) {\ + if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + if (grn_ts_op_greater_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + return GRN_TRUE;\ + }\ + }\ + }\ + return lhs.size > rhs.size; +/* grn_ts_op_greater_int_vector() returns lhs > rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_int_vector(grn_ts_int_vector lhs, grn_ts_int_vector rhs) +{ + GRN_TS_OP_GREATER_VECTOR(int) +} + +/* grn_ts_op_greater_float_vector() returns lhs > rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_float_vector(grn_ts_float_vector lhs, + grn_ts_float_vector rhs) +{ + GRN_TS_OP_GREATER_VECTOR(float) +} + +/* grn_ts_op_greater_time_vector() returns lhs > rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_time_vector(grn_ts_time_vector lhs, grn_ts_time_vector rhs) +{ + GRN_TS_OP_GREATER_VECTOR(time) +} + +/* grn_ts_op_greater_text_vector() returns lhs > rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_text_vector(grn_ts_text_vector lhs, grn_ts_text_vector rhs) +{ + GRN_TS_OP_GREATER_VECTOR(text) +} +#undef GRN_TS_OP_GREATER_VECTOR + +/* grn_ts_op_greater_equal_int() returns lhs >= rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_equal_int(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs >= rhs; +} + +/* grn_ts_op_greater_equal_float() returns lhs >= rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_equal_float(grn_ts_float lhs, grn_ts_float rhs) +{ + return lhs >= rhs; +} + +/* grn_ts_op_greater_equal_time() returns lhs >= rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_equal_time(grn_ts_time lhs, grn_ts_time rhs) +{ + return lhs >= rhs; +} + +/* grn_ts_op_greater_equal_text() returns lhs >= rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_equal_text(grn_ts_text lhs, grn_ts_text rhs) +{ + size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; + int cmp = memcmp(lhs.ptr, rhs.ptr, min_size); + return cmp ? (cmp > 0) : (lhs.size >= rhs.size); +} + +#define GRN_TS_OP_GREATER_EQUAL_VECTOR(kind)\ + size_t i, min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size;\ + for (i = 0; i < min_size; i++) {\ + if (grn_ts_op_not_equal_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + if (grn_ts_op_greater_ ## kind(lhs.ptr[i], rhs.ptr[i])) {\ + return GRN_TRUE;\ + }\ + }\ + }\ + return lhs.size >= rhs.size; +/* grn_ts_op_greater_equal_int_vector() returns lhs >= rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_equal_int_vector(grn_ts_int_vector lhs, + grn_ts_int_vector rhs) +{ + GRN_TS_OP_GREATER_EQUAL_VECTOR(int) +} + +/* grn_ts_op_greater_equal_float_vector() returns lhs >= rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_equal_float_vector(grn_ts_float_vector lhs, + grn_ts_float_vector rhs) +{ + GRN_TS_OP_GREATER_EQUAL_VECTOR(float) +} + +/* grn_ts_op_greater_equal_time_vector() returns lhs >= rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_equal_time_vector(grn_ts_time_vector lhs, + grn_ts_time_vector rhs) +{ + GRN_TS_OP_GREATER_EQUAL_VECTOR(time) +} + +/* grn_ts_op_greater_equal_text_vector() returns lhs >= rhs. */ +inline static grn_ts_bool +grn_ts_op_greater_equal_text_vector(grn_ts_text_vector lhs, + grn_ts_text_vector rhs) +{ + GRN_TS_OP_GREATER_EQUAL_VECTOR(text) +} +#undef GRN_TS_OP_GREATER_EQUAL_VECTOR + +/* grn_ts_op_shift_arithmetic_left() returns lhs << rhs. */ +inline static grn_ts_int +grn_ts_op_shift_arithmetic_left(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs << rhs; +} + +/* grn_ts_op_shift_arithmetic_right() returns lhs << rhs. */ +inline static grn_ts_int +grn_ts_op_shift_arithmetic_right(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs >> rhs; +} + +/* grn_ts_op_shift_logical_left() returns lhs << rhs. */ +inline static grn_ts_int +grn_ts_op_shift_logical_left(grn_ts_int lhs, grn_ts_int rhs) +{ + return lhs << rhs; +} + +/* grn_ts_op_shift_logical_right() returns lhs << rhs. */ +inline static grn_ts_int +grn_ts_op_shift_logical_right(grn_ts_int lhs, grn_ts_int rhs) +{ + return (uint64_t)lhs >> rhs; +} + +inline static grn_rc +grn_ts_op_plus_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, + grn_ts_int *out) +{ + *out = lhs + rhs; + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_plus_float_float(grn_ctx *ctx, grn_ts_float lhs, grn_ts_float rhs, + grn_ts_float *out) +{ + *out = lhs + rhs; + if (!grn_ts_float_is_valid(*out)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g + %g = %g", lhs, rhs, *out); + } + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_plus_time_int(grn_ctx *ctx, grn_ts_time lhs, grn_ts_int rhs, + grn_ts_time *out) +{ + *out = lhs + (rhs * 1000000); + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_plus_time_float(grn_ctx *ctx, grn_ts_time lhs, grn_ts_float rhs, + grn_ts_time *out) +{ + *out = (grn_ts_time)(lhs + (rhs * 1000000.0)); + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_minus_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, + grn_ts_int *out) +{ + *out = lhs - rhs; + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_minus_float_float(grn_ctx *ctx, grn_ts_float lhs, grn_ts_float rhs, + grn_ts_float *out) +{ + *out = lhs - rhs; + if (!grn_ts_float_is_valid(*out)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g - %g = %g", lhs, rhs, *out); + } + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_minus_time_time(grn_ctx *ctx, grn_ts_time lhs, grn_ts_time rhs, + grn_ts_float *out) +{ + *out = (lhs - rhs) * 0.000001; + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_minus_time_int(grn_ctx *ctx, grn_ts_time lhs, grn_ts_int rhs, + grn_ts_time *out) +{ + *out = lhs - (rhs * 1000000); + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_minus_time_float(grn_ctx *ctx, grn_ts_time lhs, grn_ts_float rhs, + grn_ts_time *out) +{ + *out = lhs - (grn_ts_int)(rhs * 1000000.0); + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_multiplication_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, + grn_ts_int *out) +{ + *out = lhs * rhs; + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_multiplication_float_float(grn_ctx *ctx, grn_ts_float lhs, + grn_ts_float rhs, grn_ts_float *out) +{ + *out = lhs * rhs; + if (!grn_ts_float_is_valid(*out)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g * %g = %g", lhs, rhs, *out); + } + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_division_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, + grn_ts_int *out) +{ + if (!rhs) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "%" GRN_FMT_INT64D " / %" GRN_FMT_INT64D + " causes division by zero", + lhs, rhs); + } + *out = (rhs != -1) ? (lhs / rhs) : -lhs; + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_division_float_float(grn_ctx *ctx, grn_ts_float lhs, + grn_ts_float rhs, grn_ts_float *out) +{ + *out = lhs / rhs; + if (!grn_ts_float_is_valid(*out)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g / %g = %g", lhs, rhs, *out); + } + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_modulus_int_int(grn_ctx *ctx, grn_ts_int lhs, grn_ts_int rhs, + grn_ts_int *out) +{ + if (!rhs) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "%" GRN_FMT_INT64D " %% %" GRN_FMT_INT64D + " causes division by zero", + lhs, rhs); + } + *out = (rhs != -1) ? (lhs % rhs) : -lhs; + return GRN_SUCCESS; +} + +inline static grn_rc +grn_ts_op_modulus_float_float(grn_ctx *ctx, grn_ts_float lhs, grn_ts_float rhs, + grn_ts_float *out) +{ + *out = fmod(lhs, rhs); + if (!grn_ts_float_is_valid(*out)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "%g %% %g = %g", lhs, rhs, *out); + } + return GRN_SUCCESS; +} + +static grn_ts_bool +grn_ts_op_match(grn_ts_text lhs, grn_ts_text rhs) +{ + const char *lhs_ptr, *lhs_ptr_last; + if (lhs.size < rhs.size) { + return GRN_FALSE; + } + lhs_ptr_last = lhs.ptr + lhs.size - rhs.size; + for (lhs_ptr = lhs.ptr; lhs_ptr <= lhs_ptr_last; lhs_ptr++) { + size_t i; + for (i = 0; i < rhs.size; i++) { + if (lhs_ptr[i] != rhs.ptr[i]) { + break; + } + } + if (i == rhs.size) { + return GRN_TRUE; + } + } + return GRN_FALSE; +} + +static grn_ts_bool +grn_ts_op_prefix_match(grn_ts_text lhs, grn_ts_text rhs) +{ + size_t i; + if (lhs.size < rhs.size) { + return GRN_FALSE; + } + for (i = 0; i < rhs.size; i++) { + if (lhs.ptr[i] != rhs.ptr[i]) { + return GRN_FALSE; + } + } + return GRN_TRUE; +} + +static grn_ts_bool +grn_ts_op_suffix_match(grn_ts_text lhs, grn_ts_text rhs) +{ + size_t i; + const char *lhs_ptr; + if (lhs.size < rhs.size) { + return GRN_FALSE; + } + lhs_ptr = lhs.ptr + lhs.size - rhs.size; + for (i = 0; i < rhs.size; i++) { + if (lhs_ptr[i] != rhs.ptr[i]) { + return GRN_FALSE; + } + } + return GRN_TRUE; +} + +/*------------------------------------------------------------- + * Groonga objects. + */ + +#define GRN_TS_TABLE_GET_KEY(type)\ + uint32_t key_size;\ + const void *key_ptr = _grn_ ## type ## _key(ctx, type, id, &key_size);\ + if (!key_ptr) {\ + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "_grn_" #type "_key failed: %u", id);\ + }\ +/* grn_ts_hash_get_bool_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_bool_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_bool *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const grn_ts_bool *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_int8_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_int8_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const int8_t *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_int16_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_int16_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const int16_t *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_int32_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_int32_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const int32_t *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_int64_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_int64_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const int64_t *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_uint8_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_uint8_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const uint8_t *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_uint16_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_uint16_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const uint16_t *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_uint32_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_uint32_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const uint32_t *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_uint64_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_uint64_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = (grn_ts_int)*(const uint64_t *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_float_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_float_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_float *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const grn_ts_float *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_time_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_time_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_time *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const grn_ts_time *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_geo_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_geo_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_geo *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + *key = *(const grn_ts_geo *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_text_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_text_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_text *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + key->ptr = key_ptr; + key->size = key_size; + return GRN_SUCCESS; +} + +/* grn_ts_hash_get_ref_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_hash_get_ref_key(grn_ctx *ctx, grn_hash *hash, grn_ts_id id, + grn_ts_ref *key) +{ + GRN_TS_TABLE_GET_KEY(hash) + key->id = *(const grn_ts_id *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_bool_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_bool_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_bool *key) +{ + GRN_TS_TABLE_GET_KEY(pat) + *key = *(const grn_ts_bool *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_int8_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_int8_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_int *key) +{ + int8_t tmp; + GRN_TS_TABLE_GET_KEY(pat) + grn_ntohi(&tmp, key_ptr, sizeof(tmp)); + *key = tmp; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_int16_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_int16_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_int *key) +{ + int16_t tmp; + GRN_TS_TABLE_GET_KEY(pat) + grn_ntohi(&tmp, key_ptr, sizeof(tmp)); + *key = tmp; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_int32_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_int32_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_int *key) +{ + int32_t tmp; + GRN_TS_TABLE_GET_KEY(pat) + grn_ntohi(&tmp, key_ptr, sizeof(tmp)); + *key = tmp; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_int64_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_int64_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(pat) + grn_ntohi(key, key_ptr, sizeof(grn_ts_int)); + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_uint8_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_uint8_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(pat) + *key = *(const uint8_t *)key_ptr; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_uint16_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_uint16_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_int *key) +{ + uint16_t tmp; + GRN_TS_TABLE_GET_KEY(pat) + grn_ntoh(&tmp, key_ptr, sizeof(tmp)); + *key = tmp; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_uint32_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_uint32_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_int *key) +{ + uint32_t tmp; + GRN_TS_TABLE_GET_KEY(pat) + grn_ntoh(&tmp, key_ptr, sizeof(tmp)); + *key = tmp; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_uint64_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_uint64_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_int *key) +{ + GRN_TS_TABLE_GET_KEY(pat) + grn_ntoh(key, key_ptr, sizeof(grn_ts_int)); + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_float_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_float_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_float *key) +{ + int64_t tmp; + GRN_TS_TABLE_GET_KEY(pat) + grn_ntoh(&tmp, key_ptr, sizeof(tmp)); + tmp ^= (((tmp ^ ((int64_t)1 << 63)) >> 63) | ((int64_t)1 << 63)); + *(int64_t *)key = tmp; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_time_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_time_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_time *key) +{ + GRN_TS_TABLE_GET_KEY(pat) + grn_ntohi(key, key_ptr, sizeof(grn_ts_time)); + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_geo_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_geo_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_geo *key) +{ + GRN_TS_TABLE_GET_KEY(pat) + grn_ntog(key, key_ptr, sizeof(grn_ts_geo)); + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_text_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_text_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_text *key) +{ + GRN_TS_TABLE_GET_KEY(pat) + key->ptr = key_ptr; + key->size = key_size; + return GRN_SUCCESS; +} + +/* grn_ts_pat_get_ref_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_pat_get_ref_key(grn_ctx *ctx, grn_pat *pat, grn_ts_id id, + grn_ts_ref *key) +{ + GRN_TS_TABLE_GET_KEY(pat) + grn_ntoh(&key->id, key_ptr, sizeof(key->id)); + return GRN_SUCCESS; +} + +/* grn_ts_dat_get_text_key() gets a reference to a key (_key). */ +static grn_rc +grn_ts_dat_get_text_key(grn_ctx *ctx, grn_dat *dat, grn_ts_id id, + grn_ts_text *key) +{ + GRN_TS_TABLE_GET_KEY(dat) + key->ptr = key_ptr; + key->size = key_size; + return GRN_SUCCESS; +} +#undef GRN_TS_TABLE_GET_KEY + +/*------------------------------------------------------------- + * grn_ts_expr_id_node. + */ + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS +} grn_ts_expr_id_node; + +/* grn_ts_expr_id_node_init() initializes a node. */ +static void +grn_ts_expr_id_node_init(grn_ctx *ctx, grn_ts_expr_id_node *node) +{ + memset(node, 0, sizeof(*node)); + node->type = GRN_TS_EXPR_ID_NODE; + node->data_kind = GRN_TS_INT; + node->data_type = GRN_DB_UINT32; +} + +/* grn_ts_expr_id_node_fin() finalizes a node. */ +static void +grn_ts_expr_id_node_fin(grn_ctx *ctx, grn_ts_expr_id_node *node) +{ + /* Nothing to do. */ +} + +grn_rc +grn_ts_expr_id_node_open(grn_ctx *ctx, grn_ts_expr_node **node) +{ + grn_ts_expr_id_node *new_node = GRN_MALLOCN(grn_ts_expr_id_node, 1); + if (!new_node) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_expr_id_node)); + } + grn_ts_expr_id_node_init(ctx, new_node); + *node = (grn_ts_expr_node *)new_node; + return GRN_SUCCESS; +} + +/* grn_ts_expr_id_node_close() destroys a node. */ +static void +grn_ts_expr_id_node_close(grn_ctx *ctx, grn_ts_expr_id_node *node) +{ + grn_ts_expr_id_node_fin(ctx, node); + GRN_FREE(node); +} + +/* grn_ts_expr_id_node_evaluate() outputs IDs. */ +static grn_rc +grn_ts_expr_id_node_evaluate(grn_ctx *ctx, grn_ts_expr_id_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + size_t i; + grn_ts_int *out_ptr = (grn_ts_int *)out; + for (i = 0; i < n_in; i++) { + out_ptr[i] = (grn_ts_int)in[i].id; + } + return GRN_SUCCESS; +} + +/*------------------------------------------------------------- + * grn_ts_expr_score_node. + */ + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS +} grn_ts_expr_score_node; + +/* grn_ts_expr_score_node_init() initializes a node. */ +static void +grn_ts_expr_score_node_init(grn_ctx *ctx, grn_ts_expr_score_node *node) +{ + memset(node, 0, sizeof(*node)); + node->type = GRN_TS_EXPR_SCORE_NODE; + node->data_kind = GRN_TS_FLOAT; + node->data_type = GRN_DB_FLOAT; +} + +/* grn_ts_expr_score_node_fin() finalizes a node. */ +static void +grn_ts_expr_score_node_fin(grn_ctx *ctx, grn_ts_expr_score_node *node) +{ + /* Nothing to do. */ +} + +grn_rc +grn_ts_expr_score_node_open(grn_ctx *ctx, grn_ts_expr_node **node) +{ + grn_ts_expr_score_node *new_node = GRN_MALLOCN(grn_ts_expr_score_node, 1); + if (!new_node) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_expr_score_node)); + } + grn_ts_expr_score_node_init(ctx, new_node); + *node = (grn_ts_expr_node *)new_node; + return GRN_SUCCESS; +} + +/* grn_ts_expr_score_node_close() destroys a node. */ +static void +grn_ts_expr_score_node_close(grn_ctx *ctx, grn_ts_expr_score_node *node) +{ + grn_ts_expr_score_node_fin(ctx, node); + GRN_FREE(node); +} + +/* grn_ts_expr_score_node_evaluate() outputs scores. */ +static grn_rc +grn_ts_expr_score_node_evaluate(grn_ctx *ctx, grn_ts_expr_score_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + size_t i; + grn_ts_float *out_ptr = (grn_ts_float *)out; + for (i = 0; i < n_in; i++) { + out_ptr[i] = (grn_ts_float)in[i].score; + } + return GRN_SUCCESS; +} + +/* grn_ts_expr_score_node_adjust() does nothing. */ +static grn_rc +grn_ts_expr_score_node_adjust(grn_ctx *ctx, grn_ts_expr_score_node *node, + grn_ts_record *io, size_t n_io) +{ + /* Nothing to do. */ + return GRN_SUCCESS; +} + +/*------------------------------------------------------------- + * grn_ts_expr_key_node. + */ + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS + grn_obj *table; + grn_ts_buf buf; +} grn_ts_expr_key_node; + +/* grn_ts_expr_key_node_init() initializes a node. */ +static void +grn_ts_expr_key_node_init(grn_ctx *ctx, grn_ts_expr_key_node *node) +{ + memset(node, 0, sizeof(*node)); + node->type = GRN_TS_EXPR_KEY_NODE; + node->table = NULL; + grn_ts_buf_init(ctx, &node->buf); +} + +/* grn_ts_expr_key_node_fin() finalizes a node. */ +static void +grn_ts_expr_key_node_fin(grn_ctx *ctx, grn_ts_expr_key_node *node) +{ + grn_ts_buf_fin(ctx, &node->buf); + if (node->table) { + grn_obj_unlink(ctx, node->table); + } +} + +grn_rc +grn_ts_expr_key_node_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_node **node) +{ + grn_rc rc; + grn_ts_expr_key_node *new_node; + if (!grn_ts_table_has_key(ctx, table)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "the table has no _key"); + } + new_node = GRN_MALLOCN(grn_ts_expr_key_node, 1); + if (!new_node) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_expr_key_node)); + } + grn_ts_expr_key_node_init(ctx, new_node); + rc = grn_ts_obj_increment_ref_count(ctx, table); + if (rc != GRN_SUCCESS) { + grn_ts_expr_key_node_fin(ctx, new_node); + GRN_FREE(new_node); + return rc; + } + new_node->data_kind = grn_ts_data_type_to_kind(table->header.domain); + new_node->data_type = table->header.domain; + new_node->table = table; + *node = (grn_ts_expr_node *)new_node; + return GRN_SUCCESS; +} + +/* grn_ts_expr_key_node_close() destroys a node. */ +static void +grn_ts_expr_key_node_close(grn_ctx *ctx, grn_ts_expr_key_node *node) +{ + grn_ts_expr_key_node_fin(ctx, node); + GRN_FREE(node); +} + +#define GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(table, KIND, kind)\ + case GRN_TS_ ## KIND: {\ + grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ + for (i = 0; i < n_in; i++) {\ + rc = grn_ts_ ## table ## _get_ ## kind ## _key(ctx, table, in[i].id,\ + &out_ptr[i]);\ + if (rc != GRN_SUCCESS) {\ + out_ptr[i] = grn_ts_ ## kind ## _zero();\ + }\ + }\ + return GRN_SUCCESS;\ + } +#define GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(table, TYPE, type)\ + case GRN_DB_ ## TYPE: {\ + grn_ts_int *out_ptr = (grn_ts_int *)out;\ + for (i = 0; i < n_in; i++) {\ + rc = grn_ts_ ## table ## _get_ ## type ## _key(ctx, table, in[i].id,\ + &out_ptr[i]);\ + if (rc != GRN_SUCCESS) {\ + out_ptr[i] = grn_ts_int_zero();\ + }\ + }\ + return GRN_SUCCESS;\ + } +#define GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(table)\ + case GRN_TS_TEXT: {\ + char *buf_ptr;\ + grn_ts_text *out_ptr = (grn_ts_text *)out;\ + node->buf.pos = 0;\ + for (i = 0; i < n_in; i++) {\ + grn_ts_text key;\ + rc = grn_ts_ ## table ## _get_text_key(ctx, table, in[i].id, &key);\ + if (rc != GRN_SUCCESS) {\ + key = grn_ts_text_zero();\ + }\ + rc = grn_ts_buf_write(ctx, &node->buf, key.ptr, key.size);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + out_ptr[i].size = key.size;\ + }\ + buf_ptr = (char *)node->buf.ptr;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i].ptr = buf_ptr;\ + buf_ptr += out_ptr[i].size;\ + }\ + return GRN_SUCCESS;\ + } +#define GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(table)\ + case GRN_TS_REF: {\ + grn_ts_ref *out_ptr = (grn_ts_ref *)out;\ + for (i = 0; i < n_in; i++) {\ + rc = grn_ts_ ## table ## _get_ref_key(ctx, table, in[i].id,\ + &out_ptr[i]);\ + if (rc != GRN_SUCCESS) {\ + out_ptr[i] = grn_ts_ref_zero();\ + }\ + out_ptr[i].score = in[i].score;\ + }\ + return GRN_SUCCESS;\ + } +/* grn_ts_expr_key_node_evaluate() outputs keys. */ +static grn_rc +grn_ts_expr_key_node_evaluate(grn_ctx *ctx, grn_ts_expr_key_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + size_t i; + grn_rc rc; + switch (node->table->header.type) { + case GRN_TABLE_HASH_KEY: { + grn_hash *hash = (grn_hash *)node->table; + switch (node->data_kind) { + GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, BOOL, bool) + case GRN_TS_INT: { + switch (node->data_type) { + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT8, int8) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT16, int16) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT32, int32) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, INT64, int64) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT8, uint8) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT16, uint16) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT32, uint32) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(hash, UINT64, uint64) + } + } + GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, FLOAT, float) + GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, TIME, time) + GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(hash) + GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(hash, GEO, geo) + GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(hash) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } + } + case GRN_TABLE_PAT_KEY: { + grn_pat *pat = (grn_pat *)node->table; + switch (node->data_kind) { + GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, BOOL, bool) + case GRN_TS_INT: { + switch (node->data_type) { + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT8, int8) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT16, int16) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT32, int32) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, INT64, int64) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT8, uint8) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT16, uint16) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT32, uint32) + GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE(pat, UINT64, uint64) + } + } + GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, FLOAT, float) + GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, TIME, time) + GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(pat) + GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE(pat, GEO, geo) + GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE(pat) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } + } + case GRN_TABLE_DAT_KEY: { + grn_dat *dat = (grn_dat *)node->table; + switch (node->data_kind) { + GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE(dat) + /* GRN_TABLE_DAT_KEY supports only Text. */ + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } + } + /* GRN_TABLE_NO_KEY doesn't support _key. */ + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d", + node->table->header.type); + } + } +} +#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_REF_CASE +#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_TEXT_CASE +#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_INT_CASE +#undef GRN_TS_EXPR_KEY_NODE_EVALUATE_CASE + +/* grn_ts_expr_key_node_filter() filters records. */ +static grn_rc +grn_ts_expr_key_node_filter(grn_ctx *ctx, grn_ts_expr_key_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + size_t i, count; + grn_ts_bool key; + switch (node->table->header.type) { + case GRN_TABLE_HASH_KEY: { + grn_hash *hash = (grn_hash *)node->table; + for (i = 0, count = 0; i < n_in; i++) { + grn_rc rc = grn_ts_hash_get_bool_key(ctx, hash, in[i].id, &key); + if (rc != GRN_SUCCESS) { + key = grn_ts_bool_zero(); + } + if (key) { + out[count++] = in[i]; + } + } + *n_out = count; + return GRN_SUCCESS; + } + case GRN_TABLE_PAT_KEY: { + grn_pat *pat = (grn_pat *)node->table; + for (i = 0, count = 0; i < n_in; i++) { + grn_rc rc = grn_ts_pat_get_bool_key(ctx, pat, in[i].id, &key); + if (rc != GRN_SUCCESS) { + key = grn_ts_bool_zero(); + } + if (key) { + out[count++] = in[i]; + } + } + *n_out = count; + return GRN_SUCCESS; + } + /* GRN_TABLE_DAT_KEY and GRN_TABLE_NO_KEY don't support a Bool key. */ + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d", + node->table->header.type); + } + } +} + +/* grn_ts_expr_key_node_adjust() updates scores. */ +static grn_rc +grn_ts_expr_key_node_adjust(grn_ctx *ctx, grn_ts_expr_key_node *node, + grn_ts_record *io, size_t n_io) +{ + size_t i; + grn_ts_float key; + switch (node->table->header.type) { + case GRN_TABLE_HASH_KEY: { + grn_hash *hash = (grn_hash *)node->table; + for (i = 0; i < n_io; i++) { + grn_rc rc = grn_ts_hash_get_float_key(ctx, hash, io[i].id, &key); + if (rc != GRN_SUCCESS) { + key = grn_ts_float_zero(); + } + io[i].score = (grn_ts_score)key; + } + return GRN_SUCCESS; + } + case GRN_TABLE_PAT_KEY: { + grn_pat *pat = (grn_pat *)node->table; + for (i = 0; i < n_io; i++) { + grn_rc rc = grn_ts_pat_get_float_key(ctx, pat, io[i].id, &key); + if (rc != GRN_SUCCESS) { + key = grn_ts_float_zero(); + } + io[i].score = (grn_ts_score)key; + } + return GRN_SUCCESS; + } + /* GRN_TABLE_DAT_KEY and GRN_TABLE_NO_KEY don't support a Float key. */ + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid table type: %d", + node->table->header.type); + } + } +} + +/*------------------------------------------------------------- + * grn_ts_expr_value_node. + */ + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS + grn_obj *table; +} grn_ts_expr_value_node; + +/* grn_ts_expr_value_node_init() initializes a node. */ +static void +grn_ts_expr_value_node_init(grn_ctx *ctx, grn_ts_expr_value_node *node) +{ + memset(node, 0, sizeof(*node)); + node->type = GRN_TS_EXPR_VALUE_NODE; + node->table = NULL; +} + +/* grn_ts_expr_value_node_fin() finalizes a node. */ +static void +grn_ts_expr_value_node_fin(grn_ctx *ctx, grn_ts_expr_value_node *node) +{ + if (node->table) { + grn_obj_unlink(ctx, node->table); + } +} + +grn_rc +grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_node **node) +{ + grn_rc rc; + grn_ts_expr_value_node *new_node; + if (!grn_ts_table_has_value(ctx, table)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "table has no _value"); + } + new_node = GRN_MALLOCN(grn_ts_expr_value_node, 1); + if (!new_node) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_expr_value_node)); + } + grn_ts_expr_value_node_init(ctx, new_node); + rc = grn_ts_obj_increment_ref_count(ctx, table); + if (rc != GRN_SUCCESS) { + GRN_FREE(new_node); + return rc; + } + new_node->data_kind = grn_ts_data_type_to_kind(DB_OBJ(table)->range); + new_node->data_type = DB_OBJ(table)->range; + new_node->table = table; + *node = (grn_ts_expr_node *)new_node; + return GRN_SUCCESS; +} + +/* grn_ts_expr_value_node_close() destroys a node. */ +static void +grn_ts_expr_value_node_close(grn_ctx *ctx, grn_ts_expr_value_node *node) +{ + grn_ts_expr_value_node_fin(ctx, node); + GRN_FREE(node); +} + +#define GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(KIND, kind)\ + case GRN_TS_ ## KIND: {\ + size_t i;\ + grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ + for (i = 0; i < n_in; i++) {\ + const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);\ + if (ptr) {\ + out_ptr[i] = *(const grn_ts_ ## kind *)ptr;\ + } else {\ + out_ptr[i] = grn_ts_ ## kind ## _zero();\ + }\ + }\ + return GRN_SUCCESS;\ + } +#define GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(TYPE, type)\ + case GRN_DB_ ## TYPE: {\ + size_t i;\ + grn_ts_int *out_ptr = (grn_ts_int *)out;\ + for (i = 0; i < n_in; i++) {\ + const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id);\ + if (ptr) {\ + out_ptr[i] = (grn_ts_int)*(const type ## _t *)ptr;\ + } else {\ + out_ptr[i] = grn_ts_int_zero();\ + }\ + }\ + return GRN_SUCCESS;\ + } +/* grn_ts_expr_value_node_evaluate() outputs values. */ +static grn_rc +grn_ts_expr_value_node_evaluate(grn_ctx *ctx, grn_ts_expr_value_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + switch (node->data_kind) { + GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(BOOL, bool) + case GRN_TS_INT: { + switch (node->data_type) { + GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT8, int8) + GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT16, int16) + GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT32, int32) + GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(INT64, int64) + GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT8, uint8) + GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT16, uint16) + GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT32, uint32) + GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE(UINT64, uint64) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", + node->data_type); + } + } + } + GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(FLOAT, float) + GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(TIME, time) + GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE(GEO, geo) + case GRN_TS_REF: { + size_t i; + grn_ts_ref *out_ptr = (grn_ts_ref *)out; + for (i = 0; i < n_in; i++) { + const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id); + if (ptr) { + out_ptr[i].id = *(const grn_ts_id *)ptr; + out_ptr[i].score = in[i].score; + } else { + out_ptr[i] = grn_ts_ref_zero(); + } + } + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} +#undef GRN_TS_EXPR_VALUE_NODE_EVALUATE_INT_CASE +#undef GRN_TS_EXPR_VALUE_NODE_EVALUATE_CASE + +/* grn_ts_expr_value_node_filter() filters records. */ +static grn_rc +grn_ts_expr_value_node_filter(grn_ctx *ctx, grn_ts_expr_value_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + size_t i, count = 0; + for (i = 0; i < n_in; i++) { + const void *ptr = grn_ts_table_get_value(ctx, node->table, in[i].id); + if (ptr && *(const grn_ts_bool *)ptr) { + out[count++] = in[i]; + } + } + *n_out = count; + return GRN_SUCCESS; +} + +/* grn_ts_expr_value_node_adjust() updates scores. */ +static grn_rc +grn_ts_expr_value_node_adjust(grn_ctx *ctx, grn_ts_expr_value_node *node, + grn_ts_record *io, size_t n_io) +{ + size_t i; + for (i = 0; i < n_io; i++) { + const void *ptr = grn_ts_table_get_value(ctx, node->table, io[i].id); + if (ptr) { + io[i].score = (grn_ts_score)*(const grn_ts_float *)ptr; + } + } + return GRN_SUCCESS; +} + +/*------------------------------------------------------------- + * grn_ts_expr_const_node. + */ + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS + grn_ts_any content; + grn_ts_buf text_buf; + grn_ts_buf vector_buf; +} grn_ts_expr_const_node; + +/* grn_ts_expr_const_node_init() initializes a node. */ +static void +grn_ts_expr_const_node_init(grn_ctx *ctx, grn_ts_expr_const_node *node) +{ + memset(node, 0, sizeof(*node)); + node->type = GRN_TS_EXPR_CONST_NODE; + grn_ts_buf_init(ctx, &node->text_buf); + grn_ts_buf_init(ctx, &node->vector_buf); +} + +/* grn_ts_expr_const_node_fin() finalizes a node. */ +static void +grn_ts_expr_const_node_fin(grn_ctx *ctx, grn_ts_expr_const_node *node) +{ + grn_ts_buf_fin(ctx, &node->vector_buf); + grn_ts_buf_fin(ctx, &node->text_buf); +} + +#define GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(KIND, kind)\ + case GRN_TS_ ## KIND: {\ + node->content.as_ ## kind = value.as_ ## kind;\ + return GRN_SUCCESS;\ + } +/* grn_ts_expr_const_node_set_scalar() sets a scalar value. */ +static grn_rc +grn_ts_expr_const_node_set_scalar(grn_ctx *ctx, grn_ts_expr_const_node *node, + grn_ts_any value) +{ + switch (node->data_kind) { + GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(BOOL, bool) + GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(INT, int) + GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(FLOAT, float) + GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(TIME, time) + case GRN_TS_TEXT: { + grn_rc rc = grn_ts_buf_write(ctx, &node->text_buf, + value.as_text.ptr, value.as_text.size); + if (rc != GRN_SUCCESS) { + return rc; + } + node->content.as_text.ptr = (const char *)node->text_buf.ptr; + node->content.as_text.size = value.as_text.size; + return GRN_SUCCESS; + } + GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE(GEO, geo) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} +#undef GRN_TS_EXPR_CONST_NODE_SET_SCALAR_CASE + +#define GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(KIND, kind)\ + case GRN_TS_ ## KIND ## _VECTOR: {\ + grn_rc rc;\ + size_t n_bytes;\ + const grn_ts_ ## kind *buf_ptr;\ + grn_ts_ ## kind ## _vector vector;\ + vector = value.as_ ## kind ## _vector;\ + n_bytes = sizeof(grn_ts_ ## kind) * vector.size;\ + rc = grn_ts_buf_write(ctx, &node->vector_buf, vector.ptr, n_bytes);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + buf_ptr = (const grn_ts_ ## kind *)node->vector_buf.ptr;\ + node->content.as_ ## kind ## _vector.ptr = buf_ptr;\ + node->content.as_ ## kind ## _vector.size = vector.size;\ + return GRN_SUCCESS;\ + } +/* grn_ts_expr_const_node_set_vector() sets a vector value. */ +static grn_rc +grn_ts_expr_const_node_set_vector(grn_ctx *ctx, grn_ts_expr_const_node *node, + grn_ts_any value) +{ + switch (node->data_kind) { + GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(BOOL, bool) + GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(INT, int) + GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(FLOAT, float) + GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(TIME, time) + case GRN_TS_TEXT_VECTOR: { + grn_rc rc; + size_t i, n_bytes, offset, total_size; + grn_ts_text_vector vector = value.as_text_vector; + grn_ts_text *vector_buf; + char *text_buf; + n_bytes = sizeof(grn_ts_text) * vector.size; + rc = grn_ts_buf_resize(ctx, &node->vector_buf, n_bytes); + if (rc != GRN_SUCCESS) { + return rc; + } + vector_buf = (grn_ts_text *)node->vector_buf.ptr; + total_size = 0; + for (i = 0; i < vector.size; i++) { + total_size += vector.ptr[i].size; + } + rc = grn_ts_buf_resize(ctx, &node->text_buf, total_size); + if (rc != GRN_SUCCESS) { + return rc; + } + text_buf = (char *)node->text_buf.ptr; + offset = 0; + for (i = 0; i < vector.size; i++) { + grn_memcpy(text_buf + offset, vector.ptr[i].ptr, vector.ptr[i].size); + vector_buf[i].ptr = text_buf + offset; + vector_buf[i].size = vector.ptr[i].size; + offset += vector.ptr[i].size; + } + node->content.as_text_vector.ptr = vector_buf; + node->content.as_text_vector.size = vector.size; + return GRN_SUCCESS; + } + GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE(GEO, geo) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} +#undef GRN_TS_EXPR_CONST_NODE_SET_VECTOR_CASE + +#define GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(KIND, kind)\ + case GRN_TS_ ## KIND: {\ + if (!grn_ts_ ## kind ## _is_valid(value.as_ ## kind)) {\ + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument");\ + }\ + return GRN_SUCCESS;\ + } +static grn_rc +grn_ts_expr_const_node_check_value(grn_ctx *ctx, grn_ts_data_kind kind, + grn_ts_any value) +{ + switch (kind) { + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(BOOL, bool) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(INT, int) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(FLOAT, float) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(TIME, time) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(TEXT, text) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(GEO, geo) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(BOOL_VECTOR, bool_vector) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(INT_VECTOR, int_vector) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(FLOAT_VECTOR, float_vector) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(TIME_VECTOR, time_vector) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(TEXT_VECTOR, text_vector) + GRN_TS_EXPR_CONST_NODE_CHECK_VALUE(GEO_VECTOR, geo_vector) + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + } +} +#undef GRN_TS_EXPR_CONST_NODE_CHECK_VALUE + +grn_rc +grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind data_kind, + grn_ts_data_type data_type, + grn_ts_any value, grn_ts_expr_node **node) +{ + grn_rc rc = grn_ts_expr_const_node_check_value(ctx, data_kind, value); + grn_ts_expr_const_node *new_node; + if (rc != GRN_SUCCESS) { + return rc; + } + new_node = GRN_MALLOCN(grn_ts_expr_const_node, 1); + if (!new_node) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_expr_const_node)); + } + grn_ts_expr_const_node_init(ctx, new_node); + new_node->data_kind = data_kind; + if (data_type != GRN_DB_VOID) { + new_node->data_type = data_type; + } else { + new_node->data_type = grn_ts_data_kind_to_type(data_kind); + } + if (data_kind & GRN_TS_VECTOR_FLAG) { + rc = grn_ts_expr_const_node_set_vector(ctx, new_node, value); + } else { + rc = grn_ts_expr_const_node_set_scalar(ctx, new_node, value); + } + if (rc != GRN_SUCCESS) { + grn_ts_expr_const_node_fin(ctx, new_node); + GRN_FREE(new_node); + return rc; + } + *node = (grn_ts_expr_node *)new_node; + return GRN_SUCCESS; +} + +/* grn_ts_expr_const_node_close() destroys a node. */ +static void +grn_ts_expr_const_node_close(grn_ctx *ctx, grn_ts_expr_const_node *node) +{ + grn_ts_expr_const_node_fin(ctx, node); + GRN_FREE(node); +} + +#define GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(KIND, kind)\ + case GRN_TS_ ## KIND: {\ + size_t i;\ + grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = node->content.as_ ## kind;\ + }\ + return GRN_SUCCESS;\ + } +#define GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(KIND, kind)\ + GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(KIND ## _VECTOR, kind ## _vector) +/* grn_ts_expr_const_node_evaluate() outputs the stored const. */ +static grn_rc +grn_ts_expr_const_node_evaluate(grn_ctx *ctx, grn_ts_expr_const_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + switch (node->data_kind) { + GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(BOOL, bool) + GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(INT, int) + GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(FLOAT, float) + GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(TIME, time) + GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(TEXT, text) + GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE(GEO, geo) + GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(BOOL, bool) + GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(INT, int) + GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(FLOAT, float) + GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(TIME, time) + GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(TEXT, text) + GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE(GEO, geo) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} +#undef GRN_TS_EXPR_CONST_NODE_EVALUATE_VECTOR_CASE +#undef GRN_TS_EXPR_CONST_NODE_EVALUATE_CASE + +/* grn_ts_expr_const_node_filter() filters records. */ +static grn_rc +grn_ts_expr_const_node_filter(grn_ctx *ctx, grn_ts_expr_const_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + if (node->content.as_bool) { + /* All the records pass through the filter. */ + if (in != out) { + size_t i; + for (i = 0; i < n_in; i++) { + out[i] = in[i]; + } + } + *n_out = n_in; + } else { + /* All the records are discarded. */ + *n_out = 0; + } + return GRN_SUCCESS; +} + +/* grn_ts_expr_const_node_adjust() updates scores. */ +static grn_rc +grn_ts_expr_const_node_adjust(grn_ctx *ctx, grn_ts_expr_const_node *node, + grn_ts_record *io, size_t n_io) +{ + size_t i; + grn_ts_score score = (grn_ts_score)node->content.as_float; + for (i = 0; i < n_io; i++) { + io[i].score = score; + } + return GRN_SUCCESS; +} + +/*------------------------------------------------------------- + * grn_ts_expr_column_node. + */ + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS + grn_obj *column; + grn_ts_buf buf; + grn_ts_buf body_buf; + grn_ja_reader *reader; +} grn_ts_expr_column_node; + +/* grn_ts_expr_column_node_init() initializes a node. */ +static void +grn_ts_expr_column_node_init(grn_ctx *ctx, grn_ts_expr_column_node *node) +{ + memset(node, 0, sizeof(*node)); + node->type = GRN_TS_EXPR_COLUMN_NODE; + node->column = NULL; + grn_ts_buf_init(ctx, &node->buf); + grn_ts_buf_init(ctx, &node->body_buf); + node->reader = NULL; +} + +/* grn_ts_expr_column_node_fin() finalizes a node. */ +static void +grn_ts_expr_column_node_fin(grn_ctx *ctx, grn_ts_expr_column_node *node) +{ + if (node->reader) { + grn_ja_reader_close(ctx, node->reader); + } + grn_ts_buf_fin(ctx, &node->body_buf); + grn_ts_buf_fin(ctx, &node->buf); + if (node->column) { + grn_obj_unlink(ctx, node->column); + } +} + +#define GRN_TS_EXPR_COLUMN_NODE_OPEN_CASE(TYPE)\ + case GRN_DB_ ## TYPE: {\ + GRN_ ## TYPE ## _INIT(&new_node->buf, GRN_OBJ_VECTOR);\ + break;\ + } +grn_rc +grn_ts_expr_column_node_open(grn_ctx *ctx, grn_obj *column, + grn_ts_expr_node **node) +{ + grn_rc rc; + grn_ts_expr_column_node *new_node = GRN_MALLOCN(grn_ts_expr_column_node, 1); + if (!new_node) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_expr_column_node)); + } + grn_ts_expr_column_node_init(ctx, new_node); + new_node->data_kind = grn_ts_data_type_to_kind(DB_OBJ(column)->range); + if (column->header.type == GRN_COLUMN_VAR_SIZE) { + grn_obj_flags type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK; + if (type == GRN_OBJ_COLUMN_VECTOR) { + new_node->data_kind |= GRN_TS_VECTOR_FLAG; + } + } + new_node->data_type = DB_OBJ(column)->range; + rc = grn_ts_obj_increment_ref_count(ctx, column); + if (rc != GRN_SUCCESS) { + grn_ts_expr_column_node_fin(ctx, new_node); + GRN_FREE(new_node); + return rc; + } + new_node->column = column; + *node = (grn_ts_expr_node *)new_node; + return GRN_SUCCESS; +} +#undef GRN_TS_EXPR_COLUMN_NODE_OPEN_CASE + +/* grn_ts_expr_column_node_close() destroys a node. */ +static void +grn_ts_expr_column_node_close(grn_ctx *ctx, grn_ts_expr_column_node *node) +{ + grn_ts_expr_column_node_fin(ctx, node); + GRN_FREE(node); +} + +#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(KIND, kind)\ + case GRN_TS_ ## KIND: {\ + size_t i;\ + grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ + grn_ra *ra = (grn_ra *)node->column;\ + grn_ra_cache cache;\ + GRN_RA_CACHE_INIT(ra, &cache);\ + for (i = 0; i < n_in; i++) {\ + grn_ts_ ## kind *ptr = NULL;\ + if (in[i].id) {\ + ptr = (grn_ts_ ## kind *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache);\ + }\ + out_ptr[i] = ptr ? *ptr : grn_ts_ ## kind ## _zero();\ + }\ + GRN_RA_CACHE_FIN(ra, &cache);\ + return GRN_SUCCESS;\ + } +#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(TYPE, type)\ + case GRN_DB_ ## TYPE: {\ + size_t i;\ + grn_ts_int *out_ptr = (grn_ts_int *)out;\ + grn_ra *ra = (grn_ra *)node->column;\ + grn_ra_cache cache;\ + GRN_RA_CACHE_INIT(ra, &cache);\ + for (i = 0; i < n_in; i++) {\ + type ## _t *ptr = NULL;\ + if (in[i].id) {\ + ptr = (type ## _t *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache);\ + }\ + out_ptr[i] = ptr ? (grn_ts_int)*ptr : grn_ts_int_zero();\ + }\ + GRN_RA_CACHE_FIN(ra, &cache);\ + return GRN_SUCCESS;\ + } +/* grn_ts_expr_column_node_evaluate_scalar() outputs scalar column values. */ +static grn_rc +grn_ts_expr_column_node_evaluate_scalar(grn_ctx *ctx, + grn_ts_expr_column_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + switch (node->data_kind) { + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(BOOL, bool) + case GRN_TS_INT: { + switch (node->data_type) { + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT8, int8) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT16, int16) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT32, int32) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(INT64, int64) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT8, uint8) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT16, uint16) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT32, uint32) + /* The behavior is undefined if a value is greater than 2^63 - 1. */ + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE(UINT64, uint64) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", + node->data_type); + } + } + } + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(FLOAT, float) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(TIME, time) + case GRN_TS_TEXT: { + size_t i; + char *buf_ptr; + grn_rc rc; + grn_ts_text *out_ptr = (grn_ts_text *)out; + if (!node->reader) { + rc = grn_ja_reader_open(ctx, (grn_ja *)node->column, &node->reader); + if (rc != GRN_SUCCESS) { + GRN_TS_ERR_RETURN(rc, "grn_ja_reader_open failed"); + } + } else { + grn_ja_reader_unref(ctx, node->reader); + } + node->buf.pos = 0; + for (i = 0; i < n_in; i++) { + rc = grn_ja_reader_seek(ctx, node->reader, in[i].id); + if (rc == GRN_SUCCESS) { + if (node->reader->ref_avail) { + void *addr; + rc = grn_ja_reader_ref(ctx, node->reader, &addr); + if (rc == GRN_SUCCESS) { + out_ptr[i].ptr = (char *)addr; + } + } else { + rc = grn_ts_buf_reserve(ctx, &node->buf, + node->buf.pos + node->reader->value_size); + if (rc == GRN_SUCCESS) { + rc = grn_ja_reader_read(ctx, node->reader, + (char *)node->buf.ptr + node->buf.pos); + if (rc == GRN_SUCCESS) { + out_ptr[i].ptr = NULL; + node->buf.pos += node->reader->value_size; + } + } + } + } + if (rc == GRN_SUCCESS) { + out_ptr[i].size = node->reader->value_size; + } else { + out_ptr[i].ptr = NULL; + out_ptr[i].size = 0; + } + } + buf_ptr = (char *)node->buf.ptr; + for (i = 0; i < n_in; i++) { + if (!out_ptr[i].ptr) { + out_ptr[i].ptr = buf_ptr; + buf_ptr += out_ptr[i].size; + } + } + return GRN_SUCCESS; + } + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE(GEO, geo) + case GRN_TS_REF: { + size_t i; + grn_ts_ref *out_ptr = (grn_ts_ref *)out; + grn_ra *ra = (grn_ra *)node->column; + grn_ra_cache cache; + GRN_RA_CACHE_INIT(ra, &cache); + for (i = 0; i < n_in; i++) { + grn_ts_id *ptr = NULL; + if (in[i].id) { + ptr = (grn_ts_id *)grn_ra_ref_cache(ctx, ra, in[i].id, &cache); + } + out_ptr[i].id = ptr ? *ptr : GRN_ID_NIL; + out_ptr[i].score = in[i].score; + } + GRN_RA_CACHE_FIN(ra, &cache); + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} +#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_INT_CASE +#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_SCALAR_CASE + +/* + * grn_ts_expr_column_node_evaluate_text_vector() outputs text vector column + * values. + */ +static grn_rc +grn_ts_expr_column_node_evaluate_text_vector(grn_ctx *ctx, + grn_ts_expr_column_node *node, + const grn_ts_record *in, + size_t n_in, void *out) +{ + grn_rc rc; + char *buf_ptr; + size_t i, j, n_bytes, n_values, total_n_bytes = 0, total_n_values = 0; + grn_ts_text *text_ptr; + grn_ts_text_vector *out_ptr = (grn_ts_text_vector *)out; + /* Read encoded values into node->body_buf and get the size of each value. */ + node->body_buf.pos = 0; + for (i = 0; i < n_in; i++) { + char *ptr; + rc = grn_ts_ja_get_value(ctx, node->column, in[i].id, + &node->body_buf, &n_bytes); + if (rc == GRN_SUCCESS) { + ptr = (char *)node->body_buf.ptr + total_n_bytes; + GRN_B_DEC(n_values, ptr); + } else { + n_bytes = 0; + n_values = 0; + } + grn_memcpy(&out_ptr[i].ptr, &n_bytes, sizeof(n_bytes)); + out_ptr[i].size = n_values; + total_n_bytes += n_bytes; + total_n_values += n_values; + } + /* Resize node->buf. */ + n_bytes = sizeof(grn_ts_text) * total_n_values; + rc = grn_ts_buf_reserve(ctx, &node->buf, n_bytes); + if (rc != GRN_SUCCESS) { + return rc; + } + /* Decode values and compose the result. */ + buf_ptr = (char *)node->body_buf.ptr; + text_ptr = (grn_ts_text *)node->buf.ptr; + for (i = 0; i < n_in; i++) { + char *ptr = buf_ptr; + grn_memcpy(&n_bytes, &out_ptr[i].ptr, sizeof(n_bytes)); + buf_ptr += n_bytes; + GRN_B_DEC(n_values, ptr); + out_ptr[i].ptr = text_ptr; + for (j = 0; j < out_ptr[i].size; j++) { + GRN_B_DEC(text_ptr[j].size, ptr); + } + for (j = 0; j < out_ptr[i].size; j++) { + text_ptr[j].ptr = ptr; + ptr += text_ptr[j].size; + } + text_ptr += out_ptr[i].size; + } + return GRN_SUCCESS; +} + +/* + * grn_ts_expr_column_node_evaluate_ref_vector() outputs ref vector column + * values. + */ +static grn_rc +grn_ts_expr_column_node_evaluate_ref_vector(grn_ctx *ctx, + grn_ts_expr_column_node *node, + const grn_ts_record *in, + size_t n_in, void *out) +{ + grn_rc rc; + size_t i, j, n_bytes, offset = 0; + grn_ts_id *buf_ptr; + grn_ts_ref *ref_ptr; + grn_ts_ref_vector *out_ptr = (grn_ts_ref_vector *)out; + /* Read column values into node->body_buf and get the size of each value. */ + node->body_buf.pos = 0; + for (i = 0; i < n_in; i++) { + size_t size; + rc = grn_ts_ja_get_value(ctx, node->column, in[i].id, + &node->body_buf, &size); + if (rc == GRN_SUCCESS) { + out_ptr[i].size = size / sizeof(grn_ts_id); + offset += out_ptr[i].size; + } else { + out_ptr[i].size = 0; + } + } + /* Resize node->buf. */ + n_bytes = sizeof(grn_ts_ref) * offset; + rc = grn_ts_buf_reserve(ctx, &node->buf, n_bytes); + if (rc != GRN_SUCCESS) { + return rc; + } + /* Compose the result. */ + buf_ptr = (grn_ts_id *)node->body_buf.ptr; + ref_ptr = (grn_ts_ref *)node->buf.ptr; + for (i = 0; i < n_in; i++) { + out_ptr[i].ptr = ref_ptr; + for (j = 0; j < out_ptr[i].size; j++, buf_ptr++, ref_ptr++) { + ref_ptr->id = *buf_ptr; + ref_ptr->score = in[i].score; + } + } + return GRN_SUCCESS; +} + +#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(KIND, kind)\ + case GRN_TS_ ## KIND ## _VECTOR: {\ + size_t i;\ + grn_ts_ ## kind *buf_ptr;\ + grn_ts_ ## kind ## _vector *out_ptr = (grn_ts_ ## kind ## _vector *)out;\ + /* Read column values into node->buf and save the size of each value. */\ + node->buf.pos = 0;\ + for (i = 0; i < n_in; i++) {\ + size_t n_bytes;\ + grn_rc rc = grn_ts_ja_get_value(ctx, node->column, in[i].id,\ + &node->buf, &n_bytes);\ + if (rc == GRN_SUCCESS) {\ + out_ptr[i].size = n_bytes / sizeof(grn_ts_ ## kind);\ + } else {\ + out_ptr[i].size = 0;\ + }\ + }\ + buf_ptr = (grn_ts_ ## kind *)node->buf.ptr;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i].ptr = buf_ptr;\ + buf_ptr += out_ptr[i].size;\ + }\ + return GRN_SUCCESS;\ + } +#define GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(TYPE, type)\ + case GRN_DB_ ## TYPE: {\ + size_t i, j;\ + grn_ts_int *buf_ptr;\ + grn_ts_int_vector *out_ptr = (grn_ts_int_vector *)out;\ + /* + * Read column values into body_buf and typecast the values to grn_ts_int. + * Then, store the grn_ts_int values into node->buf and save the size of + * each value. + */\ + node->buf.pos = 0;\ + for (i = 0; i < n_in; i++) {\ + grn_rc rc;\ + size_t n_bytes, new_n_bytes;\ + node->body_buf.pos = 0;\ + rc = grn_ts_ja_get_value(ctx, node->column, in[i].id,\ + &node->body_buf, &n_bytes);\ + if (rc == GRN_SUCCESS) {\ + out_ptr[i].size = n_bytes / sizeof(type ## _t);\ + } else {\ + out_ptr[i].size = 0;\ + }\ + new_n_bytes = node->buf.pos + (sizeof(grn_ts_int) * out_ptr[i].size);\ + rc = grn_ts_buf_reserve(ctx, &node->buf, new_n_bytes);\ + if (rc == GRN_SUCCESS) {\ + type ## _t *src_ptr = (type ## _t *)node->body_buf.ptr;\ + grn_ts_int *dest_ptr;\ + dest_ptr = (grn_ts_int *)((char *)node->buf.ptr + node->buf.pos);\ + for (j = 0; j < out_ptr[i].size; j++) {\ + dest_ptr[j] = (grn_ts_int)src_ptr[j];\ + }\ + node->buf.pos = new_n_bytes;\ + } else {\ + out_ptr[i].size = 0;\ + }\ + }\ + buf_ptr = (grn_ts_int *)node->buf.ptr;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i].ptr = buf_ptr;\ + buf_ptr += out_ptr[i].size;\ + }\ + return GRN_SUCCESS;\ + } +/* grn_ts_expr_column_node_evaluate_vector() outputs vector column values. */ +static grn_rc +grn_ts_expr_column_node_evaluate_vector(grn_ctx *ctx, + grn_ts_expr_column_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + switch (node->data_kind) { + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(BOOL, bool) + case GRN_TS_INT_VECTOR: { + switch (node->data_type) { + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT8, int8) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT16, int16) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT32, int32) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(INT64, int64) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT8, uint8) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT16, uint16) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT32, uint32) + /* The behavior is undefined if a value is greater than 2^63 - 1. */ + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE(UINT64, uint64) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", + node->data_type); + } + } + } + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(FLOAT, float) + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(TIME, time) + case GRN_TS_TEXT_VECTOR: { + return grn_ts_expr_column_node_evaluate_text_vector(ctx, node, in, n_in, + out); + } + GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE(GEO, geo) + case GRN_TS_REF_VECTOR: { + return grn_ts_expr_column_node_evaluate_ref_vector(ctx, node, in, n_in, + out); + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} +#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_INT_CASE +#undef GRN_TS_EXPR_COLUMN_NODE_EVALUATE_VECTOR_CASE + +/* grn_ts_expr_column_node_evaluate() outputs column values. */ +static grn_rc +grn_ts_expr_column_node_evaluate(grn_ctx *ctx, grn_ts_expr_column_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + if (node->data_kind & GRN_TS_VECTOR_FLAG) { + return grn_ts_expr_column_node_evaluate_vector(ctx, node, in, n_in, out); + } else { + return grn_ts_expr_column_node_evaluate_scalar(ctx, node, in, n_in, out); + } +} + +/* grn_ts_expr_column_node_filter() filters records. */ +static grn_rc +grn_ts_expr_column_node_filter(grn_ctx *ctx, grn_ts_expr_column_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + size_t i, count = 0; + grn_ra *ra = (grn_ra *)node->column; + grn_ra_cache cache; + GRN_RA_CACHE_INIT(ra, &cache); + for (i = 0; i < n_in; i++) { + grn_ts_bool *ptr = NULL; + if (in[i].id) { + ptr = grn_ra_ref_cache(ctx, ra, in[i].id, &cache); + } + if (ptr && *ptr) { + out[count++] = in[i]; + } + } + GRN_RA_CACHE_FIN(ra, &cache); + *n_out = count; + return GRN_SUCCESS; +} + +/* grn_ts_expr_column_node_adjust() updates scores. */ +static grn_rc +grn_ts_expr_column_node_adjust(grn_ctx *ctx, grn_ts_expr_column_node *node, + grn_ts_record *io, size_t n_io) +{ + size_t i; + grn_ra *ra = (grn_ra *)node->column; + grn_ra_cache cache; + GRN_RA_CACHE_INIT(ra, &cache); + for (i = 0; i < n_io; i++) { + grn_ts_float *ptr = NULL; + if (io[i].id) { + ptr = grn_ra_ref_cache(ctx, ra, io[i].id, &cache); + } + if (ptr) { + io[i].score = (grn_ts_score)*ptr; + } + } + GRN_RA_CACHE_FIN(ra, &cache); + return GRN_SUCCESS; +} + +/*------------------------------------------------------------- + * grn_ts_expr_op_node. + */ + +enum { + GRN_TS_EXPR_OP_NODE_MAX_N_ARGS = 3, + GRN_TS_EXPR_OP_NODE_N_BUFS = 3 +}; + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS + grn_ts_op_type op_type; + grn_ts_expr_node *args[GRN_TS_EXPR_OP_NODE_MAX_N_ARGS]; + size_t n_args; + grn_ts_buf bufs[GRN_TS_EXPR_OP_NODE_N_BUFS]; +} grn_ts_expr_op_node; + +/* grn_ts_expr_op_node_init() initializes a node. */ +static void +grn_ts_expr_op_node_init(grn_ctx *ctx, grn_ts_expr_op_node *node) +{ + size_t i; + memset(node, 0, sizeof(*node)); + node->type = GRN_TS_EXPR_OP_NODE; + for (i = 0; i < GRN_TS_EXPR_OP_NODE_MAX_N_ARGS; i++) { + node->args[i] = NULL; + } + for (i = 0; i < GRN_TS_EXPR_OP_NODE_N_BUFS; i++) { + grn_ts_buf_init(ctx, &node->bufs[i]); + } +} + +/* grn_ts_expr_op_node_fin() finalizes a node. */ +static void +grn_ts_expr_op_node_fin(grn_ctx *ctx, grn_ts_expr_op_node *node) +{ + size_t i; + for (i = 0; i < GRN_TS_EXPR_OP_NODE_N_BUFS; i++) { + grn_ts_buf_fin(ctx, &node->bufs[i]); + } + for (i = 0; i < GRN_TS_EXPR_OP_NODE_MAX_N_ARGS; i++) { + if (node->args[i]) { + grn_ts_expr_node_close(ctx, node->args[i]); + } + } +} + +/* + * grn_ts_expr_op_node_deref_args_for_equal() resolves references if required. + */ +static grn_rc +grn_ts_expr_op_node_deref_args_for_equal(grn_ctx *ctx, + grn_ts_expr_op_node *node) +{ + grn_rc rc; + if (node->n_args != 2) { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid #args: %" GRN_FMT_SIZE, + node->n_args); + } + if ((node->args[0]->data_kind & ~GRN_TS_VECTOR_FLAG) != GRN_TS_REF) { + return grn_ts_expr_node_deref(ctx, &node->args[1]); + } + if ((node->args[1]->data_kind & ~GRN_TS_VECTOR_FLAG) != GRN_TS_REF) { + return grn_ts_expr_node_deref(ctx, &node->args[0]); + } + + /* FIXME: Arguments should be compared as references if possible. */ + rc = grn_ts_expr_node_deref(ctx, &node->args[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_node_deref(ctx, &node->args[1]); + if (rc != GRN_SUCCESS) { + return rc; + } + return GRN_SUCCESS; +} + +/* grn_ts_expr_op_node_deref_args() resolves references if required. */ +static grn_rc +grn_ts_expr_op_node_deref_args(grn_ctx *ctx, grn_ts_expr_op_node *node) +{ + switch (node->op_type) { + case GRN_TS_OP_EQUAL: + case GRN_TS_OP_NOT_EQUAL: { + return grn_ts_expr_op_node_deref_args_for_equal(ctx, node); + } + /* TODO: Add a ternary operator. */ + default: { + size_t i; + for (i = 0; i < node->n_args; i++) { + grn_rc rc = grn_ts_expr_node_deref(ctx, &node->args[i]); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; + } + } +} + +/* + * grn_ts_op_plus_check_args() checks arguments. Note that arguments are + * rearranged in some cases. + */ +static grn_rc +grn_ts_op_plus_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) +{ + grn_rc rc; + if ((node->args[0]->data_kind == GRN_TS_INT) && + (node->args[1]->data_kind == GRN_TS_FLOAT)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_FLOAT, &node->args[0], + 1, &node->args[0]); + if (rc != GRN_SUCCESS) { + node->args[0] = NULL; + return rc; + } + } else if ((node->args[0]->data_kind == GRN_TS_FLOAT) && + (node->args[1]->data_kind == GRN_TS_INT)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_FLOAT, &node->args[1], + 1, &node->args[1]); + if (rc != GRN_SUCCESS) { + node->args[1] = NULL; + return rc; + } + } + + switch (node->args[0]->data_kind) { + case GRN_TS_INT: { + switch (node->args[1]->data_kind) { + case GRN_TS_INT: { + /* Int + Int = Int. */ + node->data_kind = GRN_TS_INT; + node->data_type = GRN_DB_INT64; + return GRN_SUCCESS; + } + case GRN_TS_TIME: { + /* Int + Time = Time + Int = Time. */ + grn_ts_expr_node *tmp = node->args[0]; + node->args[0] = node->args[1]; + node->args[1] = tmp; + node->data_kind = GRN_TS_TIME; + node->data_type = GRN_DB_TIME; + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[1]->data_kind); + } + } + } + case GRN_TS_FLOAT: { + switch (node->args[1]->data_kind) { + case GRN_TS_FLOAT: { + /* Float + Float = Float. */ + node->data_kind = GRN_TS_FLOAT; + node->data_type = GRN_DB_FLOAT; + return GRN_SUCCESS; + } + case GRN_TS_TIME: { + /* Float + Time = Time + Float = Time. */ + grn_ts_expr_node *tmp = node->args[0]; + node->args[0] = node->args[1]; + node->args[1] = tmp; + node->data_kind = GRN_TS_TIME; + node->data_type = GRN_DB_TIME; + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[1]->data_kind); + } + } + } + case GRN_TS_TIME: { + switch (node->args[1]->data_kind) { + case GRN_TS_INT: + case GRN_TS_FLOAT: { + /* Time + Int or Float = Time. */ + node->data_kind = GRN_TS_TIME; + node->data_type = GRN_DB_TIME; + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[1]->data_kind); + } + } + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } +} + +/* grn_ts_op_minus_check_args() checks arguments. */ +static grn_rc +grn_ts_op_minus_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) +{ + grn_rc rc; + if ((node->args[0]->data_kind == GRN_TS_INT) && + (node->args[1]->data_kind == GRN_TS_FLOAT)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_FLOAT, &node->args[0], + 1, &node->args[0]); + if (rc != GRN_SUCCESS) { + node->args[0] = NULL; + return rc; + } + } else if ((node->args[0]->data_kind == GRN_TS_FLOAT) && + (node->args[1]->data_kind == GRN_TS_INT)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_FLOAT, &node->args[1], + 1, &node->args[1]); + if (rc != GRN_SUCCESS) { + node->args[1] = NULL; + return rc; + } + } + + switch (node->args[0]->data_kind) { + case GRN_TS_INT: { + if (node->args[1]->data_kind != GRN_TS_INT) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[1]->data_kind); + } + /* Int - Int = Int. */ + node->data_kind = GRN_TS_INT; + node->data_type = GRN_DB_INT64; + return GRN_SUCCESS; + } + case GRN_TS_FLOAT: { + if (node->args[1]->data_kind != GRN_TS_FLOAT) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[1]->data_kind); + } + /* Float - Float = Float. */ + node->data_kind = GRN_TS_FLOAT; + node->data_type = GRN_DB_FLOAT; + return GRN_SUCCESS; + } + case GRN_TS_TIME: { + switch (node->args[1]->data_kind) { + case GRN_TS_INT: + case GRN_TS_FLOAT: { + /* Time - Int or Float = Time. */ + node->data_kind = GRN_TS_TIME; + node->data_type = GRN_DB_TIME; + return GRN_SUCCESS; + } + case GRN_TS_TIME: { + /* Time - Time = Float. */ + node->data_kind = GRN_TS_FLOAT; + node->data_type = GRN_DB_FLOAT; + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[1]->data_kind); + } + } + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } +} + +/* + * grn_ts_expr_op_node_typecast_args_for_cmp() inserts a typecast operator for + * comparison. + */ +static grn_rc +grn_ts_expr_op_node_typecast_args_for_cmp(grn_ctx *ctx, + grn_ts_expr_op_node *node) +{ + grn_rc rc; + if ((node->args[0]->data_kind == GRN_TS_INT) && + (node->args[1]->data_kind == GRN_TS_FLOAT)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_FLOAT, &node->args[0], + 1, &node->args[0]); + if (rc != GRN_SUCCESS) { + node->args[0] = NULL; + return rc; + } + } else if ((node->args[0]->data_kind == GRN_TS_FLOAT) && + (node->args[1]->data_kind == GRN_TS_INT)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_FLOAT, &node->args[1], + 1, &node->args[1]); + if (rc != GRN_SUCCESS) { + node->args[1] = NULL; + return rc; + } + } else if ((node->args[0]->data_kind == GRN_TS_TIME) && + (node->args[1]->data_kind == GRN_TS_TEXT)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_TIME, &node->args[1], + 1, &node->args[1]); + if (rc != GRN_SUCCESS) { + node->args[1] = NULL; + return rc; + } + } else if ((node->args[0]->data_kind == GRN_TS_TEXT) && + (node->args[1]->data_kind == GRN_TS_TIME)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_TIME, &node->args[0], + 1, &node->args[0]); + if (rc != GRN_SUCCESS) { + node->args[0] = NULL; + return rc; + } + } else { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "data kind conflict: %d != %d", + node->args[0]->data_kind, + node->args[1]->data_kind); + } + return GRN_SUCCESS; +} + +/* + * grn_ts_expr_op_node_check_args() checks the combination of an operator and + * its arguments. + */ +static grn_rc +grn_ts_expr_op_node_check_args(grn_ctx *ctx, grn_ts_expr_op_node *node) +{ + switch (node->op_type) { + case GRN_TS_OP_LOGICAL_NOT: { + if (node->args[0]->data_kind != GRN_TS_BOOL) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + node->data_kind = GRN_TS_BOOL; + node->data_type = GRN_DB_BOOL; + return GRN_SUCCESS; + } + case GRN_TS_OP_BITWISE_NOT: { + switch (node->args[0]->data_kind) { + case GRN_TS_BOOL: + case GRN_TS_INT: { + node->data_kind = node->args[0]->data_kind; + node->data_type = grn_ts_data_kind_to_type(node->data_kind); + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } + } + case GRN_TS_OP_POSITIVE: + case GRN_TS_OP_NEGATIVE: { + if ((node->args[0]->data_kind != GRN_TS_INT) && + (node->args[0]->data_kind != GRN_TS_FLOAT)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + node->data_kind = node->args[0]->data_kind; + node->data_type = grn_ts_data_kind_to_type(node->data_kind); + return GRN_SUCCESS; + } + case GRN_TS_OP_FLOAT: { + if (node->args[0]->data_kind != GRN_TS_INT) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + node->data_kind = GRN_TS_FLOAT; + node->data_type = GRN_DB_FLOAT; + return GRN_SUCCESS; + } + case GRN_TS_OP_TIME: { + if (node->args[0]->data_kind != GRN_TS_TEXT) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + node->data_kind = GRN_TS_TIME; + node->data_type = GRN_DB_TIME; + return GRN_SUCCESS; + } + case GRN_TS_OP_LOGICAL_AND: + case GRN_TS_OP_LOGICAL_OR: + case GRN_TS_OP_LOGICAL_SUB: { + if ((node->args[0]->data_kind != GRN_TS_BOOL) || + (node->args[1]->data_kind != GRN_TS_BOOL)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d, %d", + node->args[0]->data_kind, node->args[1]->data_kind); + } + node->data_kind = GRN_TS_BOOL; + node->data_type = GRN_DB_BOOL; + return GRN_SUCCESS; + } + case GRN_TS_OP_BITWISE_AND: + case GRN_TS_OP_BITWISE_OR: + case GRN_TS_OP_BITWISE_XOR: { + if (node->args[0]->data_kind != node->args[1]->data_kind) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data kind conflict: %d != %d", + node->args[0]->data_kind, node->args[1]->data_kind); + } + switch (node->args[0]->data_kind) { + case GRN_TS_BOOL: + case GRN_TS_INT: { + node->data_kind = node->args[0]->data_kind; + node->data_type = grn_ts_data_kind_to_type(node->data_kind); + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } + node->data_kind = GRN_TS_BOOL; + node->data_type = GRN_DB_BOOL; + return GRN_SUCCESS; + } + case GRN_TS_OP_EQUAL: + case GRN_TS_OP_NOT_EQUAL: { + grn_ts_data_kind scalar_data_kind; + if (node->args[0]->data_kind != node->args[1]->data_kind) { + grn_rc rc = grn_ts_expr_op_node_typecast_args_for_cmp(ctx, node); + if (rc != GRN_SUCCESS) { + return rc; + } + } + scalar_data_kind = node->args[0]->data_kind & ~GRN_TS_VECTOR_FLAG; + if (((scalar_data_kind == GRN_TS_REF) || + (scalar_data_kind == GRN_TS_GEO)) && + (node->args[0]->data_type != node->args[1]->data_type)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "data type conflict: %d != %d", + node->args[0]->data_type, node->args[1]->data_type); + } + node->data_kind = GRN_TS_BOOL; + node->data_type = GRN_DB_BOOL; + return GRN_SUCCESS; + } + case GRN_TS_OP_LESS: + case GRN_TS_OP_LESS_EQUAL: + case GRN_TS_OP_GREATER: + case GRN_TS_OP_GREATER_EQUAL: { + if (node->args[0]->data_kind != node->args[1]->data_kind) { + grn_rc rc = grn_ts_expr_op_node_typecast_args_for_cmp(ctx, node); + if (rc != GRN_SUCCESS) { + return rc; + } + } + switch (node->args[0]->data_kind) { + case GRN_TS_INT: + case GRN_TS_FLOAT: + case GRN_TS_TIME: + case GRN_TS_TEXT: + case GRN_TS_INT_VECTOR: + case GRN_TS_FLOAT_VECTOR: + case GRN_TS_TIME_VECTOR: + case GRN_TS_TEXT_VECTOR: { + node->data_kind = GRN_TS_BOOL; + node->data_type = GRN_DB_BOOL; + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } + case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: + case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: + case GRN_TS_OP_SHIFT_LOGICAL_LEFT: + case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { + if ((node->args[0]->data_kind != GRN_TS_INT) || + (node->args[1]->data_kind != GRN_TS_INT)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d, %d", + node->args[0]->data_kind, + node->args[1]->data_kind); + } + node->data_kind = GRN_TS_INT; + node->data_type = GRN_DB_INT64; + return GRN_SUCCESS; + } + case GRN_TS_OP_PLUS: { + return grn_ts_op_plus_check_args(ctx, node); + } + case GRN_TS_OP_MINUS: { + return grn_ts_op_minus_check_args(ctx, node); + } + case GRN_TS_OP_MULTIPLICATION: + case GRN_TS_OP_DIVISION: + case GRN_TS_OP_MODULUS: { + if (node->args[0]->data_kind != node->args[1]->data_kind) { + grn_rc rc; + if ((node->args[0]->data_kind == GRN_TS_INT) && + (node->args[1]->data_kind == GRN_TS_FLOAT)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_FLOAT, &node->args[0], + 1, &node->args[0]); + if (rc != GRN_SUCCESS) { + node->args[0] = NULL; + return rc; + } + } else if ((node->args[0]->data_kind == GRN_TS_FLOAT) && + (node->args[1]->data_kind == GRN_TS_INT)) { + rc = grn_ts_expr_op_node_open(ctx, GRN_TS_OP_FLOAT, &node->args[1], + 1, &node->args[1]); + if (rc != GRN_SUCCESS) { + node->args[1] = NULL; + return rc; + } + } else { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "data kind conflict: %d != %d", + node->args[0]->data_kind, + node->args[1]->data_kind); + } + } + switch (node->args[0]->data_kind) { + case GRN_TS_INT: + case GRN_TS_FLOAT: { + node->data_kind = node->args[0]->data_kind; + node->data_type = grn_ts_data_kind_to_type(node->data_kind); + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } + } + } + case GRN_TS_OP_MATCH: + case GRN_TS_OP_PREFIX_MATCH: + case GRN_TS_OP_SUFFIX_MATCH: { + if ((node->args[0]->data_kind != GRN_TS_TEXT) || + (node->args[1]->data_kind != GRN_TS_TEXT)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d, %d", + node->args[0]->data_kind, + node->args[1]->data_kind); + } + node->data_kind = GRN_TS_BOOL; + node->data_type = GRN_DB_BOOL; + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid operator: %d", + node->op_type); + } + } +} + +/* grn_ts_expr_op_node_setup() sets up an operator node. */ +static grn_rc +grn_ts_expr_op_node_setup(grn_ctx *ctx, grn_ts_expr_op_node *node) +{ + grn_rc rc = grn_ts_expr_op_node_deref_args(ctx, node); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_op_node_check_args(ctx, node); + if (rc != GRN_SUCCESS) { + return rc; + } + if (node->data_kind == GRN_TS_VOID) { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + GRN_TS_VOID); + } else if (node->data_type == GRN_DB_VOID) { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data type: %d", + GRN_DB_VOID); + } + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_op_node_open(grn_ctx *ctx, grn_ts_op_type op_type, + grn_ts_expr_node **args, size_t n_args, + grn_ts_expr_node **node) +{ + size_t i; + grn_rc rc; + grn_ts_expr_op_node *new_node = GRN_MALLOCN(grn_ts_expr_op_node, 1); + if (!new_node) { + for (i = 0; i < n_args; i++) { + grn_ts_expr_node_close(ctx, args[i]); + } + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_expr_op_node)); + } + grn_ts_expr_op_node_init(ctx, new_node); + new_node->op_type = op_type; + for (i = 0; i < n_args; i++) { + new_node->args[i] = args[i]; + } + new_node->n_args = n_args; + rc = grn_ts_expr_op_node_setup(ctx, new_node); + if (rc != GRN_SUCCESS) { + grn_ts_expr_op_node_fin(ctx, new_node); + GRN_FREE(new_node); + return rc; + } + *node = (grn_ts_expr_node *)new_node; + return GRN_SUCCESS; +} + +/* grn_ts_expr_op_node_close() destroys a node. */ +static void +grn_ts_expr_op_node_close(grn_ctx *ctx, grn_ts_expr_op_node *node) +{ + grn_ts_expr_op_node_fin(ctx, node); + GRN_FREE(node); +} + +/* grn_ts_op_logical_not_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_logical_not_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + size_t i; + grn_ts_bool *out_ptr = (grn_ts_bool *)out; + grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out); + if (rc != GRN_SUCCESS) { + return rc; + } + for (i = 0; i < n_in; i++) { + out_ptr[i] = grn_ts_op_logical_not_bool(out_ptr[i]); + } + return GRN_SUCCESS; +} + +/* grn_ts_op_bitwise_not_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_bitwise_not_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + size_t i; + grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out); + if (rc != GRN_SUCCESS) { + return rc; + } + switch (node->data_kind) { + case GRN_TS_BOOL: { + grn_ts_bool *out_ptr = (grn_ts_bool *)out; + for (i = 0; i < n_in; i++) { + out_ptr[i] = grn_ts_op_bitwise_not_bool(out_ptr[i]); + } + return GRN_SUCCESS; + } + case GRN_TS_INT: { + grn_ts_int *out_ptr = (grn_ts_int *)out; + for (i = 0; i < n_in; i++) { + out_ptr[i] = grn_ts_op_bitwise_not_int(out_ptr[i]); + } + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} + +#define GRN_TS_OP_SIGN_EVALUATE_CASE(type, KIND, kind) \ + case GRN_TS_ ## KIND: {\ + grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(out_ptr[i]);\ + }\ + return GRN_SUCCESS;\ + } +#define GRN_TS_OP_SIGN_EVALUATE(type) \ + size_t i;\ + grn_rc rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + switch (node->data_kind) {\ + GRN_TS_OP_SIGN_EVALUATE_CASE(type, INT, int)\ + GRN_TS_OP_SIGN_EVALUATE_CASE(type, FLOAT, float)\ + default: {\ + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ + node->data_kind);\ + }\ + } +/* grn_ts_op_positive_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_positive_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + GRN_TS_OP_SIGN_EVALUATE(positive) +} + +/* grn_ts_op_negative_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_negative_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + GRN_TS_OP_SIGN_EVALUATE(negative) +} +#undef GRN_TS_OP_SIGN_EVALUATE +#undef GRN_TS_OP_SIGN_EVALUATE_CASE + +/* grn_ts_op_float_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_float_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + size_t i; + grn_ts_int *buf_ptr; + grn_ts_float *out_ptr = (grn_ts_float *)out; + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptr = (grn_ts_int *)node->bufs[0].ptr; + for (i = 0; i < n_in; i++) { + rc = grn_ts_op_float(ctx, buf_ptr[i], &out_ptr[i]); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +/* grn_ts_op_time_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_time_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + size_t i; + grn_ts_text *buf_ptr; + grn_ts_time *out_ptr = (grn_ts_time *)out; + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptr = (grn_ts_text *)node->bufs[0].ptr; + for (i = 0; i < n_in; i++) { + rc = grn_ts_op_time(ctx, buf_ptr[i], &out_ptr[i]); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +/* grn_ts_op_logical_and_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_logical_and_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + size_t i, j, count; + grn_rc rc; + grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out; + grn_ts_buf *tmp_in_buf = &node->bufs[2]; + grn_ts_record *tmp_in; + + /* Evaluate the 1st argument. */ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; + + /* Create a list of true records. */ + rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); + if (rc != GRN_SUCCESS) { + return rc; + } + tmp_in = (grn_ts_record *)tmp_in_buf->ptr; + count = 0; + for (i = 0; i < n_in; i++) { + if (buf_ptrs[0][i]) { + tmp_in[count++] = in[i]; + } + } + + /* Evaluate the 2nd argument. */ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, + &node->bufs[1]); + buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; + + /* Merge the results. */ + count = 0; + for (i = 0, j = 0; i < n_in; i++) { + out_ptr[count++] = buf_ptrs[0][i] && buf_ptrs[1][j++]; + } + return GRN_SUCCESS; +} + +/* grn_ts_op_logical_or_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_logical_or_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + size_t i, j, count; + grn_rc rc; + grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out; + grn_ts_buf *tmp_in_buf = &node->bufs[2]; + grn_ts_record *tmp_in; + + /* Evaluate the 1st argument. */ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; + + /* Create a list of false records. */ + rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); + if (rc != GRN_SUCCESS) { + return rc; + } + tmp_in = (grn_ts_record *)tmp_in_buf->ptr; + count = 0; + for (i = 0; i < n_in; i++) { + if (!buf_ptrs[0][i]) { + tmp_in[count++] = in[i]; + } + } + + /* Evaluate the 2nd argument. */ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, + &node->bufs[1]); + buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; + + /* Merge the results. */ + count = 0; + for (i = 0, j = 0; i < n_in; i++) { + out_ptr[count++] = buf_ptrs[0][i] || buf_ptrs[1][j++]; + } + return GRN_SUCCESS; +} + +/* grn_ts_op_logical_sub_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_logical_sub_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + size_t i, j, count; + grn_rc rc; + grn_ts_bool *buf_ptrs[2], *out_ptr = (grn_ts_bool *)out; + grn_ts_buf *tmp_in_buf = &node->bufs[2]; + grn_ts_record *tmp_in; + + /* Evaluate the 1st argument. */ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; + + /* Create a list of true records. */ + rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); + if (rc != GRN_SUCCESS) { + return rc; + } + tmp_in = (grn_ts_record *)tmp_in_buf->ptr; + count = 0; + for (i = 0; i < n_in; i++) { + if (buf_ptrs[0][i]) { + tmp_in[count++] = in[i]; + } + } + + /* Evaluate the 2nd argument. */ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, + &node->bufs[1]); + buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; + + /* Merge the results. */ + count = 0; + for (i = 0, j = 0; i < n_in; i++) { + out_ptr[count++] = buf_ptrs[0][i] && + grn_ts_op_logical_not_bool(buf_ptrs[1][j++]); + } + return GRN_SUCCESS; +} + +#define GRN_TS_OP_BITWISE_EVALUATE_CASE(type, KIND, kind)\ + case GRN_TS_ ## KIND: {\ + /* + * Use the output buffer to put evaluation results of the 1st argument, + * because the data kind is same. + */\ + size_t i;\ + grn_rc rc;\ + grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ + rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ + if (rc == GRN_SUCCESS) {\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ + in, n_in, &node->bufs[0]);\ + if (rc == GRN_SUCCESS) {\ + grn_ts_ ## kind *buf_ptr = (grn_ts_ ## kind *)node->bufs[0].ptr;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = grn_ts_op_bitwise_ ## type ## _ ## kind(out_ptr[i],\ + buf_ptr[i]);\ + }\ + }\ + }\ + return rc;\ + } +/* grn_ts_op_bitwise_and_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_bitwise_and_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + switch (node->args[0]->data_kind) { + GRN_TS_OP_BITWISE_EVALUATE_CASE(and, BOOL, bool) + GRN_TS_OP_BITWISE_EVALUATE_CASE(and, INT, int) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } +} + +/* grn_ts_op_bitwise_or_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_bitwise_or_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + switch (node->args[0]->data_kind) { + GRN_TS_OP_BITWISE_EVALUATE_CASE(or, BOOL, bool) + GRN_TS_OP_BITWISE_EVALUATE_CASE(or, INT, int) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } +} + +/* grn_ts_op_bitwise_xor_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_bitwise_xor_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + switch (node->args[0]->data_kind) { + GRN_TS_OP_BITWISE_EVALUATE_CASE(xor, BOOL, bool) + GRN_TS_OP_BITWISE_EVALUATE_CASE(xor, INT, int) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } +} +#undef GRN_TS_OP_BITWISE_EVALUATE_CASE + +#define GRN_TS_OP_CHK_EVALUATE_CASE(type, KIND, kind)\ + case GRN_TS_ ## KIND: {\ + grn_ts_ ## kind *buf_ptrs[] = {\ + (grn_ts_ ## kind *)node->bufs[0].ptr,\ + (grn_ts_ ## kind *)node->bufs[1].ptr\ + };\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i],\ + buf_ptrs[1][i]);\ + }\ + return GRN_SUCCESS;\ + } +#define GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, KIND, kind)\ + GRN_TS_OP_CHK_EVALUATE_CASE(type, KIND ## _VECTOR, kind ## _vector) +#define GRN_TS_OP_CHK_EVALUATE(type)\ + size_t i;\ + grn_rc rc;\ + grn_ts_bool *out_ptr = (grn_ts_bool *)out;\ + if (node->args[0]->data_kind == GRN_TS_BOOL) {\ + /* + * Use the output buffer to put evaluation results of the 1st argument, + * because the data kind is same. + */\ + rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ + if (rc == GRN_SUCCESS) {\ + grn_ts_buf *buf = &node->bufs[0];\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ + in, n_in, buf);\ + if (rc == GRN_SUCCESS) {\ + grn_ts_bool *buf_ptr = (grn_ts_bool *)buf->ptr;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = grn_ts_op_ ## type ## _bool(out_ptr[i], buf_ptr[i]);\ + }\ + }\ + }\ + return rc;\ + }\ + for (i = 0; i < 2; i++) {\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ + &node->bufs[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + switch (node->args[0]->data_kind) {\ + GRN_TS_OP_CHK_EVALUATE_CASE(type, INT, int)\ + GRN_TS_OP_CHK_EVALUATE_CASE(type, FLOAT, float)\ + GRN_TS_OP_CHK_EVALUATE_CASE(type, TIME, time)\ + GRN_TS_OP_CHK_EVALUATE_CASE(type, TEXT, text)\ + GRN_TS_OP_CHK_EVALUATE_CASE(type, GEO, geo)\ + GRN_TS_OP_CHK_EVALUATE_CASE(type, REF, ref)\ + GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, BOOL, bool)\ + GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, INT, int)\ + GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, FLOAT, float)\ + GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, TIME, time)\ + GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, TEXT, text)\ + GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, GEO, geo)\ + GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE(type, REF, ref)\ + default: {\ + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ + node->args[0]->data_kind);\ + }\ + } +/* grn_ts_op_equal_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + GRN_TS_OP_CHK_EVALUATE(equal) +} + +/* grn_ts_op_not_equal_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_not_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + GRN_TS_OP_CHK_EVALUATE(not_equal) +} +#undef GRN_TS_OP_CHK_EVALUATE +#undef GRN_TS_OP_CHK_EVALUATE_VECTOR_CASE +#undef GRN_TS_OP_CHK_EVALUATE_CASE + +#define GRN_TS_OP_CMP_EVALUATE_CASE(type, KIND, kind)\ + case GRN_TS_ ## KIND: {\ + grn_ts_ ## kind *buf_ptrs[] = {\ + (grn_ts_ ## kind *)node->bufs[0].ptr,\ + (grn_ts_ ## kind *)node->bufs[1].ptr\ + };\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i],\ + buf_ptrs[1][i]);\ + }\ + return GRN_SUCCESS;\ + } +#define GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, KIND, kind)\ + GRN_TS_OP_CMP_EVALUATE_CASE(type, KIND ## _VECTOR, kind ## _vector) +#define GRN_TS_OP_CMP_EVALUATE(type)\ + size_t i;\ + grn_rc rc;\ + grn_ts_bool *out_ptr = (grn_ts_bool *)out;\ + for (i = 0; i < 2; i++) {\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ + &node->bufs[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + switch (node->args[0]->data_kind) {\ + GRN_TS_OP_CMP_EVALUATE_CASE(type, INT, int)\ + GRN_TS_OP_CMP_EVALUATE_CASE(type, FLOAT, float)\ + GRN_TS_OP_CMP_EVALUATE_CASE(type, TIME, time)\ + GRN_TS_OP_CMP_EVALUATE_CASE(type, TEXT, text)\ + GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, INT, int)\ + GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, FLOAT, float)\ + GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, TIME, time)\ + GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE(type, TEXT, text)\ + default: {\ + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ + node->args[0]->data_kind);\ + }\ + } +/* grn_ts_op_less_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_less_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + GRN_TS_OP_CMP_EVALUATE(less) +} + +/* grn_ts_op_less_equal_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_less_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + GRN_TS_OP_CMP_EVALUATE(less_equal) +} + +/* grn_ts_op_greater_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_greater_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + GRN_TS_OP_CMP_EVALUATE(greater) +} + +/* grn_ts_op_greater_equal_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_greater_equal_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + GRN_TS_OP_CMP_EVALUATE(greater_equal) +} +#undef GRN_TS_OP_CMP_EVALUATE +#undef GRN_TS_OP_CMP_EVALUATE_VECTOR_CASE +#undef GRN_TS_OP_CMP_EVALUATE_CASE + +#define GRN_TS_OP_SHIFT_EVALUATE(type)\ + size_t i;\ + grn_rc rc;\ + grn_ts_int *out_ptr = (grn_ts_int *)out;\ + rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ + if (rc == GRN_SUCCESS) {\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ + in, n_in, &node->bufs[0]);\ + if (rc == GRN_SUCCESS) {\ + grn_ts_int *buf_ptr = (grn_ts_int *)node->bufs[0].ptr;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = grn_ts_op_shift_ ## type(out_ptr[i], buf_ptr[i]);\ + }\ + }\ + }\ + return rc; +/* grn_ts_op_shift_arithmetic_left_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_shift_arithmetic_left_evaluate(grn_ctx *ctx, + grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + GRN_TS_OP_SHIFT_EVALUATE(arithmetic_left) +} + +/* grn_ts_op_shift_arithmetic_right_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_shift_arithmetic_right_evaluate(grn_ctx *ctx, + grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + GRN_TS_OP_SHIFT_EVALUATE(arithmetic_right) +} + +/* grn_ts_op_shift_logical_left_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_shift_logical_left_evaluate(grn_ctx *ctx, + grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + GRN_TS_OP_SHIFT_EVALUATE(logical_left) +} + +/* grn_ts_op_shift_logical_right_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_shift_logical_right_evaluate(grn_ctx *ctx, + grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + GRN_TS_OP_SHIFT_EVALUATE(logical_right) +} +#undef GRN_TS_OP_SHIFT_EVALUATE + +#define GRN_TS_OP_ARITH_EVALUATE(type, lhs_kind, rhs_kind)\ + /* + * Use the output buffer to put evaluation results of the 1st argument, + * because the data kind is same. + */\ + size_t i;\ + grn_rc rc;\ + grn_ts_ ## lhs_kind *out_ptr = (grn_ts_ ## lhs_kind *)out;\ + rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ + if (rc == GRN_SUCCESS) {\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ + in, n_in, &node->bufs[0]);\ + if (rc == GRN_SUCCESS) {\ + grn_ts_ ## rhs_kind *buf_ptr = (grn_ts_ ## rhs_kind *)node->bufs[0].ptr;\ + for (i = 0; i < n_in; i++) {\ + rc = grn_ts_op_ ## type ## _ ## lhs_kind ## _ ## rhs_kind(\ + ctx, out_ptr[i], buf_ptr[i], &out_ptr[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + }\ + }\ + return rc; + +#define GRN_TS_OP_ARITH_EVALUATE_CASE(type, KIND, kind)\ + case GRN_TS_ ## KIND: {\ + /* + * Use the output buffer to put evaluation results of the 1st argument, + * because the data kind is same. + */\ + size_t i;\ + grn_rc rc;\ + grn_ts_ ## kind *out_ptr = (grn_ts_ ## kind *)out;\ + rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ + if (rc == GRN_SUCCESS) {\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ + in, n_in, &node->bufs[0]);\ + if (rc == GRN_SUCCESS) {\ + grn_ts_ ## kind *buf_ptr = (grn_ts_ ## kind *)node->bufs[0].ptr;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = grn_ts_op_ ## type ## _ ## kind(out_ptr[i],\ + buf_ptr[i]);\ + }\ + }\ + }\ + return rc;\ + } +#define GRN_TS_OP_ARITH_EVALUATE_TIME_CASE(type, KIND, lhs, rhs)\ + case GRN_TS_ ## KIND: {\ + /* + * Use the output buffer to put evaluation results of the 1st argument, + * because the data kind is same. + */\ + size_t i;\ + grn_rc rc;\ + grn_ts_ ## lhs *out_ptr = (grn_ts_ ## lhs *)out;\ + rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, out);\ + if (rc == GRN_SUCCESS) {\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1],\ + in, n_in, &node->bufs[0]);\ + if (rc == GRN_SUCCESS) {\ + grn_ts_ ## rhs *buf_ptr = (grn_ts_ ## rhs *)node->bufs[0].ptr;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = grn_ts_op_ ## type ## _ ## lhs ## _ ## rhs(out_ptr[i],\ + buf_ptr[i]);\ + }\ + }\ + }\ + return rc;\ + } +/* grn_ts_op_plus_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_plus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + switch (node->args[0]->data_kind) { + case GRN_TS_INT: { + GRN_TS_OP_ARITH_EVALUATE(plus, int, int) + } + case GRN_TS_FLOAT: { + GRN_TS_OP_ARITH_EVALUATE(plus, float, float) + } + case GRN_TS_TIME: { + switch (node->args[1]->data_kind) { + case GRN_TS_INT: { + GRN_TS_OP_ARITH_EVALUATE(plus, time, int) + } + case GRN_TS_FLOAT: { + GRN_TS_OP_ARITH_EVALUATE(plus, time, float) + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "data kind conflict: %d, %d", + node->args[0]->data_kind, + node->args[1]->data_kind); + } + } + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } +} + +/* grn_ts_op_minus_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_minus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + switch (node->args[0]->data_kind) { + case GRN_TS_INT: { + GRN_TS_OP_ARITH_EVALUATE(minus, int, int) + } + case GRN_TS_FLOAT: { + GRN_TS_OP_ARITH_EVALUATE(minus, float, float) + } + case GRN_TS_TIME: { + switch (node->args[1]->data_kind) { + case GRN_TS_INT: { + GRN_TS_OP_ARITH_EVALUATE(minus, time, int) + } + case GRN_TS_FLOAT: { + GRN_TS_OP_ARITH_EVALUATE(minus, time, float) + } + case GRN_TS_TIME: { + size_t i; + grn_rc rc; + grn_ts_float *out_ptr = (grn_ts_float *)out; + grn_ts_time *buf_ptrs[2]; + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], in, n_in, + &node->bufs[1]); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptrs[0] = (grn_ts_time *)node->bufs[0].ptr; + buf_ptrs[1] = (grn_ts_time *)node->bufs[1].ptr; + for (i = 0; i < n_in; i++) { + rc = grn_ts_op_minus_time_time(ctx, buf_ptrs[0][i], buf_ptrs[1][i], + &out_ptr[i]); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "data kind conflict: %d, %d", + node->args[0]->data_kind, + node->args[1]->data_kind); + } + } + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->args[0]->data_kind); + } + } +} +#undef GRN_TS_OP_ARITH_EVALUATE_TIME_CASE + +/* grn_ts_op_multiplication_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_multiplication_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + switch (node->data_kind) { + case GRN_TS_INT: { + GRN_TS_OP_ARITH_EVALUATE(multiplication, int, int) + } + case GRN_TS_FLOAT: { + GRN_TS_OP_ARITH_EVALUATE(multiplication, float, float) + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} + +/* grn_ts_op_division_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_division_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + switch (node->data_kind) { + case GRN_TS_INT: { + GRN_TS_OP_ARITH_EVALUATE(division, int, int) + } + case GRN_TS_FLOAT: { + GRN_TS_OP_ARITH_EVALUATE(division, float, float) + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} + +/* grn_ts_op_modulus_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_modulus_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + switch (node->data_kind) { + case GRN_TS_INT: { + GRN_TS_OP_ARITH_EVALUATE(modulus, int, int) + } + case GRN_TS_FLOAT: { + GRN_TS_OP_ARITH_EVALUATE(modulus, float, float) + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d", + node->data_kind); + } + } +} +#undef GRN_TS_OP_ARITH_EVALUATE_CASE + +#define GRN_TS_OP_MATCH_EVALUATE(type)\ + size_t i;\ + grn_rc rc;\ + grn_ts_bool *out_ptr = (grn_ts_bool *)out;\ + grn_ts_text *buf_ptrs[2];\ + for (i = 0; i < 2; i++) {\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ + &node->bufs[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + buf_ptrs[0] = (grn_ts_text *)node->bufs[0].ptr;\ + buf_ptrs[1] = (grn_ts_text *)node->bufs[1].ptr;\ + for (i = 0; i < n_in; i++) {\ + out_ptr[i] = grn_ts_op_ ## type(buf_ptrs[0][i], buf_ptrs[1][i]);\ + }\ + return GRN_SUCCESS;\ +/* grn_ts_op_match_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_match_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + GRN_TS_OP_MATCH_EVALUATE(match) +} + +/* grn_ts_op_prefix_match_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_prefix_match_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + GRN_TS_OP_MATCH_EVALUATE(prefix_match) +} + +/* grn_ts_op_suffix_match_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_op_suffix_match_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + GRN_TS_OP_MATCH_EVALUATE(suffix_match) +} +#undef GRN_TS_OP_MATCH_EVALUATE + +/* grn_ts_expr_op_node_evaluate() evaluates an operator. */ +static grn_rc +grn_ts_expr_op_node_evaluate(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + switch (node->op_type) { + case GRN_TS_OP_LOGICAL_NOT: { + return grn_ts_op_logical_not_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_BITWISE_NOT: { + return grn_ts_op_bitwise_not_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_POSITIVE: { + return grn_ts_op_positive_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_NEGATIVE: { + return grn_ts_op_negative_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_FLOAT: { + return grn_ts_op_float_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_TIME: { + return grn_ts_op_time_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_LOGICAL_AND: { + return grn_ts_op_logical_and_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_LOGICAL_OR: { + return grn_ts_op_logical_or_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_LOGICAL_SUB: { + return grn_ts_op_logical_sub_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_BITWISE_AND: { + return grn_ts_op_bitwise_and_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_BITWISE_OR: { + return grn_ts_op_bitwise_or_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_BITWISE_XOR: { + return grn_ts_op_bitwise_xor_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_EQUAL: { + return grn_ts_op_equal_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_NOT_EQUAL: { + return grn_ts_op_not_equal_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_LESS: { + return grn_ts_op_less_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_LESS_EQUAL: { + return grn_ts_op_less_equal_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_GREATER: { + return grn_ts_op_greater_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_GREATER_EQUAL: { + return grn_ts_op_greater_equal_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: { + return grn_ts_op_shift_arithmetic_left_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: { + return grn_ts_op_shift_arithmetic_right_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_SHIFT_LOGICAL_LEFT: { + return grn_ts_op_shift_logical_left_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { + return grn_ts_op_shift_logical_right_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_PLUS: { + return grn_ts_op_plus_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_MINUS: { + return grn_ts_op_minus_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_MULTIPLICATION: { + return grn_ts_op_multiplication_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_DIVISION: { + return grn_ts_op_division_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_MODULUS: { + return grn_ts_op_modulus_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_MATCH: { + return grn_ts_op_match_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_PREFIX_MATCH: { + return grn_ts_op_prefix_match_evaluate(ctx, node, in, n_in, out); + } + case GRN_TS_OP_SUFFIX_MATCH: { + return grn_ts_op_suffix_match_evaluate(ctx, node, in, n_in, out); + } + // TODO: Add operators. + default: { + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, + "operator not supported: %d", node->op_type); + } + } +} + +/* grn_ts_op_logical_not_filter() filters records. */ +static grn_rc +grn_ts_op_logical_not_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + size_t i, count; + grn_rc rc; + grn_ts_bool *buf_ptr; + rc = grn_ts_buf_reserve(ctx, &node->bufs[0], sizeof(grn_ts_bool) * n_in); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptr = (grn_ts_bool *)node->bufs[0].ptr; + rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, buf_ptr); + if (rc != GRN_SUCCESS) { + return rc; + } + for (i = 0, count = 0; i < n_in; i++) { + if (grn_ts_op_logical_not_bool(buf_ptr[i])) { + out[count++] = in[i]; + } + } + *n_out = count; + return GRN_SUCCESS; +} + +/* grn_ts_op_bitwise_not_filter() filters records. */ +static grn_rc +grn_ts_op_bitwise_not_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + size_t i, count; + grn_rc rc; + grn_ts_bool *buf_ptr; + rc = grn_ts_buf_reserve(ctx, &node->bufs[0], sizeof(grn_ts_bool) * n_in); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptr = (grn_ts_bool *)node->bufs[0].ptr; + rc = grn_ts_expr_node_evaluate(ctx, node->args[0], in, n_in, buf_ptr); + if (rc != GRN_SUCCESS) { + return rc; + } + for (i = 0, count = 0; i < n_in; i++) { + if (grn_ts_op_bitwise_not_bool(buf_ptr[i])) { + out[count++] = in[i]; + } + } + *n_out = count; + return GRN_SUCCESS; +} + +/* grn_ts_op_logical_and_filter() filters records. */ +static grn_rc +grn_ts_op_logical_and_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + grn_rc rc = grn_ts_expr_node_filter(ctx, node->args[0], in, n_in, + out, n_out); + if (rc != GRN_SUCCESS) { + return rc; + } + return grn_ts_expr_node_filter(ctx, node->args[1], out, *n_out, out, n_out); +} + +/* grn_ts_op_logical_or_filter() filters records. */ +static grn_rc +grn_ts_op_logical_or_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + size_t i, j, count; + grn_rc rc; + grn_ts_bool *buf_ptrs[2]; + grn_ts_buf *tmp_in_buf = &node->bufs[2]; + grn_ts_record *tmp_in; + + /* Evaluate the 1st argument. */ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], in, n_in, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptrs[0] = (grn_ts_bool *)node->bufs[0].ptr; + + /* Create a list of false records. */ + rc = grn_ts_buf_reserve(ctx, tmp_in_buf, sizeof(grn_ts_record) * n_in); + if (rc != GRN_SUCCESS) { + return rc; + } + tmp_in = (grn_ts_record *)tmp_in_buf->ptr; + count = 0; + for (i = 0; i < n_in; i++) { + if (!buf_ptrs[0][i]) { + tmp_in[count++] = in[i]; + } + } + + /* Evaluate the 2nd argument. */ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], tmp_in, count, + &node->bufs[1]); + buf_ptrs[1] = (grn_ts_bool *)node->bufs[1].ptr; + + /* Merge the results. */ + count = 0; + for (i = 0, j = 0; i < n_in; i++) { + if (buf_ptrs[0][i] || buf_ptrs[1][j++]) { + out[count++] = in[i]; + } + } + *n_out = count; + return GRN_SUCCESS; +} + +/* grn_ts_op_logical_sub_filter() filters records. */ +static grn_rc +grn_ts_op_logical_sub_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + size_t i, n, count; + grn_ts_bool *buf_ptr; + grn_rc rc = grn_ts_expr_node_filter(ctx, node->args[0], in, n_in, out, &n); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[1], out, n, + &node->bufs[0]); + buf_ptr = (grn_ts_bool *)node->bufs[0].ptr; + for (i = 0, count = 0; i < n; i++) { + if (grn_ts_op_logical_not_bool(buf_ptr[i])) { + out[count++] = out[i]; + } + } + *n_out = count; + return GRN_SUCCESS; +} + +#define GRN_TS_OP_BITWISE_FILTER(type)\ + size_t i, count = 0;\ + grn_ts_bool *buf_ptrs[2];\ + for (i = 0; i < 2; i++) {\ + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ + &node->bufs[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + buf_ptrs[i] = (grn_ts_bool *)node->bufs[i].ptr;\ + }\ + for (i = 0; i < n_in; i++) {\ + if (grn_ts_op_bitwise_ ## type ## _bool(buf_ptrs[0][i], buf_ptrs[1][i])) {\ + out[count++] = in[i];\ + }\ + }\ + *n_out = count;\ + return GRN_SUCCESS;\ +/* grn_ts_op_bitwise_and_filter() filters records. */ +static grn_rc +grn_ts_op_bitwise_and_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_BITWISE_FILTER(and); +} + +/* grn_ts_op_bitwise_or_filter() filters records. */ +static grn_rc +grn_ts_op_bitwise_or_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_BITWISE_FILTER(or); +} + +/* grn_ts_op_bitwise_xor_filter() filters records. */ +static grn_rc +grn_ts_op_bitwise_xor_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_BITWISE_FILTER(xor); +} +#undef GRN_TS_OP_BITWISE_FILTER_CASE + +#define GRN_TS_OP_CHK_FILTER_CASE(type, KIND, kind)\ + case GRN_TS_ ## KIND: {\ + grn_ts_ ## kind *buf_ptrs[] = {\ + (grn_ts_ ## kind *)node->bufs[0].ptr,\ + (grn_ts_ ## kind *)node->bufs[1].ptr\ + };\ + for (i = 0; i < n_in; i++) {\ + if (grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i], buf_ptrs[1][i])) {\ + out[count++] = in[i];\ + }\ + }\ + *n_out = count;\ + return GRN_SUCCESS;\ + } +#define GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, KIND, kind)\ + GRN_TS_OP_CHK_FILTER_CASE(type, KIND ## _VECTOR, kind ## _vector) +#define GRN_TS_OP_CHK_FILTER(type)\ + size_t i, count = 0;\ + for (i = 0; i < 2; i++) {\ + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ + &node->bufs[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + switch (node->args[0]->data_kind) {\ + GRN_TS_OP_CHK_FILTER_CASE(type, BOOL, bool)\ + GRN_TS_OP_CHK_FILTER_CASE(type, INT, int)\ + GRN_TS_OP_CHK_FILTER_CASE(type, FLOAT, float)\ + GRN_TS_OP_CHK_FILTER_CASE(type, TIME, time)\ + GRN_TS_OP_CHK_FILTER_CASE(type, TEXT, text)\ + GRN_TS_OP_CHK_FILTER_CASE(type, GEO, geo)\ + GRN_TS_OP_CHK_FILTER_CASE(type, REF, ref)\ + GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, BOOL, bool)\ + GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, INT, int)\ + GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, FLOAT, float)\ + GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, TIME, time)\ + GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, TEXT, text)\ + GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, GEO, geo)\ + GRN_TS_OP_CHK_FILTER_VECTOR_CASE(type, REF, ref)\ + default: {\ + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ + node->args[0]->data_kind);\ + }\ + } +/* grn_ts_op_equal_filter() filters records. */ +static grn_rc +grn_ts_op_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_CHK_FILTER(equal) +} + +/* grn_ts_op_not_equal_filter() filters records. */ +static grn_rc +grn_ts_op_not_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_CHK_FILTER(not_equal) +} +#undef GRN_TS_OP_CHK_FILTER +#undef GRN_TS_OP_CHK_FILTER_VECTOR_CASE +#undef GRN_TS_OP_CHK_FILTER_CASE + +#define GRN_TS_OP_CMP_FILTER_CASE(type, KIND, kind)\ + case GRN_TS_ ## KIND: {\ + grn_ts_ ## kind *buf_ptrs[] = {\ + (grn_ts_ ## kind *)node->bufs[0].ptr,\ + (grn_ts_ ## kind *)node->bufs[1].ptr\ + };\ + for (i = 0; i < n_in; i++) {\ + if (grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i], buf_ptrs[1][i])) {\ + out[count++] = in[i];\ + }\ + }\ + *n_out = count;\ + return GRN_SUCCESS;\ + } +#define GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, KIND, kind)\ + GRN_TS_OP_CMP_FILTER_CASE(type, KIND ## _VECTOR, kind ## _vector) +#define GRN_TS_OP_CMP_FILTER(type)\ + size_t i, count = 0;\ + for (i = 0; i < 2; i++) {\ + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ + &node->bufs[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + switch (node->args[0]->data_kind) {\ + GRN_TS_OP_CMP_FILTER_CASE(type, INT, int)\ + GRN_TS_OP_CMP_FILTER_CASE(type, FLOAT, float)\ + GRN_TS_OP_CMP_FILTER_CASE(type, TIME, time)\ + GRN_TS_OP_CMP_FILTER_CASE(type, TEXT, text)\ + GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, INT, int)\ + GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, FLOAT, float)\ + GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, TIME, time)\ + GRN_TS_OP_CMP_FILTER_VECTOR_CASE(type, TEXT, text)\ + default: {\ + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid data kind: %d",\ + node->args[0]->data_kind);\ + }\ + } +/* grn_ts_op_less_filter() filters records. */ +static grn_rc +grn_ts_op_less_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_CMP_FILTER(less) +} + +/* grn_ts_op_less_equal_filter() filters records. */ +static grn_rc +grn_ts_op_less_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_CMP_FILTER(less_equal) +} + +/* grn_ts_op_greater_filter() filters records. */ +static grn_rc +grn_ts_op_greater_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_CMP_FILTER(greater) +} + +/* grn_ts_op_greater_equal_filter() filters records. */ +static grn_rc +grn_ts_op_greater_equal_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_CMP_FILTER(greater_equal) +} +#undef GRN_TS_OP_CMP_FILTER +#undef GRN_TS_OP_CMP_FILTER_VECTOR_CASE +#undef GRN_TS_OP_CMP_FILTER_CASE + +#define GRN_TS_OP_MATCH_FILTER_CASE(type, KIND, kind)\ + case GRN_TS_ ## KIND: {\ + grn_ts_ ## kind *buf_ptrs[] = {\ + (grn_ts_ ## kind *)node->bufs[0].ptr,\ + (grn_ts_ ## kind *)node->bufs[1].ptr\ + };\ + for (i = 0; i < n_in; i++) {\ + if (grn_ts_op_ ## type ## _ ## kind(buf_ptrs[0][i], buf_ptrs[1][i])) {\ + out[count++] = in[i];\ + }\ + }\ + *n_out = count;\ + return GRN_SUCCESS;\ + } + +#define GRN_TS_OP_MATCH_FILTER(type)\ + size_t i, count = 0;\ + grn_ts_text *buf_ptrs[2];\ + for (i = 0; i < 2; i++) {\ + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], in, n_in,\ + &node->bufs[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + buf_ptrs[0] = (grn_ts_text *)node->bufs[0].ptr;\ + buf_ptrs[1] = (grn_ts_text *)node->bufs[1].ptr;\ + for (i = 0; i < n_in; i++) {\ + if (grn_ts_op_ ## type(buf_ptrs[0][i], buf_ptrs[1][i])) {\ + out[count++] = in[i];\ + }\ + }\ + *n_out = count;\ + return GRN_SUCCESS;\ +/* grn_ts_op_match_filter() filters records. */ +static grn_rc +grn_ts_op_match_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_MATCH_FILTER(match) +} + +/* grn_ts_op_prefix_match_filter() filters records. */ +static grn_rc +grn_ts_op_prefix_match_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_MATCH_FILTER(prefix_match) +} + +/* grn_ts_op_suffix_match_filter() filters records. */ +static grn_rc +grn_ts_op_suffix_match_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + GRN_TS_OP_MATCH_FILTER(suffix_match) +} +#undef GRN_TS_OP_MATCH_FILTER + +/* grn_ts_expr_op_node_filter() filters records. */ +static grn_rc +grn_ts_expr_op_node_filter(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + switch (node->op_type) { + case GRN_TS_OP_LOGICAL_NOT: { + return grn_ts_op_logical_not_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_BITWISE_NOT: { + return grn_ts_op_bitwise_not_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_LOGICAL_AND: { + return grn_ts_op_logical_and_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_LOGICAL_OR: { + return grn_ts_op_logical_or_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_LOGICAL_SUB: { + return grn_ts_op_logical_sub_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_BITWISE_AND: { + return grn_ts_op_bitwise_and_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_BITWISE_OR: { + return grn_ts_op_bitwise_or_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_BITWISE_XOR: { + return grn_ts_op_bitwise_xor_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_EQUAL: { + return grn_ts_op_equal_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_NOT_EQUAL: { + return grn_ts_op_not_equal_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_LESS: { + return grn_ts_op_less_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_LESS_EQUAL: { + return grn_ts_op_less_equal_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_GREATER: { + return grn_ts_op_greater_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_GREATER_EQUAL: { + return grn_ts_op_greater_equal_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_MATCH: { + return grn_ts_op_match_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_PREFIX_MATCH: { + return grn_ts_op_prefix_match_filter(ctx, node, in, n_in, out, n_out); + } + case GRN_TS_OP_SUFFIX_MATCH: { + return grn_ts_op_suffix_match_filter(ctx, node, in, n_in, out, n_out); + } + // TODO: Add operators. + default: { + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, + "operator not supported: %d", node->op_type); + } + } +} + +#define GRN_TS_OP_SIGN_ADJUST(type)\ + size_t i;\ + grn_ts_float *buf_ptr;\ + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], io, n_io,\ + &node->bufs[0]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + buf_ptr = (grn_ts_float *)node->bufs[0].ptr;\ + for (i = 0; i < n_io; i++) {\ + grn_ts_float result = grn_ts_op_ ## type ## _float(buf_ptr[i]);\ + io[i].score = (grn_ts_score)result;\ + if (!isfinite(io[i].score)) {\ + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid score: %g", result);\ + }\ + }\ + return GRN_SUCCESS; +/* grn_ts_op_positive_adjust() updates scores. */ +static grn_rc +grn_ts_op_positive_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *io, size_t n_io) +{ + GRN_TS_OP_SIGN_ADJUST(positive) +} + +/* grn_ts_op_negative_adjust() updates scores. */ +static grn_rc +grn_ts_op_negative_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *io, size_t n_io) +{ + GRN_TS_OP_SIGN_ADJUST(negative) +} +#undef GRN_TS_OP_SIGN_ADJUST + +/* grn_ts_op_float_adjust() updates scores. */ +static grn_rc +grn_ts_op_float_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *io, size_t n_io) +{ + size_t i; + grn_ts_int *buf_ptr; + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[0], io, n_io, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + buf_ptr = (grn_ts_int *)node->bufs[0].ptr; + for (i = 0; i < n_io; i++) { + grn_ts_float result; + rc = grn_ts_op_float(ctx, buf_ptr[i], &result); + io[i].score = (grn_ts_score)result; + if (!isfinite(io[i].score)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid score: %g", result); + } + } + return GRN_SUCCESS; +} + +#define GRN_TS_OP_ARITH_ADJUST(type)\ + grn_rc rc;\ + size_t i;\ + grn_ts_float *buf_ptrs[2];\ + for (i = 0; i < 2; i++) {\ + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->args[i], io, n_io,\ + &node->bufs[i]);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + }\ + buf_ptrs[0] = (grn_ts_float *)node->bufs[0].ptr;\ + buf_ptrs[1] = (grn_ts_float *)node->bufs[1].ptr;\ + for (i = 0; i < n_io; i++) {\ + grn_ts_float result;\ + rc = grn_ts_op_ ## type ## _float_float(ctx, buf_ptrs[0][i],\ + buf_ptrs[1][i], &result);\ + io[i].score = (grn_ts_score)result;\ + if (!isfinite(io[i].score)) {\ + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid score: %g", result);\ + }\ + }\ + return GRN_SUCCESS; +/* grn_ts_op_plus_adjust() updates scores. */ +static grn_rc +grn_ts_op_plus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *io, size_t n_io) +{ + GRN_TS_OP_ARITH_ADJUST(plus) +} + +/* grn_ts_op_minus_adjust() updates scores. */ +static grn_rc +grn_ts_op_minus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *io, size_t n_io) +{ + GRN_TS_OP_ARITH_ADJUST(minus) +} + +/* grn_ts_op_multiplication_adjust() updates scores. */ +static grn_rc +grn_ts_op_multiplication_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *io, size_t n_io) +{ + GRN_TS_OP_ARITH_ADJUST(multiplication) +} + +/* grn_ts_op_division_adjust() updates scores. */ +static grn_rc +grn_ts_op_division_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *io, size_t n_io) +{ + GRN_TS_OP_ARITH_ADJUST(division) +} + +/* grn_ts_op_modulus_adjust() updates scores. */ +static grn_rc +grn_ts_op_modulus_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *io, size_t n_io) +{ + GRN_TS_OP_ARITH_ADJUST(modulus) +} +#undef GRN_TS_OP_ARITH_ADJUST + +/* grn_ts_expr_op_node_adjust() updates scores. */ +static grn_rc +grn_ts_expr_op_node_adjust(grn_ctx *ctx, grn_ts_expr_op_node *node, + grn_ts_record *io, size_t n_io) +{ + switch (node->op_type) { + case GRN_TS_OP_POSITIVE: { + return grn_ts_op_positive_adjust(ctx, node, io, n_io); + } + case GRN_TS_OP_NEGATIVE: { + return grn_ts_op_negative_adjust(ctx, node, io, n_io); + } + case GRN_TS_OP_FLOAT: { + return grn_ts_op_float_adjust(ctx, node, io, n_io); + } + case GRN_TS_OP_PLUS: { + return grn_ts_op_plus_adjust(ctx, node, io, n_io); + } + case GRN_TS_OP_MINUS: { + return grn_ts_op_minus_adjust(ctx, node, io, n_io); + } + case GRN_TS_OP_MULTIPLICATION: { + return grn_ts_op_multiplication_adjust(ctx, node, io, n_io); + } + case GRN_TS_OP_DIVISION: { + return grn_ts_op_division_adjust(ctx, node, io, n_io); + } + case GRN_TS_OP_MODULUS: { + return grn_ts_op_modulus_adjust(ctx, node, io, n_io); + } + // TODO: Add operators. + default: { + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, + "operator not supported: %d", node->op_type); + } + } +} + +/*------------------------------------------------------------- + * grn_ts_expr_bridge_node. + */ + +enum { GRN_TS_EXPR_BRIDGE_NODE_N_BUFS = 2 }; + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS + grn_ts_expr_node *src; + grn_ts_expr_node *dest; + grn_ts_buf bufs[GRN_TS_EXPR_BRIDGE_NODE_N_BUFS]; +} grn_ts_expr_bridge_node; + +/* grn_ts_expr_bridge_node_init() initializes a node. */ +static void +grn_ts_expr_bridge_node_init(grn_ctx *ctx, grn_ts_expr_bridge_node *node) +{ + size_t i; + memset(node, 0, sizeof(*node)); + node->type = GRN_TS_EXPR_BRIDGE_NODE; + node->src = NULL; + node->dest = NULL; + for (i = 0; i < GRN_TS_EXPR_BRIDGE_NODE_N_BUFS; i++) { + grn_ts_buf_init(ctx, &node->bufs[i]); + } +} + +/* grn_ts_expr_bridge_node_fin() finalizes a node. */ +static void +grn_ts_expr_bridge_node_fin(grn_ctx *ctx, grn_ts_expr_bridge_node *node) +{ + size_t i; + for (i = 0; i < GRN_TS_EXPR_BRIDGE_NODE_N_BUFS; i++) { + grn_ts_buf_fin(ctx, &node->bufs[i]); + } + if (node->dest) { + grn_ts_expr_node_close(ctx, node->dest); + } + if (node->src) { + grn_ts_expr_node_close(ctx, node->src); + } +} + +grn_rc +grn_ts_expr_bridge_node_open(grn_ctx *ctx, grn_ts_expr_node *src, + grn_ts_expr_node *dest, grn_ts_expr_node **node) +{ + grn_ts_expr_bridge_node *new_node = GRN_MALLOCN(grn_ts_expr_bridge_node, 1); + if (!new_node) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_expr_bridge_node)); + } + grn_ts_expr_bridge_node_init(ctx, new_node); + new_node->data_kind = dest->data_kind; + new_node->data_type = dest->data_type; + new_node->src = src; + new_node->dest = dest; + *node = (grn_ts_expr_node *)new_node; + return GRN_SUCCESS; +} + +/* grn_ts_expr_bridge_node_close() destroys a node. */ +static void +grn_ts_expr_bridge_node_close(grn_ctx *ctx, grn_ts_expr_bridge_node *node) +{ + grn_ts_expr_bridge_node_fin(ctx, node); + GRN_FREE(node); +} + +/* grn_ts_expr_bridge_node_evaluate() evaluates a bridge. */ +static grn_rc +grn_ts_expr_bridge_node_evaluate(grn_ctx *ctx, grn_ts_expr_bridge_node *node, + const grn_ts_record *in, size_t n_in, + void *out) +{ + grn_ts_record *tmp; + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, in, n_in, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + tmp = (grn_ts_record *)node->bufs[0].ptr; + return grn_ts_expr_node_evaluate(ctx, node->dest, tmp, n_in, out); +} + +/* grn_ts_expr_bridge_node_filter() filters records. */ +static grn_rc +grn_ts_expr_bridge_node_filter(grn_ctx *ctx, grn_ts_expr_bridge_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + size_t i, count; + grn_ts_bool *values; + grn_ts_record *tmp; + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, in, n_in, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + tmp = (grn_ts_record *)node->bufs[0].ptr; + rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->dest, in, n_in, + &node->bufs[1]); + if (rc != GRN_SUCCESS) { + return rc; + } + values = (grn_ts_bool *)&node->bufs[1].ptr; + for (i = 0, count = 0; i < n_in; i++) { + if (values[i]) { + out[count++] = in[i]; + } + } + *n_out = count; + return GRN_SUCCESS; +} + +/* grn_ts_expr_bridge_node_adjust() updates scores. */ +static grn_rc +grn_ts_expr_bridge_node_adjust(grn_ctx *ctx, grn_ts_expr_bridge_node *node, + grn_ts_record *io, size_t n_io) +{ + size_t i; + grn_ts_record *tmp; + grn_rc rc = grn_ts_expr_node_evaluate_to_buf(ctx, node->src, io, n_io, + &node->bufs[0]); + if (rc != GRN_SUCCESS) { + return rc; + } + tmp = (grn_ts_record *)node->bufs[0].ptr; + rc = grn_ts_expr_node_adjust(ctx, node->dest, tmp, n_io); + if (rc != GRN_SUCCESS) { + return rc; + } + for (i = 0; i < n_io; i++) { + io[i].score = tmp[i].score; + } + return GRN_SUCCESS; +} + +/*------------------------------------------------------------- + * grn_ts_expr_node. + */ + +#define GRN_TS_EXPR_NODE_CLOSE_CASE(TYPE, type)\ + case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ + grn_ts_expr_ ## type ## _node *type ## _node;\ + type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ + grn_ts_expr_ ## type ## _node_close(ctx, type ## _node);\ + return;\ + } +void +grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node) +{ + switch (node->type) { + GRN_TS_EXPR_NODE_CLOSE_CASE(ID, id) + GRN_TS_EXPR_NODE_CLOSE_CASE(SCORE, score) + GRN_TS_EXPR_NODE_CLOSE_CASE(KEY, key) + GRN_TS_EXPR_NODE_CLOSE_CASE(VALUE, value) + GRN_TS_EXPR_NODE_CLOSE_CASE(CONST, const) + GRN_TS_EXPR_NODE_CLOSE_CASE(COLUMN, column) + GRN_TS_EXPR_NODE_CLOSE_CASE(OP, op) + GRN_TS_EXPR_NODE_CLOSE_CASE(BRIDGE, bridge) + } +} +#undef GRN_TS_EXPR_NODE_CLOSE_CASE + +/* grn_ts_expr_node_deref_once() resolves a reference. */ +static grn_rc +grn_ts_expr_node_deref_once(grn_ctx *ctx, grn_ts_expr_node *in, + grn_ts_expr_node **out) +{ + grn_rc rc; + grn_id table_id = in->data_type; + grn_ts_expr_node *key_node, *bridge_node; + grn_obj *table = grn_ctx_at(ctx, table_id); + if (!table) { + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", table_id); + } + if (!grn_ts_obj_is_table(ctx, table)) { + grn_obj_unlink(ctx, table); + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "not table: %d", table_id); + } + rc = grn_ts_expr_key_node_open(ctx, table, &key_node); + grn_obj_unlink(ctx, table); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_bridge_node_open(ctx, in, key_node, &bridge_node); + if (rc != GRN_SUCCESS) { + grn_ts_expr_node_close(ctx, key_node); + return rc; + } + *out = bridge_node; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_node_deref(grn_ctx *ctx, grn_ts_expr_node **node_ptr) +{ + grn_ts_expr_node *node = *node_ptr, **in_ptr = NULL; + while ((node->data_kind & ~GRN_TS_VECTOR_FLAG) == GRN_TS_REF) { + grn_ts_expr_node *new_node= 0; + grn_rc rc = grn_ts_expr_node_deref_once(ctx, node, &new_node); + if (rc != GRN_SUCCESS) { + if (in_ptr) { + *in_ptr = NULL; + grn_ts_expr_node_close(ctx, node); + } + return rc; + } + if (node == *node_ptr) { + grn_ts_expr_bridge_node *bridge_node; + bridge_node = (grn_ts_expr_bridge_node *)new_node; + if (bridge_node->src != node) { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "broken bridge node"); + } + in_ptr = &bridge_node->src; + } + node = new_node; + } + *node_ptr = node; + return GRN_SUCCESS; +} + +#define GRN_TS_EXPR_NODE_EVALUATE_CASE(TYPE, type)\ + case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ + grn_ts_expr_ ## type ## _node *type ## _node;\ + type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ + return grn_ts_expr_ ## type ## _node_evaluate(ctx, type ## _node,\ + in, n_in, out);\ + } +grn_rc +grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, + const grn_ts_record *in, size_t n_in, void *out) +{ + switch (node->type) { + GRN_TS_EXPR_NODE_EVALUATE_CASE(ID, id) + GRN_TS_EXPR_NODE_EVALUATE_CASE(SCORE, score) + GRN_TS_EXPR_NODE_EVALUATE_CASE(KEY, key) + GRN_TS_EXPR_NODE_EVALUATE_CASE(VALUE, value) + GRN_TS_EXPR_NODE_EVALUATE_CASE(CONST, const) + GRN_TS_EXPR_NODE_EVALUATE_CASE(COLUMN, column) + GRN_TS_EXPR_NODE_EVALUATE_CASE(OP, op) + GRN_TS_EXPR_NODE_EVALUATE_CASE(BRIDGE, bridge) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, + "invalid node type: %d", node->type); + } + } +} +#undef GRN_TS_EXPR_NODE_EVALUATE_CASE + +#define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND, kind)\ + case GRN_TS_ ## KIND: {\ + grn_rc rc = grn_ts_buf_reserve(ctx, out, sizeof(grn_ts_ ## kind) * n_in);\ + if (rc != GRN_SUCCESS) {\ + return rc;\ + }\ + return grn_ts_expr_node_evaluate(ctx, node, in, n_in, out->ptr);\ + } +#define GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(KIND, kind)\ + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(KIND ## _VECTOR, kind ## _vector) +grn_rc +grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_buf *out) +{ + switch (node->data_kind) { + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(BOOL, bool) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(INT, int) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(FLOAT, float) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(TIME, time) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(TEXT, text) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(GEO, geo) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE(REF, ref) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(BOOL, bool) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(INT, int) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(FLOAT, float) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(TIME, time) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(TEXT, text) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(GEO, geo) + GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE(REF, ref) + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, + "invalid data kind: %d", node->data_kind); + } + } +} +#undef GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_VECTOR_CASE +#undef GRN_TS_EXPR_NODE_EVALUATE_TO_BUF_CASE + +#define GRN_TS_EXPR_NODE_FILTER_CASE(TYPE, type)\ + case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ + grn_ts_expr_ ## type ## _node *type ## _node;\ + type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ + return grn_ts_expr_ ## type ## _node_filter(ctx, type ## _node,\ + in, n_in, out, n_out);\ + } +grn_rc +grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out) +{ + if (node->data_kind != GRN_TS_BOOL) { + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, + "invalid data kind: %d", node->data_kind); + } + switch (node->type) { + GRN_TS_EXPR_NODE_FILTER_CASE(KEY, key) + GRN_TS_EXPR_NODE_FILTER_CASE(VALUE, value) + GRN_TS_EXPR_NODE_FILTER_CASE(CONST, const) + GRN_TS_EXPR_NODE_FILTER_CASE(COLUMN, column) + GRN_TS_EXPR_NODE_FILTER_CASE(OP, op) + GRN_TS_EXPR_NODE_FILTER_CASE(BRIDGE, bridge) + default: { + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, + "invalid node type: %d", node->type); + } + } +} +#undef GRN_TS_EXPR_NODE_FILTER_CASE + +#define GRN_TS_EXPR_NODE_ADJUST_CASE(TYPE, type)\ + case GRN_TS_EXPR_ ## TYPE ## _NODE: {\ + grn_ts_expr_ ## type ## _node *type ## _node;\ + type ## _node = (grn_ts_expr_ ## type ## _node *)node;\ + return grn_ts_expr_ ## type ## _node_adjust(ctx, type ## _node, io, n_io);\ + } +grn_rc +grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, + grn_ts_record *io, size_t n_io) +{ + if (node->data_kind != GRN_TS_FLOAT) { + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, + "invalid data kind: %d", node->data_kind); + } + switch (node->type) { + GRN_TS_EXPR_NODE_ADJUST_CASE(SCORE, score) + GRN_TS_EXPR_NODE_ADJUST_CASE(KEY, key) + GRN_TS_EXPR_NODE_ADJUST_CASE(VALUE, value) + GRN_TS_EXPR_NODE_ADJUST_CASE(CONST, const) + GRN_TS_EXPR_NODE_ADJUST_CASE(COLUMN, column) + GRN_TS_EXPR_NODE_ADJUST_CASE(OP, op) + GRN_TS_EXPR_NODE_ADJUST_CASE(BRIDGE, bridge) + default: { + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, + "invalid node type: %d", node->type); + } + } +} +#undef GRN_TS_EXPR_NODE_ADJUST_CASE diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.h b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.h new file mode 100644 index 00000000..bcc9f371 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_node.h @@ -0,0 +1,128 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#include "ts_buf.h" +#include "ts_op.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + GRN_TS_EXPR_ID_NODE, /* ID (_id). */ + GRN_TS_EXPR_SCORE_NODE, /* Score (_score). */ + GRN_TS_EXPR_KEY_NODE, /* Key (_key). */ + GRN_TS_EXPR_VALUE_NODE, /* Embedded value (_value). */ + GRN_TS_EXPR_CONST_NODE, /* Const. */ + GRN_TS_EXPR_COLUMN_NODE, /* Column. */ + GRN_TS_EXPR_OP_NODE, /* Operator. */ + GRN_TS_EXPR_BRIDGE_NODE /* Bridge to a subexpression. */ +} grn_ts_expr_node_type; + +#define GRN_TS_EXPR_NODE_COMMON_MEMBERS\ + grn_ts_expr_node_type type; /* Node type. */\ + grn_ts_data_kind data_kind; /* Abstract data type. */\ + grn_ts_data_type data_type; /* Detailed data type. */ + +typedef struct { + GRN_TS_EXPR_NODE_COMMON_MEMBERS +} grn_ts_expr_node; + +/* grn_ts_expr_id_node_open() creates a node associated with IDs (_id). */ +grn_rc grn_ts_expr_id_node_open(grn_ctx *ctx, grn_ts_expr_node **node); + +/* + * grn_ts_expr_score_node_open() creates a node associated with scores + * (_score). + */ +grn_rc grn_ts_expr_score_node_open(grn_ctx *ctx, grn_ts_expr_node **node); + +/* grn_ts_expr_key_node_open() creates a node associated with keys (_key). */ +grn_rc grn_ts_expr_key_node_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_node **node); + +/* + * grn_ts_expr_value_node_open() creates a node associated with values + * (_value). + */ +grn_rc grn_ts_expr_value_node_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_node **node); + +/* grn_ts_expr_const_node_open() creates a node associated with a const. */ +grn_rc grn_ts_expr_const_node_open(grn_ctx *ctx, grn_ts_data_kind data_kind, + grn_ts_data_type data_type, + grn_ts_any value, grn_ts_expr_node **node); + +/* grn_ts_expr_column_node_open() creates a node associated with a column. */ +grn_rc grn_ts_expr_column_node_open(grn_ctx *ctx, grn_obj *column, + grn_ts_expr_node **node); + +/* + * grn_ts_expr_op_node_open() creates a node associated with an operator. + * Note that argument nodes are destroyed on failure. + */ +grn_rc grn_ts_expr_op_node_open(grn_ctx *ctx, grn_ts_op_type op_type, + grn_ts_expr_node **args, size_t n_args, + grn_ts_expr_node **node); + +/* grn_ts_expr_bridge_node_open() creates a node associated with a bridge. */ +grn_rc grn_ts_expr_bridge_node_open(grn_ctx *ctx, grn_ts_expr_node *src, + grn_ts_expr_node *dest, + grn_ts_expr_node **node); + +/* grn_ts_expr_node_close() destroys a node. */ +void grn_ts_expr_node_close(grn_ctx *ctx, grn_ts_expr_node *node); + +/* + * grn_ts_expr_node_deref() resolves references. + * + * If *node_ptr refers to a reference node, grn_ts_expr_node_deref() creates a + * key node associated with the destination table and creates a bridge node + * from *node_ptr to the key node. If the data kind of the bridge node is + * GRN_TS_REF, references are recursively resolved. + */ +grn_rc grn_ts_expr_node_deref(grn_ctx *ctx, grn_ts_expr_node **node_ptr); + +/* grn_ts_expr_node_evaluate() evaluates a subtree. */ +grn_rc grn_ts_expr_node_evaluate(grn_ctx *ctx, grn_ts_expr_node *node, + const grn_ts_record *in, size_t n_in, + void *out); + +/* grn_ts_expr_node_evaluate_to_buf() evaluates a subtree. */ +grn_rc grn_ts_expr_node_evaluate_to_buf(grn_ctx *ctx, grn_ts_expr_node *node, + const grn_ts_record *in, size_t n_in, + grn_ts_buf *out); + +/* grn_ts_expr_node_filter() filters records. */ +grn_rc grn_ts_expr_node_filter(grn_ctx *ctx, grn_ts_expr_node *node, + grn_ts_record *in, size_t n_in, + grn_ts_record *out, size_t *n_out); + +/* grn_ts_expr_node_adjust() updates scores. */ +grn_rc grn_ts_expr_node_adjust(grn_ctx *ctx, grn_ts_expr_node *node, + grn_ts_record *io, size_t n_io); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_expr_parser.c b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_parser.c new file mode 100644 index 00000000..10e6d2fc --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_parser.c @@ -0,0 +1,1329 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_expr_parser.h" + +#include +#include + +#include "../grn_ctx.h" + +#include "ts_log.h" +#include "ts_str.h" +#include "ts_util.h" + +/*------------------------------------------------------------- + * grn_ts_expr_token. + */ + +#define GRN_TS_EXPR_TOKEN_INIT(TYPE)\ + memset(token, 0, sizeof(*token));\ + token->type = GRN_TS_EXPR_ ## TYPE ## _TOKEN;\ + token->src = src; +/* grn_ts_expr_dummy_token_init() initializes a token. */ +static void +grn_ts_expr_dummy_token_init(grn_ctx *ctx, grn_ts_expr_dummy_token *token, + grn_ts_str src) +{ + GRN_TS_EXPR_TOKEN_INIT(DUMMY) +} + +/* grn_ts_expr_start_token_init() initializes a token. */ +static void +grn_ts_expr_start_token_init(grn_ctx *ctx, grn_ts_expr_start_token *token, + grn_ts_str src) +{ + GRN_TS_EXPR_TOKEN_INIT(START) +} + +/* grn_ts_expr_end_token_init() initializes a token. */ +static void +grn_ts_expr_end_token_init(grn_ctx *ctx, grn_ts_expr_end_token *token, + grn_ts_str src) +{ + GRN_TS_EXPR_TOKEN_INIT(END) +} + +/* grn_ts_expr_const_token_init() initializes a token. */ +static void +grn_ts_expr_const_token_init(grn_ctx *ctx, grn_ts_expr_const_token *token, + grn_ts_str src) +{ + GRN_TS_EXPR_TOKEN_INIT(CONST); + grn_ts_buf_init(ctx, &token->buf); +} + +/* grn_ts_expr_name_token_init() initializes a token. */ +static void +grn_ts_expr_name_token_init(grn_ctx *ctx, grn_ts_expr_name_token *token, + grn_ts_str src) +{ + GRN_TS_EXPR_TOKEN_INIT(NAME); +} + +/* grn_ts_expr_op_token_init() initializes a token. */ +static void +grn_ts_expr_op_token_init(grn_ctx *ctx, grn_ts_expr_op_token *token, + grn_ts_str src) +{ + GRN_TS_EXPR_TOKEN_INIT(OP); +} + +/* grn_ts_expr_bridge_token_init() initializes a token. */ +static void +grn_ts_expr_bridge_token_init(grn_ctx *ctx, grn_ts_expr_bridge_token *token, + grn_ts_str src) +{ + GRN_TS_EXPR_TOKEN_INIT(BRIDGE) +} + +/* grn_ts_expr_bracket_token_init() initializes a token. */ +static void +grn_ts_expr_bracket_token_init(grn_ctx *ctx, grn_ts_expr_bracket_token *token, + grn_ts_str src) +{ + GRN_TS_EXPR_TOKEN_INIT(BRACKET) +} +#undef GRN_TS_EXPR_TOKEN_INIT + +/* grn_ts_expr_dummy_token_fin() finalizes a token. */ +static void +grn_ts_expr_dummy_token_fin(grn_ctx *ctx, grn_ts_expr_dummy_token *token) +{ + /* Nothing to do. */ +} + +/* grn_ts_expr_start_token_fin() finalizes a token. */ +static void +grn_ts_expr_start_token_fin(grn_ctx *ctx, grn_ts_expr_start_token *token) +{ + /* Nothing to do. */ +} + +/* grn_ts_expr_end_token_fin() finalizes a token. */ +static void +grn_ts_expr_end_token_fin(grn_ctx *ctx, grn_ts_expr_end_token *token) +{ + /* Nothing to do. */ +} + +/* grn_ts_expr_const_token_fin() finalizes a token. */ +static void +grn_ts_expr_const_token_fin(grn_ctx *ctx, grn_ts_expr_const_token *token) +{ + grn_ts_buf_fin(ctx, &token->buf); +} + +/* grn_ts_expr_name_token_fin() finalizes a token. */ +static void +grn_ts_expr_name_token_fin(grn_ctx *ctx, grn_ts_expr_name_token *token) +{ + /* Nothing to do. */ +} + +/* grn_ts_expr_op_token_fin() finalizes a token. */ +static void +grn_ts_expr_op_token_fin(grn_ctx *ctx, grn_ts_expr_op_token *token) +{ + /* Nothing to do. */ +} + +/* grn_ts_expr_bridge_token_fin() finalizes a token. */ +static void +grn_ts_expr_bridge_token_fin(grn_ctx *ctx, grn_ts_expr_bridge_token *token) +{ + /* Nothing to do. */ +} + +/* grn_ts_expr_bracket_token_fin() finalizes a token. */ +static void +grn_ts_expr_bracket_token_fin(grn_ctx *ctx, grn_ts_expr_bracket_token *token) +{ + /* Nothing to do. */ +} + +#define GRN_TS_EXPR_TOKEN_OPEN(TYPE, type)\ + grn_ts_expr_ ## type ## _token *new_token;\ + new_token = GRN_MALLOCN(grn_ts_expr_ ## type ## _token, 1);\ + if (!new_token) {\ + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE,\ + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1",\ + sizeof(grn_ts_expr_ ## type ## _token));\ + }\ + grn_ts_expr_ ## type ## _token_init(ctx, new_token, src);\ + *token = new_token; +/* grn_ts_expr_dummy_token_open() creates a token. */ +/* +static grn_rc +grn_ts_expr_dummy_token_open(grn_ctx *ctx, grn_ts_str src, + grn_ts_expr_dummy_token **token) +{ + GRN_TS_EXPR_TOKEN_OPEN(DUMMY, dummy) + return GRN_SUCCESS; +} +*/ + +/* grn_ts_expr_start_token_open() creates a token. */ +static grn_rc +grn_ts_expr_start_token_open(grn_ctx *ctx, grn_ts_str src, + grn_ts_expr_start_token **token) +{ + GRN_TS_EXPR_TOKEN_OPEN(START, start) + return GRN_SUCCESS; +} + +/* grn_ts_expr_end_token_open() creates a token. */ +static grn_rc +grn_ts_expr_end_token_open(grn_ctx *ctx, grn_ts_str src, + grn_ts_expr_end_token **token) +{ + GRN_TS_EXPR_TOKEN_OPEN(END, end) + return GRN_SUCCESS; +} + +/* grn_ts_expr_const_token_open() creates a token. */ +static grn_rc +grn_ts_expr_const_token_open(grn_ctx *ctx, grn_ts_str src, + grn_ts_expr_const_token **token) + { + GRN_TS_EXPR_TOKEN_OPEN(CONST, const) + return GRN_SUCCESS; +} + +/* grn_ts_expr_name_token_open() creates a token. */ +static grn_rc +grn_ts_expr_name_token_open(grn_ctx *ctx, grn_ts_str src, + grn_ts_expr_name_token **token) +{ + GRN_TS_EXPR_TOKEN_OPEN(NAME, name) + return GRN_SUCCESS; +} + +/* grn_ts_expr_op_token_open() creates a token. */ +static grn_rc +grn_ts_expr_op_token_open(grn_ctx *ctx, grn_ts_str src, grn_ts_op_type op_type, + grn_ts_expr_op_token **token) +{ + GRN_TS_EXPR_TOKEN_OPEN(OP, op) + new_token->op_type = op_type; + return GRN_SUCCESS; +} + +/* grn_ts_expr_bridge_token_open() creates a token. */ +static grn_rc +grn_ts_expr_bridge_token_open(grn_ctx *ctx, grn_ts_str src, + grn_ts_expr_bridge_token **token) +{ + GRN_TS_EXPR_TOKEN_OPEN(BRIDGE, bridge) + return GRN_SUCCESS; +} + +/* grn_ts_expr_bracket_token_open() creates a token. */ +static grn_rc +grn_ts_expr_bracket_token_open(grn_ctx *ctx, grn_ts_str src, + grn_ts_expr_bracket_token **token) +{ + GRN_TS_EXPR_TOKEN_OPEN(BRACKET, bracket) + return GRN_SUCCESS; +} +#undef GRN_TS_EXPR_TOKEN_OPEN + +#define GRN_TS_EXPR_TOKEN_CLOSE_CASE(TYPE, type)\ + case GRN_TS_EXPR_ ## TYPE ## _TOKEN: {\ + grn_ts_expr_ ## type ## _token *type ## _token;\ + type ## _token = (grn_ts_expr_ ## type ## _token *)token;\ + grn_ts_expr_ ## type ## _token_fin(ctx, type ## _token);\ + break;\ + } +/* grn_ts_expr_token_close() destroys a token. */ +static void +grn_ts_expr_token_close(grn_ctx *ctx, grn_ts_expr_token *token) +{ + switch (token->type) { + GRN_TS_EXPR_TOKEN_CLOSE_CASE(DUMMY, dummy) + GRN_TS_EXPR_TOKEN_CLOSE_CASE(START, start) + GRN_TS_EXPR_TOKEN_CLOSE_CASE(END, end) + GRN_TS_EXPR_TOKEN_CLOSE_CASE(CONST, const) + GRN_TS_EXPR_TOKEN_CLOSE_CASE(NAME, name) + GRN_TS_EXPR_TOKEN_CLOSE_CASE(OP, op) + GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRACKET, bracket) + GRN_TS_EXPR_TOKEN_CLOSE_CASE(BRIDGE, bridge) + } + GRN_FREE(token); +} +#undef GRN_TS_EXPR_TOKEN_CLOSE_CASE + +/*------------------------------------------------------------- + * grn_ts_expr_parser. + */ + +/* grn_ts_expr_parser_init() initializes a parser. */ +static void +grn_ts_expr_parser_init(grn_ctx *ctx, grn_ts_expr_parser *parser) +{ + memset(parser, 0, sizeof(*parser)); + parser->builder = NULL; + grn_ts_buf_init(ctx, &parser->str_buf); + parser->tokens = NULL; + parser->dummy_tokens = NULL; + parser->stack = NULL; +} + +/* grn_ts_expr_parser_fin() finalizes a parser. */ +static void +grn_ts_expr_parser_fin(grn_ctx *ctx, grn_ts_expr_parser *parser) +{ + if (parser->stack) { + GRN_FREE(parser->stack); + } + if (parser->dummy_tokens) { + size_t i; + for (i = 0; i < parser->n_dummy_tokens; i++) { + grn_ts_expr_dummy_token_fin(ctx, &parser->dummy_tokens[i]); + } + GRN_FREE(parser->dummy_tokens); + } + if (parser->tokens) { + size_t i; + for (i = 0; i < parser->n_tokens; i++) { + grn_ts_expr_token_close(ctx, parser->tokens[i]); + } + GRN_FREE(parser->tokens); + } + grn_ts_buf_fin(ctx, &parser->str_buf); + if (parser->builder) { + grn_ts_expr_builder_close(ctx, parser->builder); + } +} + +grn_rc +grn_ts_expr_parser_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_parser **parser) +{ + grn_rc rc; + grn_ts_expr_parser *new_parser; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || !parser) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + new_parser = GRN_MALLOCN(grn_ts_expr_parser, 1); + if (!new_parser) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_expr_parser)); + } + grn_ts_expr_parser_init(ctx, new_parser); + rc = grn_ts_expr_builder_open(ctx, table, &new_parser->builder); + if (rc != GRN_SUCCESS) { + grn_ts_expr_parser_fin(ctx, new_parser); + GRN_FREE(new_parser); + return rc; + } + *parser = new_parser; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!parser) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + grn_ts_expr_parser_fin(ctx, parser); + GRN_FREE(parser); + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_tokenize_start() creates the start token. */ +static grn_rc +grn_ts_expr_parser_tokenize_start(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr_token **token) +{ + grn_ts_str token_str = { str.ptr, 0 }; + grn_ts_expr_start_token *new_token; + grn_rc rc = grn_ts_expr_start_token_open(ctx, token_str, &new_token); + if (rc != GRN_SUCCESS) { + return rc; + } + *token = (grn_ts_expr_token *)new_token; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_tokenize_end() creates the end token. */ +static grn_rc +grn_ts_expr_parser_tokenize_end(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr_token **token) +{ + grn_ts_str token_str = { str.ptr, 0 }; + grn_ts_expr_end_token *new_token; + grn_rc rc = grn_ts_expr_end_token_open(ctx, token_str, &new_token); + if (rc != GRN_SUCCESS) { + return rc; + } + *token = (grn_ts_expr_token *)new_token; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_tokenize_number() tokenizes an Int or Float literal. */ +static grn_rc +grn_ts_expr_parser_tokenize_number(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr_token **token) +{ + char *end; + grn_rc rc; + grn_ts_int int_value; + grn_ts_str token_str; + grn_ts_expr_const_token *new_token; + + int_value = strtol(str.ptr, &end, 0); + if ((end != str.ptr) && (*end != '.') && (*end != 'e')) { + if (grn_ts_byte_is_name_char(*end)) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, + "unterminated Int literal: \"%.*s\"", + (int)str.size, str.ptr); + } + token_str.ptr = str.ptr; + token_str.size = end - str.ptr; + rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); + if (rc != GRN_SUCCESS) { + return rc; + } + new_token->data_kind = GRN_TS_INT; + new_token->content.as_int = int_value; + } else { + grn_ts_float float_value = strtod(str.ptr, &end); + if (end == str.ptr) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid number literal: \"%.*s\"", + (int)str.size, str.ptr); + } + if (grn_ts_byte_is_name_char(*end)) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, + "unterminated Float literal: \"%.*s\"", + (int)str.size, str.ptr); + } + token_str.ptr = str.ptr; + token_str.size = end - str.ptr; + rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); + if (rc != GRN_SUCCESS) { + return rc; + } + new_token->data_kind = GRN_TS_FLOAT; + new_token->content.as_float = float_value; + } + *token = (grn_ts_expr_token *)new_token; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_tokenize_text() tokenizes a Text literal. */ +static grn_rc +grn_ts_expr_parser_tokenize_text(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr_token **token) +{ + size_t i, n_escapes = 0; + grn_rc rc; + grn_ts_str token_str; + grn_ts_expr_const_token *new_token; + for (i = 1; i < str.size; i++) { + if (str.ptr[i] == '\\') { + i++; + n_escapes++; + } else if (str.ptr[i] == '"') { + break; + } + } + if (i >= str.size) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "no closing double quote: \"%.*s\"", + (int)str.size, str.ptr); + } + token_str.ptr = str.ptr; + token_str.size = i + 1; + rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); + if (rc != GRN_SUCCESS) { + return rc; + } + new_token->data_kind = GRN_TS_TEXT; + if (n_escapes) { + char *buf_ptr; + const char *str_ptr = str.ptr + 1; + size_t size = token_str.size - 2 - n_escapes; + rc = grn_ts_buf_resize(ctx, &new_token->buf, size); + if (rc != GRN_SUCCESS) { + grn_ts_expr_token_close(ctx, (grn_ts_expr_token *)new_token); + return rc; + } + buf_ptr = (char *)new_token->buf.ptr; + for (i = 0; i < size; i++) { + if (str_ptr[i] == '\\') { + str_ptr++; + } + buf_ptr[i] = str_ptr[i]; + } + new_token->content.as_text.ptr = buf_ptr; + new_token->content.as_text.size = size; + } else { + new_token->content.as_text.ptr = token_str.ptr + 1; + new_token->content.as_text.size = token_str.size - 2; + } + *token = (grn_ts_expr_token *)new_token; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_tokenize_name() tokenizes a Bool literal or a name. */ +static grn_rc +grn_ts_expr_parser_tokenize_name(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr_token **token) +{ + size_t i; + grn_ts_str token_str; + for (i = 1; i < str.size; i++) { + if (!grn_ts_byte_is_name_char(str.ptr[i])) { + break; + } + } + token_str.ptr = str.ptr; + token_str.size = i; + + if (grn_ts_str_is_bool(token_str)) { + grn_ts_expr_const_token *new_token; + grn_rc rc = grn_ts_expr_const_token_open(ctx, token_str, &new_token); + if (rc != GRN_SUCCESS) { + return rc; + } + new_token->data_kind = GRN_TS_BOOL; + if (token_str.ptr[0] == 't') { + new_token->content.as_bool = GRN_TRUE; + } else { + new_token->content.as_bool = GRN_FALSE; + } + *token = (grn_ts_expr_token *)new_token; + return GRN_SUCCESS; + } + return grn_ts_expr_name_token_open(ctx, token_str, token); +} + +/* grn_ts_expr_parser_tokenize_bridge() tokenizes a bridge. */ +static grn_rc +grn_ts_expr_parser_tokenize_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr_token **token) +{ + grn_ts_str token_str = { str.ptr, 1 }; + grn_ts_expr_bridge_token *new_token; + grn_rc rc = grn_ts_expr_bridge_token_open(ctx, token_str, &new_token); + if (rc != GRN_SUCCESS) { + return rc; + } + *token = (grn_ts_expr_token *)new_token; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_tokenize_bracket() tokenizes a bracket. */ +static grn_rc +grn_ts_expr_parser_tokenize_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, + grn_ts_expr_token **token) +{ + grn_ts_str token_str = { str.ptr, 1 }; + grn_ts_expr_bracket_token *new_token; + grn_rc rc = grn_ts_expr_bracket_token_open(ctx, token_str, &new_token); + if (rc != GRN_SUCCESS) { + return rc; + } + *token = (grn_ts_expr_token *)new_token; + return GRN_SUCCESS; +} + +/* + * grn_ts_expr_parsre_tokenize_sign() tokenizes an operator '+' or '-'. + * Note that '+' and '-' have two roles each. + * '+' is GRN_TS_OP_POSITIVE or GRN_TS_OP_PLUS. + * '-' is GRN_TS_OP_NEGATIVE or GRN_TS_OP_MINUS. + */ +static grn_rc +grn_ts_expr_parser_tokenize_sign(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr_token **token) +{ + size_t n_args; + grn_rc rc; + grn_ts_op_type op_type; + grn_ts_str token_str = { str.ptr, 1 }; + grn_ts_expr_token *prev_token = parser->tokens[parser->n_tokens - 1]; + grn_ts_expr_op_token *new_token; + switch (prev_token->type) { + case GRN_TS_EXPR_START_TOKEN: + case GRN_TS_EXPR_OP_TOKEN: { + n_args = 1; + break; + } + case GRN_TS_EXPR_CONST_TOKEN: + case GRN_TS_EXPR_NAME_TOKEN: { + n_args = 2; + break; + } + case GRN_TS_EXPR_BRACKET_TOKEN: { + grn_ts_str bracket; + const grn_ts_expr_bracket_token *bracket_token; + bracket_token = (const grn_ts_expr_bracket_token *)prev_token; + bracket = bracket_token->src; + switch (bracket.ptr[0]) { + case '(': case '[': { + n_args = 1; + break; + } + case ')': case ']': { + n_args = 2; + break; + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "undefined bracket: \"%.*s\"", + (int)bracket.size, bracket.ptr); + } + } + break; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence: %d", + prev_token->type); + } + } + if (token_str.ptr[0] == '+') { + op_type = (n_args == 1) ? GRN_TS_OP_POSITIVE : GRN_TS_OP_PLUS; + } else { + op_type = (n_args == 1) ? GRN_TS_OP_NEGATIVE : GRN_TS_OP_MINUS; + } + rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); + if (rc != GRN_SUCCESS) { + return rc; + } + *token = (grn_ts_expr_token *)new_token; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_tokenize_op() tokenizes an operator. */ +static grn_rc +grn_ts_expr_parser_tokenize_op(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr_token **token) +{ + grn_rc rc = GRN_SUCCESS; + grn_ts_str token_str = str; + grn_ts_op_type op_type; + grn_ts_expr_op_token *new_token; + switch (str.ptr[0]) { + case '+': case '-': { + return grn_ts_expr_parser_tokenize_sign(ctx, parser, str, token); + } + case '!': { + if ((str.size >= 2) && (str.ptr[1] == '=')) { + token_str.size = 2; + op_type = GRN_TS_OP_NOT_EQUAL; + } else { + token_str.size = 1; + op_type = GRN_TS_OP_LOGICAL_NOT; + } + rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); + break; + } +#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE_1, TYPE_2, TYPE_3,\ + TYPE_EQUAL)\ + case label: {\ + if ((str.size >= 2) && (str.ptr[1] == '=')) {\ + token_str.size = 2;\ + op_type = GRN_TS_OP_ ## TYPE_EQUAL;\ + } else if ((str.size >= 2) && (str.ptr[1] == label)) {\ + if ((str.size >= 3) && (str.ptr[2] == label)) {\ + token_str.size = 3;\ + op_type = GRN_TS_OP_ ## TYPE_3;\ + } else {\ + token_str.size = 2;\ + op_type = GRN_TS_OP_ ## TYPE_2;\ + }\ + } else {\ + token_str.size = 1;\ + op_type = GRN_TS_OP_ ## TYPE_1;\ + }\ + rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token);\ + break;\ + } + GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('<', LESS, SHIFT_ARITHMETIC_LEFT, + SHIFT_LOGICAL_LEFT, LESS_EQUAL) + GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('>', GREATER, SHIFT_ARITHMETIC_RIGHT, + SHIFT_LOGICAL_RIGHT, GREATER_EQUAL) +#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE + case '&': { + if ((str.size >= 2) && (str.ptr[1] == '&')) { + token_str.size = 2; + op_type = GRN_TS_OP_LOGICAL_AND; + } else if ((str.size >= 2) && (str.ptr[1] == '&')) { + token_str.size = 2; + op_type = GRN_TS_OP_LOGICAL_SUB; + } else { + token_str.size = 1; + op_type = GRN_TS_OP_BITWISE_AND; + } + rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); + break; + } + case '|': { + if ((str.size >= 2) && (str.ptr[1] == '|')) { + token_str.size = 2; + op_type = GRN_TS_OP_LOGICAL_OR; + } else { + token_str.size = 1; + op_type = GRN_TS_OP_BITWISE_OR; + } + rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); + break; + } + case '=': { + if ((str.size < 2) || (str.ptr[1] != '=')) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, + "single equal not available: =\"%.*s\"", + (int)str.size, str.ptr); + } + token_str.size = 2; + rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_EQUAL, + &new_token); + break; + } +#define GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE(label, TYPE)\ + case label: {\ + token_str.size = 1;\ + rc = grn_ts_expr_op_token_open(ctx, token_str, GRN_TS_OP_ ## TYPE,\ + &new_token);\ + break;\ + } + GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('~', BITWISE_NOT) + GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('^', BITWISE_XOR) + GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('*', MULTIPLICATION) + GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('/', DIVISION) + GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE('%', MODULUS) +#undef GRN_TS_EXPR_PARSER_TOKENIZE_OP_CASE + case '@': { + if ((str.size >= 2) && (str.ptr[1] == '^')) { + token_str.size = 2; + op_type = GRN_TS_OP_PREFIX_MATCH; + } else if ((str.size >= 2) && (str.ptr[1] == '$')) { + token_str.size = 2; + op_type = GRN_TS_OP_SUFFIX_MATCH; + } else { + token_str.size = 1; + op_type = GRN_TS_OP_MATCH; + } + rc = grn_ts_expr_op_token_open(ctx, token_str, op_type, &new_token); + break; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid character: \"%.*s\"", + (int)str.size, str.ptr); + } + } + if (rc != GRN_SUCCESS) { + return rc; + } + *token = (grn_ts_expr_token *)new_token; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_tokenize_next() extracts the next token. */ +static grn_rc +grn_ts_expr_parser_tokenize_next(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr_token **token) +{ + grn_ts_str rest; + if (!parser->n_tokens) { + return grn_ts_expr_parser_tokenize_start(ctx, parser, str, token); + } + rest = grn_ts_str_trim_left(str); + if (!rest.size) { + return grn_ts_expr_parser_tokenize_end(ctx, parser, rest, token); + } + if (grn_ts_str_has_number_prefix(rest)) { + grn_ts_expr_token *prev_token; + if ((rest.ptr[0] != '+') && (rest.ptr[0] != '-')) { + return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); + } + prev_token = parser->tokens[parser->n_tokens - 1]; + switch (prev_token->type) { + case GRN_TS_EXPR_START_TOKEN: + case GRN_TS_EXPR_OP_TOKEN: { + return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); + } + case GRN_TS_EXPR_BRACKET_TOKEN: { + if ((prev_token->src.ptr[0] == '(') || + (prev_token->src.ptr[0] == '[')) { + return grn_ts_expr_parser_tokenize_number(ctx, parser, rest, token); + } + break; + } + default: { + break; + } + } + } + if (rest.ptr[0] == '"') { + return grn_ts_expr_parser_tokenize_text(ctx, parser, rest, token); + } + if (grn_ts_byte_is_name_char(rest.ptr[0])) { + return grn_ts_expr_parser_tokenize_name(ctx, parser, rest, token); + } + switch (rest.ptr[0]) { + case '(': case ')': case '[': case ']': { + return grn_ts_expr_parser_tokenize_bracket(ctx, parser, rest, token); + } + case '.': { + return grn_ts_expr_parser_tokenize_bridge(ctx, parser, rest, token); + } + default: { + return grn_ts_expr_parser_tokenize_op(ctx, parser, rest, token); + } + } +} + +/* + * grn_ts_expr_parser_reserve_tokens() extends a token buffer for a new token. + */ +static grn_rc +grn_ts_expr_parser_reserve_tokens(grn_ctx *ctx, grn_ts_expr_parser *parser) +{ + size_t i, n_bytes, new_max_n_tokens; + grn_ts_expr_token **new_tokens; + if (parser->n_tokens < parser->max_n_tokens) { + return GRN_SUCCESS; + } + new_max_n_tokens = parser->n_tokens * 2; + if (!new_max_n_tokens) { + new_max_n_tokens = 1; + } + n_bytes = sizeof(grn_ts_expr_token *) * new_max_n_tokens; + new_tokens = (grn_ts_expr_token **)GRN_REALLOC(parser->tokens, n_bytes); + if (!new_tokens) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, + n_bytes); + } + for (i = parser->n_tokens; i < new_max_n_tokens; i++) { + new_tokens[i] = NULL; + } + parser->tokens = new_tokens; + parser->max_n_tokens = new_max_n_tokens; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_tokenize() tokenizes a string. */ +static grn_rc +grn_ts_expr_parser_tokenize(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str) +{ + grn_ts_str rest = str; + const char *end = str.ptr + str.size; + grn_ts_expr_token *token = NULL; + GRN_TS_DEBUG("str = \"%.*s\"", (int)str.size, str.ptr); + do { + grn_rc rc = grn_ts_expr_parser_reserve_tokens(ctx, parser); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_parser_tokenize_next(ctx, parser, rest, &token); + if (rc != GRN_SUCCESS) { + return rc; + } + if ((token->type != GRN_TS_EXPR_START_TOKEN) && + (token->type != GRN_TS_EXPR_END_TOKEN)) { + GRN_TS_DEBUG("token = \"%.*s\"", (int)token->src.size, token->src.ptr); + } + parser->tokens[parser->n_tokens++] = token; + rest.ptr = token->src.ptr + token->src.size; + rest.size = end - rest.ptr; + } while (token->type != GRN_TS_EXPR_END_TOKEN); + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_push_const() pushes a token to an expression. */ +static grn_rc +grn_ts_expr_parser_push_const(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_expr_const_token *token) +{ + return grn_ts_expr_builder_push_const(ctx, parser->builder, token->data_kind, + GRN_DB_VOID, token->content); +} + +/* grn_ts_expr_parser_push_name() pushes a token to an expression. */ +static grn_rc +grn_ts_expr_parser_push_name(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_expr_name_token *token) +{ + return grn_ts_expr_builder_push_name(ctx, parser->builder, token->src); +} + +/* grn_ts_expr_parser_push_op() pushes a token to an expression. */ +static grn_rc +grn_ts_expr_parser_push_op(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_expr_op_token *token) +{ + return grn_ts_expr_builder_push_op(ctx, parser->builder, token->op_type); +} + +/* + * grn_ts_expr_parser_apply_one() applies a bridge or prior operator. + * If there is no target, this function returns GRN_END_OF_DATA. + */ +// FIXME: Support a ternary operator. +static grn_rc +grn_ts_expr_parser_apply_one(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_op_precedence precedence_threshold) +{ + grn_rc rc; + grn_ts_str src; + grn_ts_expr_token **stack = parser->stack; + grn_ts_expr_dummy_token *dummy_token; + size_t n_args, depth = parser->stack_depth; + if (depth < 2) { + return GRN_END_OF_DATA; + } + if (stack[depth - 1]->type != GRN_TS_EXPR_DUMMY_TOKEN) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "argument must be dummy token"); + } + + /* Check the number of arguments. */ + switch (stack[depth - 2]->type) { + case GRN_TS_EXPR_BRIDGE_TOKEN: { + rc = grn_ts_expr_builder_end_subexpr(ctx, parser->builder); + if (rc != GRN_SUCCESS) { + return rc; + } + n_args = 2; + break; + } + case GRN_TS_EXPR_OP_TOKEN: { + grn_ts_expr_op_token *op_token; + grn_ts_op_precedence precedence; + op_token = (grn_ts_expr_op_token *)stack[depth - 2]; + precedence = grn_ts_op_get_precedence(op_token->op_type); + if (precedence < precedence_threshold) { + return GRN_END_OF_DATA; + } + rc = grn_ts_expr_parser_push_op(ctx, parser, op_token); + if (rc != GRN_SUCCESS) { + return rc; + } + n_args = grn_ts_op_get_n_args(op_token->op_type); + break; + } + default: { + return GRN_END_OF_DATA; + } + } + + /* Concatenate the source strings. */ + switch (n_args) { + case 1: { + grn_ts_expr_token *arg = stack[depth - 1]; + src.ptr = stack[depth - 2]->src.ptr; + src.size = (arg->src.ptr + arg->src.size) - src.ptr; + break; + } + case 2: { + grn_ts_expr_token *args[2] = { stack[depth - 3], stack[depth - 1] }; + src.ptr = args[0]->src.ptr; + src.size = (args[1]->src.ptr + args[1]->src.size) - src.ptr; + break; + } + default: { + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, + "invalid #arguments: %" GRN_FMT_SIZE, + n_args); + } + } + + /* Replace the operator and argument tokens with a dummy token. */ + dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; + GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr); + grn_ts_expr_dummy_token_init(ctx, dummy_token, src); + depth -= n_args + 1; + stack[depth++] = dummy_token; + parser->stack_depth = depth; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_apply() applies bridges and prior operators. */ +static grn_rc +grn_ts_expr_parser_apply(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_op_precedence precedence_threshold) +{ + for ( ; ; ) { + grn_rc rc = grn_ts_expr_parser_apply_one(ctx, parser, + precedence_threshold); + if (rc == GRN_END_OF_DATA) { + return GRN_SUCCESS; + } else if (rc != GRN_SUCCESS) { + return rc; + } + } +} + +/* grn_ts_expr_parser_analyze_op() analyzes a token. */ +static grn_rc +grn_ts_expr_parser_analyze_op(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_expr_op_token *token) +{ + size_t n_args = grn_ts_op_get_n_args(token->op_type); + grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1]; + if (n_args == 1) { + if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); + } + } else if (n_args == 2) { + grn_ts_op_precedence precedence = grn_ts_op_get_precedence(token->op_type); + grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, precedence); + if (rc != GRN_SUCCESS) { + return rc; + } + } + parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_analyze_bridge() analyzes a token. */ +static grn_rc +grn_ts_expr_parser_analyze_bridge(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_expr_bridge_token *token) +{ + grn_rc rc = grn_ts_expr_builder_begin_subexpr(ctx, parser->builder); + if (rc != GRN_SUCCESS) { + return rc; + } + parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; + return GRN_SUCCESS; +} + +/* grn_ts_expr_parser_analyze_bracket() analyzes a token. */ +static grn_rc +grn_ts_expr_parser_analyze_bracket(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_expr_bracket_token *token) +{ + grn_ts_expr_token *ex_token = parser->stack[parser->stack_depth - 1]; + switch (token->src.ptr[0]) { + case '(': { + if (ex_token->type == GRN_TS_EXPR_DUMMY_TOKEN) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); + } + parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; + return GRN_SUCCESS; + } + case '[': { + if (ex_token->type != GRN_TS_EXPR_DUMMY_TOKEN) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); + } + parser->stack[parser->stack_depth++] = (grn_ts_expr_token *)token; + return GRN_SUCCESS; + } + case ')': case ']': { + grn_ts_expr_token *ex_ex_token; + grn_rc rc = grn_ts_expr_parser_apply(ctx, parser, 0); + if (rc != GRN_SUCCESS) { + return rc; + } + if (parser->stack_depth < 2) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); + } + ex_ex_token = parser->stack[parser->stack_depth - 2]; + if (ex_ex_token->type != GRN_TS_EXPR_BRACKET_TOKEN) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); + } + if (token->src.ptr[0] == ')') { + size_t depth = parser->stack_depth; + grn_ts_str src; + grn_ts_expr_dummy_token *dummy_token; + if (ex_ex_token->src.ptr[0] != '(') { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); + } + src.ptr = ex_ex_token->src.ptr; + src.size = (token->src.ptr + token->src.size) - src.ptr; + dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; + GRN_TS_DEBUG("dummy token: \"%.*s\"", (int)src.size, src.ptr); + grn_ts_expr_dummy_token_init(ctx, dummy_token, src); + parser->stack[depth - 2] = dummy_token; + parser->stack_depth--; + // TODO: Apply a function. + } else if (token->src.ptr[0] == ']') { + size_t depth = parser->stack_depth; + if (ex_ex_token->src.ptr[0] != '[') { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "invalid token sequence"); + } + parser->stack[depth - 2] = parser->stack[depth - 1]; + parser->stack_depth--; + // TODO: Push a subscript operator. + } + return GRN_SUCCESS; + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, "undefined bracket: \"%.*s\"", + (int)token->src.size, token->src.ptr); + } + } +} + +/* grn_ts_expr_parser_analyze_token() analyzes a token. */ +static grn_rc +grn_ts_expr_parser_analyze_token(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_expr_token *token) +{ + switch (token->type) { + case GRN_TS_EXPR_START_TOKEN: { + parser->stack[parser->stack_depth++] = token; + return GRN_SUCCESS; + } + case GRN_TS_EXPR_END_TOKEN: { + return grn_ts_expr_parser_apply(ctx, parser, 0); + } + case GRN_TS_EXPR_CONST_TOKEN: { + grn_ts_expr_const_token *const_token = (grn_ts_expr_const_token *)token; + grn_ts_expr_dummy_token *dummy_token; + grn_rc rc = grn_ts_expr_parser_push_const(ctx, parser, const_token); + if (rc != GRN_SUCCESS) { + return rc; + } + dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; + grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src); + parser->stack[parser->stack_depth++] = dummy_token; + return GRN_SUCCESS; + } + case GRN_TS_EXPR_NAME_TOKEN: { + grn_ts_expr_name_token *name_token = (grn_ts_expr_name_token *)token; + grn_ts_expr_dummy_token *dummy_token; + grn_rc rc = grn_ts_expr_parser_push_name(ctx, parser, name_token); + if (rc != GRN_SUCCESS) { + return rc; + } + dummy_token = &parser->dummy_tokens[parser->n_dummy_tokens++]; + grn_ts_expr_dummy_token_init(ctx, dummy_token, token->src); + parser->stack[parser->stack_depth++] = dummy_token; + return GRN_SUCCESS; + } + case GRN_TS_EXPR_OP_TOKEN: { + grn_ts_expr_op_token *op_token = (grn_ts_expr_op_token *)token; + return grn_ts_expr_parser_analyze_op(ctx, parser, op_token); + } + case GRN_TS_EXPR_BRIDGE_TOKEN: { + grn_ts_expr_bridge_token *bridge_token; + bridge_token = (grn_ts_expr_bridge_token *)token; + return grn_ts_expr_parser_analyze_bridge(ctx, parser, bridge_token); + } + case GRN_TS_EXPR_BRACKET_TOKEN: { + grn_ts_expr_bracket_token *bracket_token; + bracket_token = (grn_ts_expr_bracket_token *)token; + return grn_ts_expr_parser_analyze_bracket(ctx, parser, bracket_token); + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid token type: %d", + token->type); + } + } +} + +/* grn_ts_expr_parser_analyze() analyzes tokens. */ +static grn_rc +grn_ts_expr_parser_analyze(grn_ctx *ctx, grn_ts_expr_parser *parser) +{ + size_t i; + + /* Reserve temporary work spaces. */ + if (parser->n_tokens > parser->max_n_dummy_tokens) { + size_t n_bytes = sizeof(grn_ts_expr_dummy_token) * parser->n_tokens; + grn_ts_expr_dummy_token *dummy_tokens = parser->dummy_tokens; + grn_ts_expr_dummy_token *new_dummy_tokens; + new_dummy_tokens = (grn_ts_expr_dummy_token *)GRN_REALLOC(dummy_tokens, + n_bytes); + if (!new_dummy_tokens) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, n_bytes); + } + parser->dummy_tokens = new_dummy_tokens; + parser->max_n_dummy_tokens = parser->n_tokens; + } + if (parser->n_tokens > parser->stack_size) { + size_t n_bytes = sizeof(grn_ts_expr_token *) * parser->n_tokens; + grn_ts_expr_token **new_stack; + new_stack = (grn_ts_expr_token **)GRN_REALLOC(parser->stack, n_bytes); + if (!new_stack) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_REALLOC failed: %" GRN_FMT_SIZE, n_bytes); + } + parser->stack = new_stack; + parser->stack_size = parser->n_tokens; + } + + /* Analyze tokens. */ + for (i = 0; i < parser->n_tokens; i++) { + grn_rc rc; + rc = grn_ts_expr_parser_analyze_token(ctx, parser, parser->tokens[i]); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (parser->stack_depth != 2) { + GRN_TS_ERR_RETURN(GRN_INVALID_FORMAT, + "tokens left in stack: %" GRN_FMT_SIZE, + parser->stack_depth); + } + return GRN_SUCCESS; +} + +/* + * grn_ts_expr_parser_clear() clears the internal states for parsing the next + * string. + */ +static void +grn_ts_expr_parser_clear(grn_ctx *ctx, grn_ts_expr_parser *parser) +{ + parser->stack_depth = 0; + if (parser->dummy_tokens) { + size_t i; + for (i = 0; i < parser->n_dummy_tokens; i++) { + grn_ts_expr_dummy_token_fin(ctx, &parser->dummy_tokens[i]); + } + parser->n_dummy_tokens = 0; + } + if (parser->tokens) { + size_t i; + for (i = 0; i < parser->n_tokens; i++) { + grn_ts_expr_token_close(ctx, parser->tokens[i]); + } + parser->n_tokens = 0; + } + grn_ts_expr_builder_clear(ctx, parser->builder); +} + +grn_rc +grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr **expr) +{ + grn_rc rc; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!parser || (!str.ptr && str.size)) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + grn_ts_expr_parser_clear(ctx, parser); + rc = grn_ts_buf_reserve(ctx, &parser->str_buf, str.size + 1); + if (rc != GRN_SUCCESS) { + return rc; + } + grn_memcpy(parser->str_buf.ptr, str.ptr, str.size); + ((char *)parser->str_buf.ptr)[str.size] = '\0'; + str.ptr = (const char *)parser->str_buf.ptr; + rc = grn_ts_expr_parser_tokenize(ctx, parser, str); + if (rc != GRN_SUCCESS) { + return rc; + } + rc = grn_ts_expr_parser_analyze(ctx, parser); + if (rc != GRN_SUCCESS) { + return rc; + } + return grn_ts_expr_builder_complete(ctx, parser->builder, expr); +} + +grn_rc +grn_ts_expr_parser_split(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_str *first, grn_ts_str *rest) +{ + size_t i; + char stack_top; + grn_rc rc = GRN_SUCCESS; + grn_ts_buf stack; + + // FIXME: `stack` should be a member of `parser`. + grn_ts_buf_init(ctx, &stack); + for ( ; ; ) { + str = grn_ts_str_trim_left(str); + if (!str.size) { + rc = GRN_END_OF_DATA; + break; + } + for (i = 0; i < str.size; i++) { + if (stack.pos) { + if (str.ptr[i] == stack_top) { + if (--stack.pos) { + stack_top = ((char *)stack.ptr)[stack.pos - 1]; + } + continue; + } + if (stack_top == '"') { + /* Skip the next byte of an escape character. */ + if ((str.ptr[i] == '\\') && (i < (str.size - 1))) { + i++; + } + continue; + } + } else if (str.ptr[i] == ',') { + /* An expression delimiter. */ + break; + } + switch (str.ptr[i]) { + case '(': { + stack_top = ')'; + rc = grn_ts_buf_write(ctx, &stack, &stack_top, 1); + break; + } + case '[': { + stack_top = ']'; + rc = grn_ts_buf_write(ctx, &stack, &stack_top, 1); + break; + } + case '{': { + stack_top = '}'; + rc = grn_ts_buf_write(ctx, &stack, &stack_top, 1); + break; + } + case '"': { + stack_top = '"'; + rc = grn_ts_buf_write(ctx, &stack, &stack_top, 1); + break; + } + } + if (rc != GRN_SUCCESS) { + break; + } + } + if (rc != GRN_SUCCESS) { + break; + } + if (i) { + /* Set the result. */ + first->ptr = str.ptr; + first->size = i; + if (first->size == str.size) { + rest->ptr = str.ptr + str.size; + rest->size = 0; + } else { + rest->ptr = str.ptr + first->size + 1; + rest->size = str.size - first->size - 1; + } + break; + } + str.ptr++; + str.size--; + } + grn_ts_buf_fin(ctx, &stack); + return rc; +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_expr_parser.h b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_parser.h new file mode 100644 index 00000000..77205983 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_expr_parser.h @@ -0,0 +1,107 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "ts_expr.h" +#include "ts_expr_builder.h" +#include "ts_str.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + GRN_TS_EXPR_DUMMY_TOKEN, /* No extra data. */ + GRN_TS_EXPR_START_TOKEN, /* No extra data. */ + GRN_TS_EXPR_END_TOKEN, /* No extra data. */ + GRN_TS_EXPR_CONST_TOKEN, /* +data_kind, content and buf. */ + GRN_TS_EXPR_NAME_TOKEN, /* +name. */ + GRN_TS_EXPR_OP_TOKEN, /* +op_type. */ + GRN_TS_EXPR_BRIDGE_TOKEN, /* No extra data. */ + GRN_TS_EXPR_BRACKET_TOKEN /* No extra data. */ +} grn_ts_expr_token_type; + +#define GRN_TS_EXPR_TOKEN_COMMON_MEMBERS\ + grn_ts_str src; /* Source string. */\ + grn_ts_expr_token_type type; /* Token type. */ + +typedef struct { + GRN_TS_EXPR_TOKEN_COMMON_MEMBERS +} grn_ts_expr_token; + +typedef grn_ts_expr_token grn_ts_expr_dummy_token; +typedef grn_ts_expr_token grn_ts_expr_start_token; +typedef grn_ts_expr_token grn_ts_expr_end_token; + +typedef struct { + GRN_TS_EXPR_TOKEN_COMMON_MEMBERS + grn_ts_data_kind data_kind; /* The data kind of the const. */ + grn_ts_any content; /* The const. */ + grn_ts_buf buf; /* Buffer for content.as_text. */ +} grn_ts_expr_const_token; + +typedef grn_ts_expr_token grn_ts_expr_name_token; + +typedef struct { + GRN_TS_EXPR_TOKEN_COMMON_MEMBERS + grn_ts_op_type op_type; /* Operator type. */ +} grn_ts_expr_op_token; + +typedef grn_ts_expr_token grn_ts_expr_bridge_token; +typedef grn_ts_expr_token grn_ts_expr_bracket_token; + +typedef struct { + grn_ts_expr_builder *builder; /* Builder. */ + grn_ts_buf str_buf; /* Buffer for a source string. */ + grn_ts_expr_token **tokens; /* Tokens. */ + size_t n_tokens; /* Number of tokens. */ + size_t max_n_tokens; /* Maximum number of tokens. */ + grn_ts_expr_dummy_token *dummy_tokens; /* Dummy tokens. */ + size_t n_dummy_tokens; /* Number of dummy tokens. */ + size_t max_n_dummy_tokens; /* Maximum number of dummy tokens. */ + grn_ts_expr_token **stack; /* Token stack. */ + size_t stack_depth; /* Token stack's current depth. */ + size_t stack_size; /* Token stack's capacity. */ +} grn_ts_expr_parser; + +/* grn_ts_expr_parser_open() creates a parser. */ +grn_rc grn_ts_expr_parser_open(grn_ctx *ctx, grn_obj *table, + grn_ts_expr_parser **parser); + +/* grn_ts_expr_parser_close() destroys a parser. */ +grn_rc grn_ts_expr_parser_close(grn_ctx *ctx, grn_ts_expr_parser *parser); + +/* grn_ts_expr_parser_parse() parses a string and creates an expression. */ +grn_rc grn_ts_expr_parser_parse(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_expr **expr); + +/* + * grn_ts_expr_parser_split() splits comma-separated strings into the first + * expression and the rest. + * Note that if `str` is empty, this function returns GRN_END_OF_DATA. + */ +grn_rc grn_ts_expr_parser_split(grn_ctx *ctx, grn_ts_expr_parser *parser, + grn_ts_str str, grn_ts_str *first, + grn_ts_str *rest); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_log.h b/storage/mroonga/vendor/groonga/lib/ts/ts_log.h new file mode 100644 index 00000000..844a0ee6 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_log.h @@ -0,0 +1,46 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" +#include "../grn_ctx.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* GRN_TS_DEBUG() logs a message that is useful for debug. */ +#define GRN_TS_DEBUG(...) GRN_LOG(ctx, GRN_LOG_DEBUG, __VA_ARGS__) + +/* GRN_TS_WARN() logs a warning. */ +#define GRN_TS_WARN(rc, ...) WARN(rc, __VA_ARGS__) + +/* GRN_TS_ERR() reports an error. */ +#define GRN_TS_ERR(rc, ...) ERR(rc, __VA_ARGS__) + +/* GRN_TS_ERR_RETURN() reports an error and returns its error code. */ +#define GRN_TS_ERR_RETURN(rc, ...) do {\ + GRN_TS_ERR(rc, __VA_ARGS__);\ + return rc;\ +} while (GRN_FALSE) + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_op.c b/storage/mroonga/vendor/groonga/lib/ts/ts_op.c new file mode 100644 index 00000000..64262b77 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_op.c @@ -0,0 +1,131 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_op.h" + +size_t +grn_ts_op_get_n_args(grn_ts_op_type op_type) +{ + switch (op_type) { + case GRN_TS_OP_LOGICAL_NOT: /* !X */ + case GRN_TS_OP_BITWISE_NOT: /* ~X */ + case GRN_TS_OP_POSITIVE: /* +X */ + case GRN_TS_OP_NEGATIVE: /* -X */ + case GRN_TS_OP_FLOAT: + case GRN_TS_OP_TIME: { + return 1; + } + case GRN_TS_OP_LOGICAL_AND: /* X && Y */ + case GRN_TS_OP_LOGICAL_OR: /* X || Y */ + case GRN_TS_OP_LOGICAL_SUB: /* X &! Y */ + case GRN_TS_OP_BITWISE_AND: /* X & Y */ + case GRN_TS_OP_BITWISE_OR: /* X | Y */ + case GRN_TS_OP_BITWISE_XOR: /* X ^ Y */ + case GRN_TS_OP_EQUAL: /* X == Y */ + case GRN_TS_OP_NOT_EQUAL: /* X != Y */ + case GRN_TS_OP_LESS: /* X < Y */ + case GRN_TS_OP_LESS_EQUAL: /* X <= Y */ + case GRN_TS_OP_GREATER: /* X > Y */ + case GRN_TS_OP_GREATER_EQUAL: /* X >= Y */ + case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: /* X << Y */ + case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: /* X >> Y */ + case GRN_TS_OP_SHIFT_LOGICAL_LEFT: /* X <<< Y */ + case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: /* X >>> Y */ + case GRN_TS_OP_PLUS: /* X + Y */ + case GRN_TS_OP_MINUS: /* X - Y */ + case GRN_TS_OP_MULTIPLICATION: /* X * Y */ + case GRN_TS_OP_DIVISION: /* X / Y */ + case GRN_TS_OP_MODULUS: /* X % Y */ + case GRN_TS_OP_MATCH: /* X @ Y */ + case GRN_TS_OP_PREFIX_MATCH: /* X @^ Y */ + case GRN_TS_OP_SUFFIX_MATCH: { /* X @$ Y */ + return 2; + } + default: { + return 0; + } + } +} + +grn_ts_op_precedence +grn_ts_op_get_precedence(grn_ts_op_type op_type) +{ + switch (op_type) { + case GRN_TS_OP_LOGICAL_NOT: + case GRN_TS_OP_BITWISE_NOT: + case GRN_TS_OP_POSITIVE: + case GRN_TS_OP_NEGATIVE: { + return 15; + } + case GRN_TS_OP_FLOAT: + case GRN_TS_OP_TIME: { + return 16; + } + case GRN_TS_OP_LOGICAL_AND: { + return 5; + } + case GRN_TS_OP_LOGICAL_OR: { + return 3; + } + case GRN_TS_OP_LOGICAL_SUB: { + return 4; + } + case GRN_TS_OP_BITWISE_AND: { + return 8; + } + case GRN_TS_OP_BITWISE_OR: { + return 6; + } + case GRN_TS_OP_BITWISE_XOR: { + return 7; + } + case GRN_TS_OP_EQUAL: + case GRN_TS_OP_NOT_EQUAL: { + return 9; + } + case GRN_TS_OP_LESS: + case GRN_TS_OP_LESS_EQUAL: + case GRN_TS_OP_GREATER: + case GRN_TS_OP_GREATER_EQUAL: { + return 10; + } + case GRN_TS_OP_SHIFT_ARITHMETIC_LEFT: + case GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT: + case GRN_TS_OP_SHIFT_LOGICAL_LEFT: + case GRN_TS_OP_SHIFT_LOGICAL_RIGHT: { + return 11; + } + case GRN_TS_OP_PLUS: + case GRN_TS_OP_MINUS: { + return 12; + } + case GRN_TS_OP_MULTIPLICATION: + case GRN_TS_OP_DIVISION: + case GRN_TS_OP_MODULUS: { + return 13; + } + case GRN_TS_OP_MATCH: + case GRN_TS_OP_PREFIX_MATCH: + case GRN_TS_OP_SUFFIX_MATCH: { + return 14; + } + default: { + return 0; + } + } +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_op.h b/storage/mroonga/vendor/groonga/lib/ts/ts_op.h new file mode 100644 index 00000000..7c34de96 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_op.h @@ -0,0 +1,87 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*------------------------------------------------------------- + * Operator types. + */ + +typedef enum { + /* Invalid operator. */ + GRN_TS_OP_NOP, + + /* Unary operators. */ + GRN_TS_OP_LOGICAL_NOT, /* !X */ + GRN_TS_OP_BITWISE_NOT, /* ~X */ + GRN_TS_OP_POSITIVE, /* +X */ + GRN_TS_OP_NEGATIVE, /* -X */ + + /* Typecast operators. */ + GRN_TS_OP_FLOAT, + GRN_TS_OP_TIME, + + /* Binary operators. */ + GRN_TS_OP_LOGICAL_AND, /* X && Y */ + GRN_TS_OP_LOGICAL_OR, /* X || Y */ + GRN_TS_OP_LOGICAL_SUB, /* X &! Y */ + GRN_TS_OP_BITWISE_AND, /* X & Y */ + GRN_TS_OP_BITWISE_OR, /* X | Y */ + GRN_TS_OP_BITWISE_XOR, /* X ^ Y */ + GRN_TS_OP_EQUAL, /* X == Y */ + GRN_TS_OP_NOT_EQUAL, /* X != Y */ + GRN_TS_OP_LESS, /* X < Y */ + GRN_TS_OP_LESS_EQUAL, /* X <= Y */ + GRN_TS_OP_GREATER, /* X > Y */ + GRN_TS_OP_GREATER_EQUAL, /* X >= Y */ + GRN_TS_OP_SHIFT_ARITHMETIC_LEFT, /* X << Y */ + GRN_TS_OP_SHIFT_ARITHMETIC_RIGHT, /* X >> Y */ + GRN_TS_OP_SHIFT_LOGICAL_LEFT, /* X <<< Y */ + GRN_TS_OP_SHIFT_LOGICAL_RIGHT, /* X >>> Y */ + GRN_TS_OP_PLUS, /* X + Y */ + GRN_TS_OP_MINUS, /* X - Y */ + GRN_TS_OP_MULTIPLICATION, /* X * Y */ + GRN_TS_OP_DIVISION, /* X / Y */ + GRN_TS_OP_MODULUS, /* X % Y */ + GRN_TS_OP_MATCH, /* X @ Y */ + GRN_TS_OP_PREFIX_MATCH, /* X @^ Y */ + GRN_TS_OP_SUFFIX_MATCH /* X @$ Y */ +} grn_ts_op_type; + +/* Operator precedence. */ +typedef int grn_ts_op_precedence; + +/* grn_ts_op_get_n_args() returns the number of arguments. */ +size_t grn_ts_op_get_n_args(grn_ts_op_type op_type); + +/* + * grn_ts_op_get_precedence() returns the precedence. + * A prior operator has a higher precedence. + */ +grn_ts_op_precedence grn_ts_op_get_precedence(grn_ts_op_type op_type); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_plan.c b/storage/mroonga/vendor/groonga/lib/ts/ts_plan.c new file mode 100644 index 00000000..3a8c9c0f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_plan.c @@ -0,0 +1,21 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_plan.h" + +// TODO diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_plan.h b/storage/mroonga/vendor/groonga/lib/ts/ts_plan.h new file mode 100644 index 00000000..462bccfa --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_plan.h @@ -0,0 +1,87 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#include "ts_buf.h" +#include "ts_cursor.h" +#include "ts_expr.h" +#include "ts_sorter.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int REMOVE_ME; +} grn_ts_plan_node; + +typedef struct { + grn_obj *table; + grn_ts_plan_node *root; +} grn_ts_plan; + +/* grn_ts_plan_open() creates a plan. */ +grn_rc grn_ts_plan_open(grn_ctx *ctx, grn_obj *table, grn_ts_plan_node *root, + grn_ts_plan **plan); + +/* grn_ts_plan_close() destroys a plan. */ +grn_rc grn_ts_plan_close(grn_ctx *ctx, grn_ts_plan *plan); + +/* grn_ts_plan_exec() executes a plan. */ +grn_rc grn_ts_plan_exec(grn_ctx *ctx, grn_ts_plan *plan, + grn_ts_rbuf *rbuf, size_t *n_hits); + +typedef struct { + grn_obj *table; +} grn_ts_planner; + +/* grn_ts_planner_open() creates a planner. */ +grn_rc grn_ts_planner_open(grn_ctx *ctx, grn_obj *table, + grn_ts_planner **planner); + +/* grn_ts_planner_close() destroys a planner. */ +grn_rc grn_ts_planner_close(grn_ctx *ctx, grn_ts_planner *planner); + +/* grn_ts_planner_complete() completes a planner. */ +grn_rc grn_ts_planner_complete(grn_ctx *ctx, grn_ts_planner *planner, + grn_ts_plan **plan); + +/* grn_ts_planner_push_cursor() pushes a cursor. */ +grn_rc grn_ts_planner_push_cursor(grn_ctx *ctx, grn_ts_planner *planner, + grn_ts_cursor *cursor); + +/* grn_ts_planner_push_filter() pushes a filter. */ +grn_rc grn_ts_planner_push_filter(grn_ctx *ctx, grn_ts_planner *planner, + grn_ts_expr *expr); + +/* grn_ts_planner_push_scorer() pushes a scorer. */ +grn_rc grn_ts_planner_push_scorer(grn_ctx *ctx, grn_ts_planner *planner, + grn_ts_expr *expr); + +/* grn_ts_planner_push_sorter() pushes a sorter. */ +grn_rc grn_ts_planner_push_sorter(grn_ctx *ctx, grn_ts_planner *planner, + grn_ts_sorter *sorter); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_sorter.c b/storage/mroonga/vendor/groonga/lib/ts/ts_sorter.c new file mode 100644 index 00000000..6a614663 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_sorter.c @@ -0,0 +1,2174 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_sorter.h" + +#include + +#include "ts_expr_parser.h" +#include "ts_log.h" +#include "ts_util.h" + +/*------------------------------------------------------------- + * grn_ts_sorter_node. + */ + +/* grn_ts_sorter_node_init() initializes a sorter node. */ +static void +grn_ts_sorter_node_init(grn_ctx *ctx, grn_ts_sorter_node *node) +{ + memset(node, 0, sizeof(*node)); + node->expr = NULL; + grn_ts_buf_init(ctx, &node->buf); + node->next = NULL; +} + +/* grn_ts_sorter_node_fin() finalizes a sorter node. */ +static void +grn_ts_sorter_node_fin(grn_ctx *ctx, grn_ts_sorter_node *node) +{ + grn_ts_buf_fin(ctx, &node->buf); + if (node->expr) { + grn_ts_expr_close(ctx, node->expr); + } +} + +/* grn_ts_sorter_node_open() creates a sorter nodes. */ +static grn_rc +grn_ts_sorter_node_open(grn_ctx *ctx, grn_ts_expr *expr, grn_ts_bool reverse, + grn_ts_sorter_node **node) +{ + grn_ts_sorter_node *new_node; + new_node = GRN_MALLOCN(grn_ts_sorter_node, 1); + if (!new_node) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_sorter_node)); + } + grn_ts_sorter_node_init(ctx, new_node); + new_node->expr = expr; + new_node->reverse = reverse; + *node = new_node; + return GRN_SUCCESS; +} + +/* grn_ts_sorter_node_close() destroys a sorter node. */ +static void +grn_ts_sorter_node_close(grn_ctx *ctx, grn_ts_sorter_node *node) +{ + grn_ts_sorter_node_fin(ctx, node); + GRN_FREE(node); +} + +/* grn_ts_sorter_node_list_close() destroys a linked list of sorter nodes. */ +static void +grn_ts_sorter_node_list_close(grn_ctx *ctx, grn_ts_sorter_node *head) +{ + grn_ts_sorter_node *node = head; + while (node) { + grn_ts_sorter_node *next = node->next; + grn_ts_sorter_node_close(ctx, node); + node = next; + } +} + +/* grn_ts_sorter_node_progress() progresses sorting. */ +static grn_rc +grn_ts_sorter_node_progress(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs, size_t *n_rest) +{ + // TODO + return GRN_FUNCTION_NOT_IMPLEMENTED; +} + +/* grn_ts_sorter_node_complete() completes sorting. */ +static grn_rc +grn_ts_sorter_node_complete(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs, size_t *n_rest) +{ + // TODO + return GRN_FUNCTION_NOT_IMPLEMENTED; +} + +/* Forward declarations. */ +static grn_rc +grn_ts_sorter_node_sort(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs); + +/* grn_ts_rec_swap() swaps records. */ +inline static void +grn_ts_rec_swap(grn_ts_record *lhs, grn_ts_record *rhs) +{ + grn_ts_record tmp = *lhs; + *lhs = *rhs; + *rhs = tmp; +} + +/* grn_ts_int_swap() swaps Int values. */ +inline static void +grn_ts_int_swap(grn_ts_int *lhs, grn_ts_int *rhs) +{ + grn_ts_int tmp = *lhs; + *lhs = *rhs; + *rhs = tmp; +} + +/* FIXME: Sorting by _id does not assume ID duplicates. */ + +/* grn_ts_move_pivot_by_id_asc() moves the pivot to the front. */ +static void +grn_ts_move_pivot_by_id_asc(grn_ts_record *recs, size_t n_recs) +{ + /* Choose the median from recs[1], recs[n_recs / 2], and recs[n_recs - 2]. */ + size_t first = 1; + size_t middle = n_recs / 2; + size_t last = n_recs - 2; + if (recs[first].id < recs[middle].id) { + /* first < middle. */ + if (recs[middle].id < recs[last].id) { + /* first < middle < last */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + } else if (recs[first].id < recs[last].id) { + /* first < last < middle. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + } else { + /* last < first < middle. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + } + } else if (recs[last].id < recs[middle].id) { + /* last < middle < first. */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + } else if (recs[last].id < recs[first].id) { + /* middle < last < first. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + } else { + /* middle < first < last. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + } +} + +/* grn_ts_isort_by_id_asc() sorts records. */ +static grn_rc +grn_ts_isort_by_id_asc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + for (size_t i = 1; i < n_recs; ++i) { + for (size_t j = i; j > 0; --j) { + if (recs[j].id < recs[j - 1].id) { + grn_ts_rec_swap(&recs[j], &recs[j - 1]); + } else { + break; + } + } + } + return GRN_SUCCESS; +} + +/* grn_ts_qsort_by_id_asc() sorts records. */ +static grn_rc +grn_ts_qsort_by_id_asc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + grn_rc rc; + /* + * FIXME: Currently, the threshold is 16. + * This value should be optimized and replaced with a named constant. + */ + while (n_recs >= 16) { + grn_ts_record pivot; + size_t left, right; + grn_ts_move_pivot_by_id_asc(recs, n_recs); + pivot = recs[0]; + left = 1; + right = n_recs; + for ( ; ; ) { + /* Move prior records to left. */ + while (left < right) { + if (pivot.id < recs[left].id) { + break; + } + ++left; + } + while (left < right) { + --right; + if (recs[right].id < pivot.id) { + break; + } + } + if (left >= right) { + break; + } + grn_ts_rec_swap(&recs[left], &recs[right]); + ++left; + } + /* Move the pivot to the boundary. */ + --left; + grn_ts_rec_swap(&recs[0], &recs[left]); + /* + * Use a recursive call to sort the smaller group so that the recursion + * depth is less than log_2(n_recs). + */ + if (left < (n_recs - right)) { + if ((offset < left) && (left >= 2)) { + size_t next_limit = (limit < left) ? limit : left; + rc = grn_ts_qsort_by_id_asc(ctx, node, offset, next_limit, recs, left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (limit <= right) { + return GRN_SUCCESS; + } + recs += right; + n_recs -= right; + offset = (offset < right) ? 0 : (offset - right); + limit -= right; + } else { + if ((limit > right) && ((n_recs - right) >= 2)) { + size_t next_offset = (offset < right) ? 0 : (offset - right); + size_t next_limit = limit - right; + rc = grn_ts_qsort_by_id_asc(ctx, node, next_offset, next_limit, + recs + right, n_recs - right); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (offset >= left) { + return GRN_SUCCESS; + } + n_recs = left; + if (limit > left) { + limit = left; + } + } + } + if (n_recs >= 2) { + return grn_ts_isort_by_id_asc(ctx, node, offset, limit, recs, n_recs); + } + return GRN_SUCCESS; +} + +/* grn_ts_move_pivot_by_id_desc() moves the pivot to the front. */ +static void +grn_ts_move_pivot_by_id_desc(grn_ts_record *recs, size_t n_recs) +{ + /* Choose the median from recs[1], recs[n_recs / 2], and recs[n_recs - 2]. */ + size_t first = 1; + size_t middle = n_recs / 2; + size_t last = n_recs - 2; + if (recs[first].id > recs[middle].id) { + /* first > middle. */ + if (recs[middle].id > recs[last].id) { + /* first > middle > last */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + } else if (recs[first].id > recs[last].id) { + /* first > last > middle. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + } else { + /* last > first > middle. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + } + } else if (recs[last].id > recs[middle].id) { + /* last > middle > first. */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + } else if (recs[last].id > recs[first].id) { + /* middle > last > first. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + } else { + /* middle > first > last. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + } +} + +/* grn_ts_isort_by_id_desc() sorts records. */ +static grn_rc +grn_ts_isort_by_id_desc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + for (size_t i = 1; i < n_recs; ++i) { + for (size_t j = i; j > 0; --j) { + if (recs[j].id > recs[j - 1].id) { + grn_ts_rec_swap(&recs[j], &recs[j - 1]); + } else { + break; + } + } + } + return GRN_SUCCESS; +} + +/* grn_ts_qsort_by_id_desc() sorts records. */ +static grn_rc +grn_ts_qsort_by_id_desc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + grn_rc rc; + /* + * FIXME: Currently, the threshold is 16. + * This value should be optimized and replaced with a named constant. + */ + while (n_recs >= 16) { + grn_ts_record pivot; + size_t left, right; + grn_ts_move_pivot_by_id_desc(recs, n_recs); + pivot = recs[0]; + left = 1; + right = n_recs; + for ( ; ; ) { + /* Move prior records to left. */ + while (left < right) { + if (pivot.id > recs[left].id) { + break; + } + ++left; + } + while (left < right) { + --right; + if (recs[right].id > pivot.id) { + break; + } + } + if (left >= right) { + break; + } + grn_ts_rec_swap(&recs[left], &recs[right]); + ++left; + } + /* Move the pivot to the boundary. */ + --left; + grn_ts_rec_swap(&recs[0], &recs[left]); + /* + * Use a recursive call to sort the smaller group so that the recursion + * depth is less than log_2(n_recs). + */ + if (left < (n_recs - right)) { + if ((offset < left) && (left >= 2)) { + size_t next_limit = (limit < left) ? limit : left; + rc = grn_ts_qsort_by_id_desc(ctx, node, offset, next_limit, + recs, left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (limit <= right) { + return GRN_SUCCESS; + } + recs += right; + n_recs -= right; + offset = (offset < right) ? 0 : (offset - right); + limit -= right; + } else { + if ((limit > right) && ((n_recs - right) >= 2)) { + size_t next_offset = (offset < right) ? 0 : (offset - right); + size_t next_limit = limit - right; + rc = grn_ts_qsort_by_id_desc(ctx, node, next_offset, next_limit, + recs + right, n_recs - right); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (offset >= left) { + return GRN_SUCCESS; + } + n_recs = left; + if (limit > left) { + limit = left; + } + } + } + if (n_recs >= 2) { + return grn_ts_isort_by_id_desc(ctx, node, offset, limit, recs, n_recs); + } + return GRN_SUCCESS; +} + +/* grn_ts_sorter_node_sort_by_id() sorts records by _id. */ +static grn_rc +grn_ts_sorter_node_sort_by_id(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + if (node->reverse) { + return grn_ts_qsort_by_id_desc(ctx, node, offset, limit, recs, n_recs); + } else { + return grn_ts_qsort_by_id_asc(ctx, node, offset, limit, recs, n_recs); + } +} + +/* grn_ts_move_pivot_by_score_asc() moves the pivot to the front. */ +static void +grn_ts_move_pivot_by_score_asc(grn_ts_record *recs, size_t n_recs) +{ + /* Choose the median from recs[1], recs[n_recs / 2], and recs[n_recs - 2]. */ + size_t first = 1; + size_t middle = n_recs / 2; + size_t last = n_recs - 2; + if (recs[first].score < recs[middle].score) { + /* first < middle. */ + if (recs[middle].score < recs[last].score) { + /* first < middle < last */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + } else if (recs[first].score < recs[last].score) { + /* first < last < middle. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + } else { /* last < first < middle. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + } + } else if (recs[last].score < recs[middle].score) { + /* last < middle < first. */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + } else if (recs[last].score < recs[first].score) { + /* middle < last < first. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + } else { /* middle < first < last. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + } +} + +/* grn_ts_isort_by_score_asc() sorts records. */ +static grn_rc +grn_ts_isort_by_score_asc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + for (size_t i = 1; i < n_recs; ++i) { + for (size_t j = i; j > 0; --j) { + if (recs[j].score < recs[j - 1].score) { + grn_ts_rec_swap(&recs[j], &recs[j - 1]); + } else { + break; + } + } + } + /* Apply the next sorting if there are score duplicates. */ + if (node->next) { + grn_rc rc; + size_t begin = 0; + for (size_t i = 1; i < n_recs; ++i) { + if ((recs[i].score < recs[begin].score) || + (recs[i].score > recs[begin].score)) { + if ((i - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, i - begin, + recs + begin, i - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + begin = i; + } + } + if ((n_recs - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, n_recs - begin, + recs + begin, n_recs - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + return GRN_SUCCESS; +} + +/* grn_ts_qsort_by_score_asc() sorts records. */ +static grn_rc +grn_ts_qsort_by_score_asc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + grn_rc rc; + /* + * FIXME: Currently, the threshold is 16. + * This value should be optimized and replaced with a named constant. + */ + while (n_recs >= 16) { + grn_ts_record pivot; + size_t left, right; + size_t pivot_left, pivot_right; + grn_ts_move_pivot_by_score_asc(recs, n_recs); + pivot = recs[0]; + left = 1; + right = n_recs; + pivot_left = 1; + pivot_right = n_recs; + for ( ; ; ) { + /* + * Prior entries are moved to left. Less prior entries are moved to + * right. Entries which equal to the pivot are moved to the edges. + */ + while (left < right) { + if (pivot.score < recs[left].score) { + break; + } else if ((pivot.score <= recs[left].score) && + (pivot.score >= recs[left].score)) { + grn_ts_rec_swap(&recs[left], &recs[pivot_left]); + ++pivot_left; + } + ++left; + } + while (left < right) { + --right; + if (recs[right].score < pivot.score) { + break; + } else if ((recs[right].score <= pivot.score) && + (recs[right].score >= pivot.score)) { + --pivot_right; + grn_ts_rec_swap(&recs[right], &recs[pivot_right]); + } + } + if (left >= right) { + break; + } + grn_ts_rec_swap(&recs[left], &recs[right]); + ++left; + } + /* Move left pivot-equivalent entries to the left of the boundary. */ + while (pivot_left > 0) { + --pivot_left; + --left; + grn_ts_rec_swap(&recs[pivot_left], &recs[left]); + } + /* Move right pivot-equivalent entries to the right of the boundary. */ + while (pivot_right < n_recs) { + grn_ts_rec_swap(&recs[pivot_right], &recs[right]); + ++pivot_right; + ++right; + } + /* Apply the next sort condition to the pivot-equivalent recs. */ + if (node->next) { + if (((right - left) >= 2) && (offset < right) && (limit > left)) { + size_t next_offset = (offset < left) ? 0 : (offset - left); + size_t next_limit = ((limit > right) ? right : limit) - left; + rc = grn_ts_sorter_node_sort(ctx, node->next, next_offset, next_limit, + recs + left, right - left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + /* + * Use a recursive call to sort the smaller group so that the recursion + * depth is less than log_2(n_recs). + */ + if (left < (n_recs - right)) { + if ((offset < left) && (left >= 2)) { + size_t next_limit = (limit < left) ? limit : left; + rc = grn_ts_qsort_by_score_asc(ctx, node, offset, next_limit, + recs, left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (limit <= right) { + return GRN_SUCCESS; + } + recs += right; + n_recs -= right; + offset = (offset < right) ? 0 : (offset - right); + limit -= right; + } else { + if ((limit > right) && ((n_recs - right) >= 2)) { + size_t next_offset = (offset < right) ? 0 : (offset - right); + size_t next_limit = limit - right; + rc = grn_ts_qsort_by_score_asc(ctx, node, next_offset, next_limit, + recs + right, n_recs - right); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (offset >= left) { + return GRN_SUCCESS; + } + n_recs = left; + if (limit > left) { + limit = left; + } + } + } + if (n_recs >= 2) { + rc = grn_ts_isort_by_score_asc(ctx, node, offset, limit, recs, n_recs); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +/* grn_ts_move_pivot_by_score_desc() moves the pivot to the front. */ +static void +grn_ts_move_pivot_by_score_desc(grn_ts_record *recs, size_t n_recs) +{ + /* Choose the median from recs[1], recs[n_recs / 2], and recs[n_recs - 2]. */ + size_t first = 1; + size_t middle = n_recs / 2; + size_t last = n_recs - 2; + if (recs[first].score > recs[middle].score) { + /* first > middle. */ + if (recs[middle].score > recs[last].score) { + /* first > middle > last */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + } else if (recs[first].score > recs[last].score) { + /* first > last > middle. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + } else { /* last > first > middle. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + } + } else if (recs[last].score > recs[middle].score) { + /* last > middle > first. */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + } else if (recs[last].score > recs[first].score) { + /* middle > last > first. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + } else { /* middle > first > last. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + } +} + +/* grn_ts_isort_by_score_desc() sorts records. */ +static grn_rc +grn_ts_isort_by_score_desc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + for (size_t i = 1; i < n_recs; ++i) { + for (size_t j = i; j > 0; --j) { + if (recs[j].score > recs[j - 1].score) { + grn_ts_rec_swap(&recs[j], &recs[j - 1]); + } else { + break; + } + } + } + /* Apply the next sorting if there are score duplicates. */ + if (node->next) { + grn_rc rc; + size_t begin = 0; + for (size_t i = 1; i < n_recs; ++i) { + if ((recs[i].score < recs[begin].score) || + (recs[i].score > recs[begin].score)) { + if ((i - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, i - begin, + recs + begin, i - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + begin = i; + } + } + if ((n_recs - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, n_recs - begin, + recs + begin, n_recs - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + return GRN_SUCCESS; +} + +/* grn_ts_qsort_by_score_desc() sorts records. */ +static grn_rc +grn_ts_qsort_by_score_desc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + grn_rc rc; + /* + * FIXME: Currently, the threshold is 16. + * This value should be optimized and replaced with a named constant. + */ + while (n_recs >= 16) { + grn_ts_record pivot; + size_t left = 1, right = n_recs; + size_t pivot_left = 1, pivot_right = n_recs; + grn_ts_move_pivot_by_score_desc(recs, n_recs); + pivot = recs[0]; + for ( ; ; ) { + /* + * Prior entries are moved to left. Less prior entries are moved to + * right. Entries which equal to the pivot are moved to the edges. + */ + while (left < right) { + if (pivot.score > recs[left].score) { + break; + } else if ((pivot.score <= recs[left].score) && + (pivot.score >= recs[left].score)) { + grn_ts_rec_swap(&recs[left], &recs[pivot_left]); + ++pivot_left; + } + ++left; + } + while (left < right) { + --right; + if (recs[right].score > pivot.score) { + break; + } else if ((recs[right].score <= pivot.score) && + (recs[right].score >= pivot.score)) { + --pivot_right; + grn_ts_rec_swap(&recs[right], &recs[pivot_right]); + } + } + if (left >= right) { + break; + } + grn_ts_rec_swap(&recs[left], &recs[right]); + ++left; + } + /* Move left pivot-equivalent entries to the left of the boundary. */ + while (pivot_left > 0) { + --pivot_left; + --left; + grn_ts_rec_swap(&recs[pivot_left], &recs[left]); + } + /* Move right pivot-equivalent entries to the right of the boundary. */ + while (pivot_right < n_recs) { + grn_ts_rec_swap(&recs[pivot_right], &recs[right]); + ++pivot_right; + ++right; + } + /* Apply the next sort condition to the pivot-equivalent recs. */ + if (node->next) { + if (((right - left) >= 2) && (offset < right) && (limit > left)) { + size_t next_offset = (offset < left) ? 0 : (offset - left); + size_t next_limit = ((limit > right) ? right : limit) - left; + rc = grn_ts_sorter_node_sort(ctx, node->next, next_offset, next_limit, + recs + left, right - left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + /* + * Use a recursive call to sort the smaller group so that the recursion + * depth is less than log_2(n_recs). + */ + if (left < (n_recs - right)) { + if ((offset < left) && (left >= 2)) { + size_t next_limit = (limit < left) ? limit : left; + rc = grn_ts_qsort_by_score_desc(ctx, node, offset, next_limit, + recs, left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (limit <= right) { + return GRN_SUCCESS; + } + recs += right; + n_recs -= right; + offset = (offset < right) ? 0 : (offset - right); + limit -= right; + } else { + if ((limit > right) && ((n_recs - right) >= 2)) { + size_t next_offset = (offset < right) ? 0 : (offset - right); + size_t next_limit = limit - right; + rc = grn_ts_qsort_by_score_desc(ctx, node, next_offset, next_limit, + recs + right, n_recs - right); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (offset >= left) { + return GRN_SUCCESS; + } + n_recs = left; + if (limit > left) { + limit = left; + } + } + } + if (n_recs >= 2) { + rc = grn_ts_isort_by_score_desc(ctx, node, offset, limit, recs, n_recs); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +/* grn_ts_sorter_node_sort_by_score() sorts records by _score. */ +static grn_rc +grn_ts_sorter_node_sort_by_score(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + if (node->reverse) { + return grn_ts_qsort_by_score_desc(ctx, node, offset, limit, recs, n_recs); + } else { + return grn_ts_qsort_by_score_asc(ctx, node, offset, limit, recs, n_recs); + } +} + +/* grn_ts_move_pivot_by_int() moves the pivot to the front. */ +static void +grn_ts_move_pivot_by_int(grn_ts_sorter_node *node, grn_ts_int *vals, + grn_ts_record *recs, size_t n_recs) +{ + /* Choose the median from recs[1], recs[n_recs / 2], and recs[n_recs - 2]. */ + size_t first = 1; + size_t middle = n_recs / 2; + size_t last = n_recs - 2; + if (vals[first] < vals[middle]) { + /* first < middle. */ + if (vals[middle] < vals[last]) { + /* first < middle < last */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + grn_ts_int_swap(&vals[0], &vals[middle]); + } else if (vals[first] < vals[last]) { + /* first < last < middle. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + grn_ts_int_swap(&vals[0], &vals[last]); + } else { /* last < first < middle. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + grn_ts_int_swap(&vals[0], &vals[first]); + } + } else if (vals[last] < vals[middle]) { + /* last < middle < first. */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + grn_ts_int_swap(&vals[0], &vals[middle]); + } else if (vals[last] < vals[first]) { + /* middle < last < first. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + grn_ts_int_swap(&vals[0], &vals[last]); + } else { /* middle < first < last. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + grn_ts_int_swap(&vals[0], &vals[first]); + } +} + +/* grn_ts_isort_by_int() sorts records. */ +static grn_rc +grn_ts_isort_by_int(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_int *vals, grn_ts_record *recs, size_t n_recs) +{ + for (size_t i = 1; i < n_recs; ++i) { + for (size_t j = i; j > 0; --j) { + if (vals[j] < vals[j - 1]) { + grn_ts_rec_swap(&recs[j], &recs[j - 1]); + grn_ts_int_swap(&vals[j], &vals[j - 1]); + } else { + break; + } + } + } + /* Apply the next sorting if there are score duplicates. */ + if (node->next) { + grn_rc rc; + size_t begin = 0; + for (size_t i = 1; i < n_recs; ++i) { + if (vals[i] != vals[begin]) { + if ((i - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, i - begin, + recs + begin, i - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + begin = i; + } + } + if ((n_recs - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, n_recs - begin, + recs + begin, n_recs - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + return GRN_SUCCESS; +} + +/* grn_ts_qsort_by_int() sorts records. */ +static grn_rc +grn_ts_qsort_by_int(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_int *vals, grn_ts_record *recs, size_t n_recs) +{ + grn_rc rc; + /* + * FIXME: Currently, the threshold is 16. + * This value should be optimized and replaced with a named constant. + */ + while (n_recs >= 16) { + grn_ts_int pivot; + size_t left, right; + size_t pivot_left, pivot_right; + grn_ts_move_pivot_by_int(node, vals, recs, n_recs); + pivot = vals[0]; + left = 1; + right = n_recs; + pivot_left = 1; + pivot_right = n_recs; + for ( ; ; ) { + /* + * Prior entries are moved to left. Less prior entries are moved to + * right. Entries which equal to the pivot are moved to the edges. + */ + while (left < right) { + if (pivot < vals[left]) { + break; + } else if (pivot == vals[left]) { + grn_ts_rec_swap(&recs[left], &recs[pivot_left]); + grn_ts_int_swap(&vals[left], &vals[pivot_left]); + ++pivot_left; + } + ++left; + } + while (left < right) { + --right; + if (vals[right] < pivot) { + break; + } else if (vals[right] == pivot) { + --pivot_right; + grn_ts_rec_swap(&recs[right], &recs[pivot_right]); + grn_ts_int_swap(&vals[right], &vals[pivot_right]); + } + } + if (left >= right) { + break; + } + grn_ts_rec_swap(&recs[left], &recs[right]); + grn_ts_int_swap(&vals[left], &vals[right]); + ++left; + } + /* Move left pivot-equivalent entries to the left of the boundary. */ + while (pivot_left > 0) { + --pivot_left; + --left; + grn_ts_rec_swap(&recs[pivot_left], &recs[left]); + grn_ts_int_swap(&vals[pivot_left], &vals[left]); + } + /* Move right pivot-equivalent entries to the right of the boundary. */ + while (pivot_right < n_recs) { + grn_ts_rec_swap(&recs[pivot_right], &recs[right]); + grn_ts_int_swap(&vals[pivot_right], &vals[right]); + ++pivot_right; + ++right; + } + /* Apply the next sort condition to the pivot-equivalent recs. */ + if (node->next) { + if (((right - left) >= 2) && (offset < right) && (limit > left)) { + size_t next_offset = (offset < left) ? 0 : (offset - left); + size_t next_limit = ((limit > right) ? right : limit) - left; + rc = grn_ts_sorter_node_sort(ctx, node->next, next_offset, next_limit, + recs + left, right - left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + /* + * Use a recursive call to sort the smaller group so that the recursion + * depth is less than log_2(n_recs). + */ + if (left < (n_recs - right)) { + if ((offset < left) && (left >= 2)) { + size_t next_limit = (limit < left) ? limit : left; + rc = grn_ts_qsort_by_int(ctx, node, offset, next_limit, + vals, recs, left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (limit <= right) { + return GRN_SUCCESS; + } + vals += right; + recs += right; + n_recs -= right; + offset = (offset < right) ? 0 : (offset - right); + limit -= right; + } else { + if ((limit > right) && ((n_recs - right) >= 2)) { + size_t next_offset = (offset < right) ? 0 : (offset - right); + size_t next_limit = limit - right; + rc = grn_ts_qsort_by_int(ctx, node, next_offset, next_limit, + vals + right, recs + right, n_recs - right); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (offset >= left) { + return GRN_SUCCESS; + } + n_recs = left; + if (limit > left) { + limit = left; + } + } + } + if (n_recs >= 2) { + rc = grn_ts_isort_by_int(ctx, node, offset, limit, vals, recs, n_recs); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +/* grn_ts_text_cmp() compares Text values. */ +inline static int +grn_ts_text_cmp(grn_ts_text lhs, grn_ts_text rhs) +{ + size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; + int result = memcmp(lhs.ptr, rhs.ptr, min_size); + if (result != 0) { + return result; + } + if (lhs.size == rhs.size) { + return 0; + } + return (lhs.size < rhs.size) ? -1 : 1; +} + +/* grn_ts_text_swap() swaps Text values. */ +inline static void +grn_ts_text_swap(grn_ts_text *lhs, grn_ts_text *rhs) +{ + grn_ts_text tmp = *lhs; + *lhs = *rhs; + *rhs = tmp; +} + +#if 0 +/* grn_ts_move_pivot_by_text_asc() moves the pivot to the front. */ +static void +grn_ts_move_pivot_by_text_asc(grn_ts_sorter_node *node, grn_ts_text *vals, + grn_ts_record *recs, size_t n_recs) +{ + /* Choose the median from recs[1], recs[n_recs / 2], and recs[n_recs - 2]. */ + size_t first = 1; + size_t middle = n_recs / 2; + size_t last = n_recs - 2; + if (grn_ts_text_cmp(vals[first], vals[middle]) < 0) { + /* first < middle. */ + if (grn_ts_text_cmp(vals[middle], vals[last]) < 0) { + /* first < middle < last */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + grn_ts_text_swap(&vals[0], &vals[middle]); + } else if (grn_ts_text_cmp(vals[first], vals[last]) < 0) { + /* first < last < middle. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + grn_ts_text_swap(&vals[0], &vals[last]); + } else { /* last < first < middle. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + grn_ts_text_swap(&vals[0], &vals[first]); + } + } else if (grn_ts_text_cmp(vals[last], vals[middle]) < 0) { + /* last < middle < first. */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + grn_ts_text_swap(&vals[0], &vals[middle]); + } else if (grn_ts_text_cmp(vals[last], vals[first]) < 0) { + /* middle < last < first. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + grn_ts_text_swap(&vals[0], &vals[last]); + } else { /* middle < first < last. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + grn_ts_text_swap(&vals[0], &vals[first]); + } +} + +/* grn_ts_isort_by_text_asc() sorts records. */ +static grn_rc +grn_ts_isort_by_text_asc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_text *vals, grn_ts_record *recs, size_t n_recs) +{ + for (size_t i = 1; i < n_recs; ++i) { + for (size_t j = i; j > 0; --j) { + if (grn_ts_text_cmp(vals[j], vals[j - 1]) < 0) { + grn_ts_rec_swap(&recs[j], &recs[j - 1]); + grn_ts_text_swap(&vals[j], &vals[j - 1]); + } else { + break; + } + } + } + /* Apply the next sorting if there are score duplicates. */ + if (node->next) { + grn_rc rc; + size_t begin = 0; + for (size_t i = 1; i < n_recs; ++i) { + if (grn_ts_text_cmp(vals[i], vals[begin]) != 0) { + if ((i - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, i - begin, + recs + begin, i - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + begin = i; + } + } + if ((n_recs - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, n_recs - begin, + recs + begin, n_recs - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + return GRN_SUCCESS; +} + +/* grn_ts_qsort_by_text_asc() sorts records. */ +static grn_rc +grn_ts_qsort_by_text_asc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_text *vals, grn_ts_record *recs, size_t n_recs) +{ + grn_rc rc; + /* + * FIXME: Currently, the threshold is 16. + * This value should be optimized and replaced with a named constant. + */ + while (n_recs >= 16) { + grn_ts_move_pivot_by_text_asc(node, vals, recs, n_recs); + grn_ts_text pivot = vals[0]; + size_t left = 1, right = n_recs; + size_t pivot_left = 1, pivot_right = n_recs; + for ( ; ; ) { + /* + * Prior entries are moved to left. Less prior entries are moved to + * right. Entries which equal to the pivot are moved to the edges. + */ + while (left < right) { + int result = grn_ts_text_cmp(pivot, vals[left]); + if (result < 0) { + break; + } else if (result == 0) { + grn_ts_rec_swap(&recs[left], &recs[pivot_left]); + grn_ts_text_swap(&vals[left], &vals[pivot_left]); + ++pivot_left; + } + ++left; + } + while (left < right) { + int result; + --right; + result = grn_ts_text_cmp(vals[right], pivot); + if (result < 0) { + break; + } else if (result == 0) { + --pivot_right; + grn_ts_rec_swap(&recs[right], &recs[pivot_right]); + grn_ts_text_swap(&vals[right], &vals[pivot_right]); + } + } + if (left >= right) { + break; + } + grn_ts_rec_swap(&recs[left], &recs[right]); + grn_ts_text_swap(&vals[left], &vals[right]); + ++left; + } + /* Move left pivot-equivalent entries to the left of the boundary. */ + while (pivot_left > 0) { + --pivot_left; + --left; + grn_ts_rec_swap(&recs[pivot_left], &recs[left]); + grn_ts_text_swap(&vals[pivot_left], &vals[left]); + } + /* Move right pivot-equivalent entries to the right of the boundary. */ + while (pivot_right < n_recs) { + grn_ts_rec_swap(&recs[pivot_right], &recs[right]); + grn_ts_text_swap(&vals[pivot_right], &vals[right]); + ++pivot_right; + ++right; + } + /* Apply the next sort condition to the pivot-equivalent recs. */ + if (node->next) { + if (((right - left) >= 2) && (offset < right) && (limit > left)) { + size_t next_offset = (offset < left) ? 0 : (offset - left); + size_t next_limit = ((limit > right) ? right : limit) - left; + rc = grn_ts_sorter_node_sort(ctx, node->next, next_offset, next_limit, + recs + left, right - left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + /* + * Use a recursive call to sort the smaller group so that the recursion + * depth is less than log_2(n_recs). + */ + if (left < (n_recs - right)) { + if ((offset < left) && (left >= 2)) { + size_t next_limit = (limit < left) ? limit : left; + rc = grn_ts_qsort_by_text_asc(ctx, node, offset, next_limit, + vals, recs, left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (limit <= right) { + return GRN_SUCCESS; + } + vals += right; + recs += right; + n_recs -= right; + offset = (offset < right) ? 0 : (offset - right); + limit -= right; + } else { + if ((limit > right) && ((n_recs - right) >= 2)) { + size_t next_offset = (offset < right) ? 0 : (offset - right); + size_t next_limit = limit - right; + rc = grn_ts_qsort_by_text_asc(ctx, node, next_offset, next_limit, + vals + right, recs + right, + n_recs - right); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (offset >= left) { + return GRN_SUCCESS; + } + n_recs = left; + if (limit > left) { + limit = left; + } + } + } + if (n_recs >= 2) { + rc = grn_ts_isort_by_text_asc(ctx, node, offset, limit, + vals, recs, n_recs); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} +#endif + +/* grn_ts_move_pivot_by_text_desc() moves the pivot to the front. */ +static void +grn_ts_move_pivot_by_text_desc(grn_ts_sorter_node *node, grn_ts_text *vals, + grn_ts_record *recs, size_t n_recs) +{ + /* Choose the median from recs[1], recs[n_recs / 2], and recs[n_recs - 2]. */ + size_t first = 1; + size_t middle = n_recs / 2; + size_t last = n_recs - 2; + if (grn_ts_text_cmp(vals[first], vals[middle]) > 0) { + /* first < middle. */ + if (grn_ts_text_cmp(vals[middle], vals[last]) > 0) { + /* first < middle < last */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + grn_ts_text_swap(&vals[0], &vals[middle]); + } else if (grn_ts_text_cmp(vals[first], vals[last]) > 0) { + /* first < last < middle. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + grn_ts_text_swap(&vals[0], &vals[last]); + } else { /* last < first < middle. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + grn_ts_text_swap(&vals[0], &vals[first]); + } + } else if (grn_ts_text_cmp(vals[last], vals[middle]) > 0) { + /* last < middle < first. */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + grn_ts_text_swap(&vals[0], &vals[middle]); + } else if (grn_ts_text_cmp(vals[last], vals[first]) > 0) { + /* middle < last < first. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + grn_ts_text_swap(&vals[0], &vals[last]); + } else { /* middle < first < last. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + grn_ts_text_swap(&vals[0], &vals[first]); + } +} + +/* grn_ts_isort_by_text_desc() sorts records. */ +static grn_rc +grn_ts_isort_by_text_desc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_text *vals, grn_ts_record *recs, + size_t n_recs) +{ + for (size_t i = 1; i < n_recs; ++i) { + for (size_t j = i; j > 0; --j) { + if (grn_ts_text_cmp(vals[j], vals[j - 1]) > 0) { + grn_ts_rec_swap(&recs[j], &recs[j - 1]); + grn_ts_text_swap(&vals[j], &vals[j - 1]); + } else { + break; + } + } + } + /* Apply the next sorting if there are score duplicates. */ + if (node->next) { + grn_rc rc; + size_t begin = 0; + for (size_t i = 1; i < n_recs; ++i) { + if (grn_ts_text_cmp(vals[i], vals[begin]) != 0) { + if ((i - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, i - begin, + recs + begin, i - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + begin = i; + } + } + if ((n_recs - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, n_recs - begin, + recs + begin, n_recs - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + return GRN_SUCCESS; +} + +/* grn_ts_qsort_by_text_desc() sorts records. */ +static grn_rc +grn_ts_qsort_by_text_desc(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_text *vals, grn_ts_record *recs, + size_t n_recs) +{ + grn_rc rc; + /* + * FIXME: Currently, the threshold is 16. + * This value should be optimized and replaced with a named constant. + */ + while (n_recs >= 16) { + grn_ts_text pivot; + size_t left, right; + size_t pivot_left, pivot_right; + grn_ts_move_pivot_by_text_desc(node, vals, recs, n_recs); + pivot = vals[0]; + left = 1; + right = n_recs; + pivot_left = 1; + pivot_right = n_recs; + for ( ; ; ) { + /* + * Prior entries are moved to left. Less prior entries are moved to + * right. Entries which equal to the pivot are moved to the edges. + */ + while (left < right) { + int result = grn_ts_text_cmp(pivot, vals[left]); + if (result > 0) { + break; + } else if (result == 0) { + grn_ts_rec_swap(&recs[left], &recs[pivot_left]); + grn_ts_text_swap(&vals[left], &vals[pivot_left]); + ++pivot_left; + } + ++left; + } + while (left < right) { + int result; + --right; + result = grn_ts_text_cmp(vals[right], pivot); + if (result > 0) { + break; + } else if (result == 0) { + --pivot_right; + grn_ts_rec_swap(&recs[right], &recs[pivot_right]); + grn_ts_text_swap(&vals[right], &vals[pivot_right]); + } + } + if (left >= right) { + break; + } + grn_ts_rec_swap(&recs[left], &recs[right]); + grn_ts_text_swap(&vals[left], &vals[right]); + ++left; + } + /* Move left pivot-equivalent entries to the left of the boundary. */ + while (pivot_left > 0) { + --pivot_left; + --left; + grn_ts_rec_swap(&recs[pivot_left], &recs[left]); + grn_ts_text_swap(&vals[pivot_left], &vals[left]); + } + /* Move right pivot-equivalent entries to the right of the boundary. */ + while (pivot_right < n_recs) { + grn_ts_rec_swap(&recs[pivot_right], &recs[right]); + grn_ts_text_swap(&vals[pivot_right], &vals[right]); + ++pivot_right; + ++right; + } + /* Apply the next sort condition to the pivot-equivalent recs. */ + if (node->next) { + if (((right - left) >= 2) && (offset < right) && (limit > left)) { + size_t next_offset = (offset < left) ? 0 : (offset - left); + size_t next_limit = ((limit > right) ? right : limit) - left; + rc = grn_ts_sorter_node_sort(ctx, node->next, next_offset, next_limit, + recs + left, right - left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + /* + * Use a recursive call to sort the smaller group so that the recursion + * depth is less than log_2(n_recs). + */ + if (left < (n_recs - right)) { + if ((offset < left) && (left >= 2)) { + size_t next_limit = (limit < left) ? limit : left; + rc = grn_ts_qsort_by_text_desc(ctx, node, offset, next_limit, + vals, recs, left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (limit <= right) { + return GRN_SUCCESS; + } + vals += right; + recs += right; + n_recs -= right; + offset = (offset < right) ? 0 : (offset - right); + limit -= right; + } else { + if ((limit > right) && ((n_recs - right) >= 2)) { + size_t next_offset = (offset < right) ? 0 : (offset - right); + size_t next_limit = limit - right; + rc = grn_ts_qsort_by_text_desc(ctx, node, next_offset, next_limit, + vals + right, recs + right, + n_recs - right); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (offset >= left) { + return GRN_SUCCESS; + } + n_recs = left; + if (limit > left) { + limit = left; + } + } + } + if (n_recs >= 2) { + rc = grn_ts_isort_by_text_desc(ctx, node, offset, limit, + vals, recs, n_recs); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +/* grn_ts_text_get_label() returns a label. */ +inline static int +grn_ts_text_get_label(grn_ts_text val, size_t depth) +{ + return (depth < val.size) ? (uint8_t)val.ptr[depth] : -1; +} + +/* grn_ts_text_cmp2() compares Text values. */ +inline static int +grn_ts_text_cmp2(grn_ts_text lhs, grn_ts_text rhs, size_t depth) +{ + size_t min_size = (lhs.size < rhs.size) ? lhs.size : rhs.size; + int result = memcmp(lhs.ptr + depth, rhs.ptr + depth, min_size - depth); + if (result != 0) { + return result; + } + if (lhs.size == rhs.size) { + return 0; + } + return (lhs.size < rhs.size) ? -1 : 1; +} + +/* grn_ts_move_pivot_by_text_asc2() moves the pivot to the front. */ +static void +grn_ts_move_pivot_by_text_asc2(grn_ts_sorter_node *node, grn_ts_text *vals, + grn_ts_record *recs, size_t n_recs, size_t depth) +{ + /* Choose the median from recs[1], recs[n_recs / 2], and recs[n_recs - 2]. */ + size_t first = 1; + size_t middle = n_recs / 2; + size_t last = n_recs - 2; + int first_label = grn_ts_text_get_label(vals[first], depth); + int middle_label = grn_ts_text_get_label(vals[middle], depth); + int last_label = grn_ts_text_get_label(vals[last], depth); + if (first_label < middle_label) { + /* first < middle. */ + if (middle_label < last_label) { + /* first < middle < last */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + grn_ts_text_swap(&vals[0], &vals[middle]); + } else if (first_label < last_label) { + /* first < last < middle. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + grn_ts_text_swap(&vals[0], &vals[last]); + } else { /* last < first < middle. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + grn_ts_text_swap(&vals[0], &vals[first]); + } + } else if (last_label < middle_label) { + /* last < middle < first. */ + grn_ts_rec_swap(&recs[0], &recs[middle]); + grn_ts_text_swap(&vals[0], &vals[middle]); + } else if (last_label < first_label) { + /* middle < last < first. */ + grn_ts_rec_swap(&recs[0], &recs[last]); + grn_ts_text_swap(&vals[0], &vals[last]); + } else { /* middle < first < last. */ + grn_ts_rec_swap(&recs[0], &recs[first]); + grn_ts_text_swap(&vals[0], &vals[first]); + } +} + +/* grn_ts_isort_by_text_asc2() sorts records. */ +static grn_rc +grn_ts_isort_by_text_asc2(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, grn_ts_text *vals, + grn_ts_record *recs, size_t n_recs, size_t depth) +{ + for (size_t i = 1; i < n_recs; ++i) { + for (size_t j = i; j > 0; --j) { + if (grn_ts_text_cmp2(vals[j], vals[j - 1], depth) < 0) { + grn_ts_rec_swap(&recs[j], &recs[j - 1]); + grn_ts_text_swap(&vals[j], &vals[j - 1]); + } else { + break; + } + } + } + /* Apply the next sorting if there are score duplicates. */ + if (node->next) { + grn_rc rc; + size_t begin = 0; + for (size_t i = 1; i < n_recs; ++i) { + if (grn_ts_text_cmp2(vals[i], vals[begin], depth) != 0) { + if ((i - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, i - begin, + recs + begin, i - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + begin = i; + } + } + if ((n_recs - begin) >= 2) { + rc = grn_ts_sorter_node_sort(ctx, node->next, 0, n_recs - begin, + recs + begin, n_recs - begin); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + return GRN_SUCCESS; +} + +/* grn_ts_qsort_by_text_asc() sorts records. */ +static grn_rc +grn_ts_qsort_by_text_asc2(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, grn_ts_text *vals, + grn_ts_record *recs, size_t n_recs, size_t depth) +{ + grn_rc rc; + /* + * FIXME: Currently, the threshold is 16. + * This value should be optimized and replaced with a named constant. + */ + while (n_recs >= 16) { + int pivot; + size_t left, right; + size_t pivot_left, pivot_right; + grn_ts_move_pivot_by_text_asc2(node, vals, recs, n_recs, depth); + pivot = grn_ts_text_get_label(vals[0], depth); + left = 1; + right = n_recs; + pivot_left = 1; + pivot_right = n_recs; + for ( ; ; ) { + /* + * Prior entries are moved to left. Less prior entries are moved to + * right. Entries which equal to the pivot are moved to the edges. + */ + while (left < right) { + int label = grn_ts_text_get_label(vals[left], depth); + if (label > pivot) { + break; + } else if (label == pivot) { + grn_ts_rec_swap(&recs[left], &recs[pivot_left]); + grn_ts_text_swap(&vals[left], &vals[pivot_left]); + ++pivot_left; + } + ++left; + } + while (left < right) { + int label; + --right; + label = grn_ts_text_get_label(vals[right], depth); + if (label < pivot) { + break; + } else if (label == pivot) { + --pivot_right; + grn_ts_rec_swap(&recs[right], &recs[pivot_right]); + grn_ts_text_swap(&vals[right], &vals[pivot_right]); + } + } + if (left >= right) { + break; + } + grn_ts_rec_swap(&recs[left], &recs[right]); + grn_ts_text_swap(&vals[left], &vals[right]); + ++left; + } + /* Move left pivot-equivalent entries to the left of the boundary. */ + while (pivot_left > 0) { + --pivot_left; + --left; + grn_ts_rec_swap(&recs[pivot_left], &recs[left]); + grn_ts_text_swap(&vals[pivot_left], &vals[left]); + } + /* Move right pivot-equivalent entries to the right of the boundary. */ + while (pivot_right < n_recs) { + grn_ts_rec_swap(&recs[pivot_right], &recs[right]); + grn_ts_text_swap(&vals[pivot_right], &vals[right]); + ++pivot_right; + ++right; + } + /* Apply the next sort condition to the pivot-equivalent recs. */ + if (((right - left) >= 2) && (offset < right) && (limit > left)) { + size_t next_offset = (offset < left) ? 0 : (offset - left); + size_t next_limit = ((limit > right) ? right : limit) - left; + if (pivot != -1) { + rc = grn_ts_qsort_by_text_asc2(ctx, node, next_offset, next_limit, + vals, recs + left, right - left, + depth + 1); + } else if (node->next) { + rc = grn_ts_sorter_node_sort(ctx, node->next, next_offset, next_limit, + recs + left, right - left); + if (rc != GRN_SUCCESS) { + return rc; + } + } + } + /* + * Use a recursive call to sort the smaller group so that the recursion + * depth is less than log_2(n_recs). + */ + if (left < (n_recs - right)) { + if ((offset < left) && (left >= 2)) { + size_t next_limit = (limit < left) ? limit : left; + rc = grn_ts_qsort_by_text_asc2(ctx, node, offset, next_limit, + vals, recs, left, depth); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (limit <= right) { + return GRN_SUCCESS; + } + vals += right; + recs += right; + n_recs -= right; + offset = (offset < right) ? 0 : (offset - right); + limit -= right; + } else { + if ((limit > right) && ((n_recs - right) >= 2)) { + size_t next_offset = (offset < right) ? 0 : (offset - right); + size_t next_limit = limit - right; + rc = grn_ts_qsort_by_text_asc2(ctx, node, next_offset, next_limit, + vals + right, recs + right, + n_recs - right, depth); + if (rc != GRN_SUCCESS) { + return rc; + } + } + if (offset >= left) { + return GRN_SUCCESS; + } + n_recs = left; + if (limit > left) { + limit = left; + } + } + } + if (n_recs >= 2) { + rc = grn_ts_isort_by_text_asc2(ctx, node, offset, limit, + vals, recs, n_recs, depth); + if (rc != GRN_SUCCESS) { + return rc; + } + } + return GRN_SUCCESS; +} + +/* grn_ts_sorter_node_sort_by_var() sorts records. */ +static grn_rc +grn_ts_sorter_node_sort_by_var(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + size_t i; + grn_rc rc; + switch (node->expr->data_kind) { + case GRN_TS_INT: { + grn_ts_int *vals; + rc = grn_ts_expr_evaluate_to_buf(ctx, node->expr, recs, n_recs, + &node->buf); + if (rc != GRN_SUCCESS) { + return rc; + } + vals = (grn_ts_int *)node->buf.ptr; + if (node->reverse) { + for (i = 0; i < n_recs; i++) { + vals[i] = -1 - vals[i]; + } + } + return grn_ts_qsort_by_int(ctx, node, offset, limit, vals, recs, n_recs); + } + case GRN_TS_FLOAT: { + grn_ts_int *vals; + rc = grn_ts_expr_evaluate_to_buf(ctx, node->expr, recs, n_recs, + &node->buf); + if (rc != GRN_SUCCESS) { + return rc; + } + vals = (grn_ts_int *)node->buf.ptr; + if (node->reverse) { + for (i = 0; i < n_recs; i++) { + if (vals[i] < 0) { + vals[i] = (vals[i] ^ INT64_MAX) + 1; + } + vals[i] = -1 - vals[i]; + } + } else { + for (i = 0; i < n_recs; i++) { + if (vals[i] < 0) { + vals[i] = (vals[i] ^ INT64_MAX) + 1; + } + } + } + return grn_ts_qsort_by_int(ctx, node, offset, limit, vals, recs, n_recs); + } + case GRN_TS_TIME: { + grn_ts_int *vals; + rc = grn_ts_expr_evaluate_to_buf(ctx, node->expr, recs, n_recs, + &node->buf); + if (rc != GRN_SUCCESS) { + return rc; + } + vals = (grn_ts_int *)node->buf.ptr; + if (node->reverse) { + for (i = 0; i < n_recs; i++) { + vals[i] = -1 - vals[i]; + } + } + return grn_ts_qsort_by_int(ctx, node, offset, limit, vals, recs, n_recs); + } + case GRN_TS_TEXT: { + grn_ts_text *vals; + rc = grn_ts_expr_evaluate_to_buf(ctx, node->expr, recs, n_recs, + &node->buf); + if (rc != GRN_SUCCESS) { + return rc; + } + vals = (grn_ts_text *)node->buf.ptr; + if (node->reverse) { + return grn_ts_qsort_by_text_desc(ctx, node, offset, limit, + vals, recs, n_recs); + } else { + return grn_ts_qsort_by_text_asc2(ctx, node, offset, limit, + vals, recs, n_recs, 0); + } + } + case GRN_TS_INT_VECTOR: + case GRN_TS_FLOAT_VECTOR: + case GRN_TS_TIME_VECTOR: + case GRN_TS_TEXT_VECTOR: { + // TODO + GRN_TS_ERR_RETURN(GRN_OPERATION_NOT_SUPPORTED, "not supported yet"); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid data kind: %d", + node->expr->data_kind); + } + } + return GRN_FUNCTION_NOT_IMPLEMENTED; +} + +/* grn_ts_sorter_node_sort() sorts records. */ +static grn_rc +grn_ts_sorter_node_sort(grn_ctx *ctx, grn_ts_sorter_node *node, + size_t offset, size_t limit, + grn_ts_record *recs, size_t n_recs) +{ + switch (node->expr->type) { + case GRN_TS_EXPR_ID: { + return grn_ts_sorter_node_sort_by_id(ctx, node, offset, limit, + recs, n_recs); + } + case GRN_TS_EXPR_SCORE: { + return grn_ts_sorter_node_sort_by_score(ctx, node, offset, limit, + recs, n_recs); + } + case GRN_TS_EXPR_CONST: { + if (!node->next) { + return GRN_SUCCESS; + } + return grn_ts_sorter_node_sort(ctx, node->next, offset, limit, recs, + n_recs); + } + case GRN_TS_EXPR_VARIABLE: { + return grn_ts_sorter_node_sort_by_var(ctx, node, offset, limit, + recs, n_recs); + break; + } + default: { + GRN_TS_ERR_RETURN(GRN_OBJECT_CORRUPT, "invalid expr type: %d", + node->expr->type); + } + } +} + +/*------------------------------------------------------------- + * grn_ts_sorter. + */ + +static void +grn_ts_sorter_init(grn_ctx *ctx, grn_ts_sorter *sorter) +{ + memset(sorter, 0, sizeof(*sorter)); + sorter->table = NULL; + sorter->head = NULL; +} + +static void +grn_ts_sorter_fin(grn_ctx *ctx, grn_ts_sorter *sorter) +{ + if (sorter->head) { + grn_ts_sorter_node_list_close(ctx, sorter->head); + } + if (sorter->table) { + grn_obj_unlink(ctx, sorter->table); + } +} + +grn_rc +grn_ts_sorter_open(grn_ctx *ctx, grn_obj *table, grn_ts_sorter_node *head, + size_t offset, size_t limit, grn_ts_sorter **sorter) +{ + grn_rc rc; + grn_ts_sorter *new_sorter; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || !head || !sorter) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + new_sorter = GRN_MALLOCN(grn_ts_sorter, 1); + if (!new_sorter) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_sorter)); + } + rc = grn_ts_obj_increment_ref_count(ctx, table); + if (rc != GRN_SUCCESS) { + GRN_FREE(new_sorter); + return rc; + } + grn_ts_sorter_init(ctx, new_sorter); + new_sorter->table = table; + new_sorter->head = head; + new_sorter->offset = offset; + new_sorter->limit = limit; + /* FIXME: Enable partial sorting. */ +/* new_sorter->partial = (offset + limit) < 1000;*/ + *sorter = new_sorter; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_sorter_parse(grn_ctx *ctx, grn_obj *table, + grn_ts_str str, size_t offset, + size_t limit, grn_ts_sorter **sorter) +{ + grn_rc rc; + grn_ts_sorter *new_sorter = NULL; + grn_ts_expr_parser *parser; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || !str.size || !sorter) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_expr_parser_open(ctx, table, &parser); + if (rc == GRN_SUCCESS) { + grn_ts_sorter_builder *builder; + rc = grn_ts_sorter_builder_open(ctx, table, &builder); + if (rc == GRN_SUCCESS) { + grn_ts_str first, rest = str; + for ( ; ; ) { + grn_ts_expr *expr; + grn_ts_bool reverse = GRN_FALSE; + rc = grn_ts_expr_parser_split(ctx, parser, rest, &first, &rest); + if (rc == GRN_END_OF_DATA) { + rc = grn_ts_sorter_builder_complete(ctx, builder, offset, limit, + &new_sorter); + break; + } else if (rc != GRN_SUCCESS) { + break; + } + if (first.ptr[0] == '-') { + reverse = GRN_TRUE; + first.ptr++; + first.size--; + } + rc = grn_ts_expr_parser_parse(ctx, parser, first, &expr); + if (rc != GRN_SUCCESS) { + break; + } + rc = grn_ts_sorter_builder_push(ctx, builder, expr, reverse); + if (rc != GRN_SUCCESS) { + grn_ts_expr_close(ctx, expr); + break; + } + } + grn_ts_sorter_builder_close(ctx, builder); + } + grn_ts_expr_parser_close(ctx, parser); + } + if (rc != GRN_SUCCESS) { + return rc; + } + *sorter = new_sorter; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_sorter_close(grn_ctx *ctx, grn_ts_sorter *sorter) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!sorter) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + grn_ts_sorter_fin(ctx, sorter); + GRN_FREE(sorter); + return GRN_SUCCESS; +} + +grn_rc +grn_ts_sorter_progress(grn_ctx *ctx, grn_ts_sorter *sorter, + grn_ts_record *recs, size_t n_recs, size_t *n_rest) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!sorter || (!recs && n_recs) || !n_rest) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + if (sorter->partial) { + return grn_ts_sorter_node_progress(ctx, sorter->head, sorter->offset, + sorter->limit, recs, n_recs, n_rest); + } + return GRN_SUCCESS; +} + +grn_rc +grn_ts_sorter_complete(grn_ctx *ctx, grn_ts_sorter *sorter, + grn_ts_record *recs, size_t n_recs, size_t *n_rest) +{ + grn_rc rc; + size_t i, limit; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!sorter || (!recs && n_recs) || !n_rest) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + if (sorter->offset >= n_recs) { + return GRN_SUCCESS; + } + limit = sorter->limit; + if (limit > (n_recs - sorter->offset)) { + limit = n_recs; + } else { + limit += sorter->offset; + } + if (sorter->partial) { + // FIXME: If there was no input. Partial sorting is not required. + rc = grn_ts_sorter_node_progress(ctx, sorter->head, sorter->offset, + limit, recs, n_recs, n_rest); + if (rc == GRN_SUCCESS) { + rc = grn_ts_sorter_node_complete(ctx, sorter->head, sorter->offset, + limit, recs, n_recs, n_rest); + } + } else { + rc = grn_ts_sorter_node_sort(ctx, sorter->head, sorter->offset, + limit, recs, n_recs); + } + if (rc != GRN_SUCCESS) { + return rc; + } + if (sorter->offset) { + for (i = 0; i < limit; i++) { + recs[i] = recs[sorter->offset + i]; + } + } + *n_rest = limit; + return GRN_SUCCESS; +} + +/*------------------------------------------------------------- + * grn_ts_sorter_builder. + */ + +/* grn_ts_sorter_builder_init() initializes a sorter builder. */ +static void +grn_ts_sorter_builder_init(grn_ctx *ctx, grn_ts_sorter_builder *builder) +{ + memset(builder, 0, sizeof(*builder)); + builder->table = NULL; + builder->head = NULL; + builder->tail = NULL; +} + +/* grn_ts_sorter_builder_fin() finalizes a sorter builder. */ +static void +grn_ts_sorter_builder_fin(grn_ctx *ctx, grn_ts_sorter_builder *builder) +{ + if (builder->head) { + grn_ts_sorter_node_list_close(ctx, builder->head); + } + if (builder->table) { + grn_obj_unlink(ctx, builder->table); + } +} + +grn_rc +grn_ts_sorter_builder_open(grn_ctx *ctx, grn_obj *table, + grn_ts_sorter_builder **builder) +{ + grn_rc rc; + grn_ts_sorter_builder *new_builder; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!table || !grn_ts_obj_is_table(ctx, table) || !builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + new_builder = GRN_MALLOCN(grn_ts_sorter_builder, 1); + if (!new_builder) { + GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, + "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x 1", + sizeof(grn_ts_sorter_builder)); + } + grn_ts_sorter_builder_init(ctx, new_builder); + rc = grn_ts_obj_increment_ref_count(ctx, table); + if (rc != GRN_SUCCESS) { + grn_ts_sorter_builder_fin(ctx, new_builder); + GRN_FREE(new_builder); + return rc; + } + new_builder->table = table; + *builder = new_builder; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_sorter_builder_close(grn_ctx *ctx, grn_ts_sorter_builder *builder) +{ + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + grn_ts_sorter_builder_fin(ctx, builder); + GRN_FREE(builder); + return GRN_SUCCESS; +} + +grn_rc +grn_ts_sorter_builder_complete(grn_ctx *ctx, grn_ts_sorter_builder *builder, + size_t offset, size_t limit, + grn_ts_sorter **sorter) +{ + grn_rc rc; + grn_ts_sorter *new_sorter; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || !builder->head || !sorter) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + rc = grn_ts_sorter_open(ctx, builder->table, builder->head, + offset, limit, &new_sorter); + if (rc != GRN_SUCCESS) { + return rc; + } + builder->head = NULL; + builder->tail = NULL; + *sorter = new_sorter; + return GRN_SUCCESS; +} + +grn_rc +grn_ts_sorter_builder_push(grn_ctx *ctx, grn_ts_sorter_builder *builder, + grn_ts_expr *expr, grn_ts_bool reverse) +{ + grn_rc rc; + grn_ts_sorter_node *new_node; + if (!ctx) { + return GRN_INVALID_ARGUMENT; + } + if (!builder || !expr || expr->table != builder->table) { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + switch (expr->data_kind) { + case GRN_TS_INT: + case GRN_TS_FLOAT: + case GRN_TS_TIME: + case GRN_TS_TEXT: { + break; + } + case GRN_TS_INT_VECTOR: + case GRN_TS_FLOAT_VECTOR: + case GRN_TS_TIME_VECTOR: + case GRN_TS_TEXT_VECTOR: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "not supported yet"); + } + default: { + GRN_TS_ERR_RETURN(GRN_INVALID_ARGUMENT, "invalid argument"); + } + } + rc = grn_ts_sorter_node_open(ctx, expr, reverse, &new_node); + if (rc != GRN_SUCCESS) { + return rc; + } + if (builder->tail) { + builder->tail->next = new_node; + } else { + builder->head = new_node; + } + builder->tail = new_node; + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_sorter.h b/storage/mroonga/vendor/groonga/lib/ts/ts_sorter.h new file mode 100644 index 00000000..d80479e1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_sorter.h @@ -0,0 +1,98 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#include "ts_expr.h" +#include "ts_str.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* TODO: Sorting should take into account the order of input records. */ + +typedef struct grn_ts_sorter_node { + grn_ts_expr *expr; /* Expression. */ + grn_ts_bool reverse; /* Reverse order or not. */ + grn_ts_buf buf; /* Buffer for values. */ + struct grn_ts_sorter_node *next; /* Next node. */ +} grn_ts_sorter_node; + +typedef struct { + grn_obj *table; /* Table. */ + grn_ts_sorter_node *head; /* First node. */ + size_t offset; /* Top `offset` records will be discarded. */ + size_t limit; /* At most `limit` records will be left. */ + grn_ts_bool partial; /* Partial sorting or not. */ +} grn_ts_sorter; + +/* grn_ts_sorter_open() creates a sorter. */ +grn_rc grn_ts_sorter_open(grn_ctx *ctx, grn_obj *table, + grn_ts_sorter_node *head, size_t offset, + size_t limit, grn_ts_sorter **sorter); + +/* grn_ts_sorter_parse() parses a string and creates a sorter. */ +grn_rc grn_ts_sorter_parse(grn_ctx *ctx, grn_obj *table, + grn_ts_str str, size_t offset, + size_t limit, grn_ts_sorter **sorter); + +/* grn_ts_sorter_close() destroys a sorter. */ +grn_rc grn_ts_sorter_close(grn_ctx *ctx, grn_ts_sorter *sorter); + +/* grn_ts_sorter_progress() progresses sorting. */ +grn_rc grn_ts_sorter_progress(grn_ctx *ctx, grn_ts_sorter *sorter, + grn_ts_record *recs, size_t n_recs, + size_t *n_rest); + +/* grn_ts_sorter_complete() completes sorting. */ +grn_rc grn_ts_sorter_complete(grn_ctx *ctx, grn_ts_sorter *sorter, + grn_ts_record *recs, size_t n_recs, + size_t *n_rest); + +typedef struct { + grn_obj *table; /* Table. */ + grn_ts_sorter_node *head; /* First node. */ + grn_ts_sorter_node *tail; /* Last node. */ +} grn_ts_sorter_builder; + +/* grn_ts_sorter_builder_open() creates a sorter builder. */ +grn_rc grn_ts_sorter_builder_open(grn_ctx *ctx, grn_obj *table, + grn_ts_sorter_builder **builder); + +/* grn_ts_sorter_builder_close() destroys a sorter builder. */ +grn_rc grn_ts_sorter_builder_close(grn_ctx *ctx, + grn_ts_sorter_builder *builder); + +/* grn_ts_sorter_builder_complete() completes a sorter. */ +grn_rc grn_ts_sorter_builder_complete(grn_ctx *ctx, + grn_ts_sorter_builder *builder, + size_t offset, size_t limit, + grn_ts_sorter **sorter); + +/* grn_ts_sorter_builder_push() pushes a node. */ +grn_rc grn_ts_sorter_builder_push(grn_ctx *ctx, grn_ts_sorter_builder *builder, + grn_ts_expr *expr, grn_ts_bool reverse); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_str.c b/storage/mroonga/vendor/groonga/lib/ts/ts_str.c new file mode 100644 index 00000000..9f200fa3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_str.c @@ -0,0 +1,191 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_str.h" + +#include +#include + +/*------------------------------------------------------------- + * Byte. + */ + +grn_ts_bool +grn_ts_byte_is_decimal(uint8_t byte) +{ + return (byte >= '0') && (byte <= '9'); +} + +grn_ts_bool +grn_ts_byte_is_name_char(uint8_t byte) +{ + /* + * Note: A table name allows '#', '@' and '-'. + * http://groonga.org/docs/reference/commands/table_create.html#name + */ + if (((byte >= '0') && (byte <= '9')) || ((byte >= 'A') && (byte <= 'Z')) || + ((byte >= 'a') && (byte <= 'z')) || (byte == '_')) { + return GRN_TRUE; + } + return GRN_FALSE; +} + +/*------------------------------------------------------------- + * String. + */ + +grn_ts_bool +grn_ts_str_starts_with(grn_ts_str str, grn_ts_str prefix) +{ + if (str.size < prefix.size) { + return GRN_FALSE; + } + return !memcmp(str.ptr, prefix.ptr, prefix.size); +} + +grn_ts_str +grn_ts_str_trim_left(grn_ts_str str) +{ + size_t i; + for (i = 0; i < str.size; i++) { + if (!isspace((uint8_t)str.ptr[i])) { + break; + } + } + str.ptr += i; + str.size -= i; + return str; +} + +grn_ts_str +grn_ts_str_trim_score_assignment(grn_ts_str str) +{ + grn_ts_str rest; + str = grn_ts_str_trim_left(str); + if (!grn_ts_str_starts_with(str, (grn_ts_str){ "_score", 6 })) { + return str; + } + rest.ptr = str.ptr + 6; + rest.size = str.size - 6; + rest = grn_ts_str_trim_left(rest); + if (!rest.size || (rest.ptr[0] != '=') || + ((rest.size >= 2) && (rest.ptr[1] == '='))) { + return str; + } + rest.ptr++; + rest.size--; + return grn_ts_str_trim_left(rest); +} + +grn_ts_bool +grn_ts_str_has_number_prefix(grn_ts_str str) +{ + if (!str.size) { + return GRN_FALSE; + } + if (grn_ts_byte_is_decimal(str.ptr[0])) { + return GRN_TRUE; + } + if (str.size == 1) { + return GRN_FALSE; + } + switch (str.ptr[0]) { + case '+': case '-': { + if (grn_ts_byte_is_decimal(str.ptr[1])) { + return GRN_TRUE; + } + if (str.size == 2) { + return GRN_FALSE; + } + return (str.ptr[1] == '.') && grn_ts_byte_is_decimal(str.ptr[2]); + } + case '.': { + return grn_ts_byte_is_decimal(str.ptr[1]); + } + default: { + return GRN_FALSE; + } + } +} + +grn_ts_bool +grn_ts_str_is_name_prefix(grn_ts_str str) +{ + size_t i; + for (i = 0; i < str.size; i++) { + if (!grn_ts_byte_is_name_char(str.ptr[i])) { + return GRN_FALSE; + } + } + return GRN_TRUE; +} + +grn_ts_bool +grn_ts_str_is_name(grn_ts_str str) +{ + if (!str.size) { + return GRN_FALSE; + } + return grn_ts_str_is_name_prefix(str); +} + +grn_ts_bool +grn_ts_str_is_true(grn_ts_str str) +{ + return (str.size == 4) && !memcmp(str.ptr, "true", 4); +} + +grn_ts_bool +grn_ts_str_is_false(grn_ts_str str) +{ + return (str.size == 5) && !memcmp(str.ptr, "false", 5); +} + +grn_ts_bool +grn_ts_str_is_bool(grn_ts_str str) +{ + return grn_ts_str_is_true(str) || grn_ts_str_is_false(str); +} + +grn_ts_bool +grn_ts_str_is_id_name(grn_ts_str str) +{ + return (str.size == GRN_COLUMN_NAME_ID_LEN) && + !memcmp(str.ptr, GRN_COLUMN_NAME_ID, GRN_COLUMN_NAME_ID_LEN); +} + +grn_ts_bool +grn_ts_str_is_score_name(grn_ts_str str) +{ + return (str.size == GRN_COLUMN_NAME_SCORE_LEN) && + !memcmp(str.ptr, GRN_COLUMN_NAME_SCORE, GRN_COLUMN_NAME_SCORE_LEN); +} + +grn_ts_bool +grn_ts_str_is_key_name(grn_ts_str str) +{ + return (str.size == GRN_COLUMN_NAME_KEY_LEN) && + !memcmp(str.ptr, GRN_COLUMN_NAME_KEY, GRN_COLUMN_NAME_KEY_LEN); +} + +grn_ts_bool +grn_ts_str_is_value_name(grn_ts_str str) +{ + return (str.size == GRN_COLUMN_NAME_VALUE_LEN) && + !memcmp(str.ptr, GRN_COLUMN_NAME_VALUE, GRN_COLUMN_NAME_VALUE_LEN); +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_str.h b/storage/mroonga/vendor/groonga/lib/ts/ts_str.h new file mode 100644 index 00000000..11371233 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_str.h @@ -0,0 +1,106 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*------------------------------------------------------------- + * Byte. + */ + +/* grn_ts_byte_is_decimal() returns whether or not a byte is decimal. */ +grn_ts_bool grn_ts_byte_is_decimal(uint8_t byte); + +/* + * grn_ts_byte_is_name_char() returns whether or not a byte is allowed as a + * part of a name. + */ +grn_ts_bool grn_ts_byte_is_name_char(uint8_t byte); + +/*------------------------------------------------------------- + * String. + */ + +typedef struct { + const char *ptr; /* The starting address. */ + size_t size; /* The size in bytes. */ +} grn_ts_str; + +/* grn_ts_str_has_prefix() returns whether or not str starts with prefix. */ +grn_ts_bool grn_ts_str_starts_with(grn_ts_str str, grn_ts_str prefix); + +/* grn_ts_str_trim_left() returns a string without leading white-spaces. */ +grn_ts_str grn_ts_str_trim_left(grn_ts_str str); + +/* + * grn_ts_str_trim_score_assignment() returns a string without leading + * white-spaces and an assignment to _score. If `str` does not start with + * an assignment, this function returns `grn_ts_str_trim_left(str)`. + */ +grn_ts_str grn_ts_str_trim_score_assignment(grn_ts_str str); + +/* + * grn_ts_str_has_number_prefix() returns whether or not a string starts with a + * number or not. + */ +grn_ts_bool grn_ts_str_has_number_prefix(grn_ts_str str); + +/* + * grn_ts_str_is_name_prefix() returns whether or not a string is valid as a + * name prefix. Note that an empty string is a name prefix. + */ +grn_ts_bool grn_ts_str_is_name_prefix(grn_ts_str str); + +/* + * grn_ts_str_is_name() returns whether or not a string is valid as a name. + * Note that an empty string is invalid as a name. + */ +grn_ts_bool grn_ts_str_is_name(grn_ts_str str); + +/* grn_ts_str_is_true() returns str == "true". */ +grn_ts_bool grn_ts_str_is_true(grn_ts_str str); + +/* grn_ts_str_is_false() returns str == "false". */ +grn_ts_bool grn_ts_str_is_false(grn_ts_str str); + +/* grn_ts_str_is_bool() returns (str == "true") || (str == "false"). */ +grn_ts_bool grn_ts_str_is_bool(grn_ts_str str); + +/* grn_ts_str_is_id_name() returns str == "_id". */ +grn_ts_bool grn_ts_str_is_id_name(grn_ts_str str); + +/* grn_ts_str_is_score_name() returns str == "_score". */ +grn_ts_bool grn_ts_str_is_score_name(grn_ts_str str); + +/* grn_ts_str_is_key_name() returns str == "_key". */ +grn_ts_bool grn_ts_str_is_key_name(grn_ts_str str); + +/* grn_ts_str_is_value_name() returns str == "_value". */ +grn_ts_bool grn_ts_str_is_value_name(grn_ts_str str); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_types.h b/storage/mroonga/vendor/groonga/lib/ts/ts_types.h new file mode 100644 index 00000000..389eec42 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_types.h @@ -0,0 +1,168 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*------------------------------------------------------------- + * Built-in data types. + */ + +/* grn_builtin_type or table ID. */ +typedef grn_id grn_ts_data_type; + +/* ID (_id). */ +typedef grn_id grn_ts_id; + +/* Score (_score). */ +typedef float grn_ts_score; + +/* Record (_id, _score). */ +typedef struct { + grn_ts_id id; + grn_ts_score score; +} grn_ts_record; + +/*------------------------------------------------------------- + * Built-in scalar data kinds. + */ + +/* Bool. */ +typedef grn_bool grn_ts_bool; + +/* Int. */ +typedef int64_t grn_ts_int; + +/* Float. */ +typedef double grn_ts_float; + +/* Time. */ +typedef int64_t grn_ts_time; + +/* Text. */ +typedef struct { + const char *ptr; + size_t size; +} grn_ts_text; + +/* Geo. */ +typedef grn_geo_point grn_ts_geo; +typedef grn_geo_point grn_ts_tokyo_geo; +typedef grn_geo_point grn_ts_wgs84_geo; + +/* Ref. */ +typedef grn_ts_record grn_ts_ref; + +/*------------------------------------------------------------- + * Built-in vector data kinds. + */ + +/* BoolVector. */ +typedef struct { + const grn_ts_bool *ptr; + size_t size; +} grn_ts_bool_vector; + +/* IntVector. */ +typedef struct { + const grn_ts_int *ptr; + size_t size; +} grn_ts_int_vector; + +/* FloatVector. */ +typedef struct { + const grn_ts_float *ptr; + size_t size; +} grn_ts_float_vector; + +/* TimeVector. */ +typedef struct { + const grn_ts_time *ptr; + size_t size; +} grn_ts_time_vector; + +/* TextVector. */ +typedef struct { + const grn_ts_text *ptr; + size_t size; +} grn_ts_text_vector; + +/* GeoVector. */ +typedef struct { + const grn_ts_geo *ptr; + size_t size; +} grn_ts_geo_vector; +typedef grn_ts_geo_vector grn_ts_tokyo_geo_vector; +typedef grn_ts_geo_vector grn_ts_wgs84_geo_vector; + +/* RefVector. */ +typedef struct { + const grn_ts_ref *ptr; + size_t size; +} grn_ts_ref_vector; + +/*------------------------------------------------------------- + * Built-in data kinds. + */ + +enum { GRN_TS_VECTOR_FLAG = 1 << 7 }; + +typedef enum { + GRN_TS_VOID = 0, /* GRN_DB_VOID */ + GRN_TS_BOOL = 1, /* GRN_DB_BOOL */ + GRN_TS_INT = 2, /* GRN_DB_[U]INT(8/16/32/64) */ + GRN_TS_FLOAT = 3, /* GRN_DB_FLOAT */ + GRN_TS_TIME = 4, /* GRN_DB_TIME */ + GRN_TS_TEXT = 5, /* GRN_DB_[SHORT_/LONG_]TEST */ + GRN_TS_GEO = 6, /* GRN_DB_(TOKYO/WGS84)_GEO_POINT */ + GRN_TS_REF = 7, /* Table reference. */ + GRN_TS_BOOL_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_BOOL, + GRN_TS_INT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_INT, + GRN_TS_FLOAT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_FLOAT, + GRN_TS_TIME_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_TIME, + GRN_TS_TEXT_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_TEXT, + GRN_TS_GEO_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_GEO, + GRN_TS_REF_VECTOR = GRN_TS_VECTOR_FLAG | GRN_TS_REF +} grn_ts_data_kind; + +typedef union { + grn_ts_bool as_bool; + grn_ts_int as_int; + grn_ts_float as_float; + grn_ts_time as_time; + grn_ts_text as_text; + grn_ts_geo as_geo; + grn_ts_ref as_ref; + grn_ts_bool_vector as_bool_vector; + grn_ts_int_vector as_int_vector; + grn_ts_float_vector as_float_vector; + grn_ts_time_vector as_time_vector; + grn_ts_text_vector as_text_vector; + grn_ts_geo_vector as_geo_vector; + grn_ts_ref_vector as_ref_vector; +} grn_ts_any; + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_util.c b/storage/mroonga/vendor/groonga/lib/ts/ts_util.c new file mode 100644 index 00000000..18e66060 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_util.c @@ -0,0 +1,129 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "ts_util.h" + +#include "../grn_dat.h" +#include "../grn_hash.h" +#include "../grn_pat.h" + +#include "ts_log.h" + +grn_rc +grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj) +{ + grn_id id = grn_obj_id(ctx, obj); + grn_obj *obj_clone = grn_ctx_at(ctx, id); + if (!obj_clone) { + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "grn_ctx_at failed: %d", id); + } + if (obj_clone != obj) { + grn_obj_unlink(ctx, obj_clone); + GRN_TS_ERR_RETURN(GRN_UNKNOWN_ERROR, "wrong object: %p != %p", + obj, obj_clone); + } + return GRN_SUCCESS; +} + +grn_ts_bool +grn_ts_obj_is_table(grn_ctx *ctx, grn_obj *obj) +{ + return grn_obj_is_table(ctx, obj); +} + +grn_ts_bool +grn_ts_obj_is_column(grn_ctx *ctx, grn_obj *obj) +{ + switch (obj->header.type) { + case GRN_COLUMN_FIX_SIZE: + case GRN_COLUMN_VAR_SIZE: { + return GRN_TRUE; + } + /* GRN_COLUMN_INDEX is not supported. */ + default: { + return GRN_FALSE; + } + } +} + +grn_rc +grn_ts_ja_get_value(grn_ctx *ctx, grn_obj *ja, grn_ts_id id, + grn_ts_buf *buf, size_t *value_size) +{ + grn_rc rc; + uint32_t size; + grn_io_win iw; + char *ptr = (char *)grn_ja_ref(ctx, (grn_ja *)ja, id, &iw, &size); + if (!ptr) { + if (value_size) { + *value_size = 0; + } + return GRN_SUCCESS; + } + rc = grn_ts_buf_write(ctx, buf, ptr, size); + grn_ja_unref(ctx, &iw); + if (rc != GRN_SUCCESS) { + return rc; + } + if (value_size) { + *value_size = size; + } + return GRN_SUCCESS; +} + +grn_ts_bool +grn_ts_table_has_key(grn_ctx *ctx, grn_obj *table) +{ + switch (table->header.type) { + case GRN_TABLE_HASH_KEY: + case GRN_TABLE_PAT_KEY: + case GRN_TABLE_DAT_KEY: { + return GRN_TRUE; + } + default: { + return GRN_FALSE; + } + } +} + +grn_ts_bool +grn_ts_table_has_value(grn_ctx *ctx, grn_obj *table) +{ + return DB_OBJ(table)->range != GRN_DB_VOID; +} + +const void * +grn_ts_table_get_value(grn_ctx *ctx, grn_obj *table, grn_ts_id id) +{ + switch (table->header.type) { + case GRN_TABLE_HASH_KEY: { + return grn_hash_get_value_(ctx, (grn_hash *)table, id, NULL); + } + case GRN_TABLE_PAT_KEY: { + uint32_t size; + return grn_pat_get_value_(ctx, (grn_pat *)table, id, &size); + } + /* GRN_TABLE_DAT_KEY does not support _value. */ + case GRN_TABLE_NO_KEY: { + return _grn_array_get_value(ctx, (grn_array *)table, id); + } + default: { + return NULL; + } + } +} diff --git a/storage/mroonga/vendor/groonga/lib/ts/ts_util.h b/storage/mroonga/vendor/groonga/lib/ts/ts_util.h new file mode 100644 index 00000000..24a6a507 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/ts/ts_util.h @@ -0,0 +1,61 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#pragma once + +#include "../grn.h" + +#include "ts_buf.h" +#include "ts_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* grn_ts_obj_increment_ref_count() increments an object reference count. */ +grn_rc grn_ts_obj_increment_ref_count(grn_ctx *ctx, grn_obj *obj); + +/* grn_ts_obj_is_table() returns whether or not an object is a table. */ +grn_ts_bool grn_ts_obj_is_table(grn_ctx *ctx, grn_obj *obj); + +/* grn_ts_obj_is_column() returns whether or not an object is a column. */ +grn_ts_bool grn_ts_obj_is_column(grn_ctx *ctx, grn_obj *obj); + +/* + * grn_ts_ja_get_value() gets a value from ja and writes it to buf. Note that + * the value is appended to the end of buf. + */ +grn_rc grn_ts_ja_get_value(grn_ctx *ctx, grn_obj *ja, grn_ts_id id, + grn_ts_buf *buf, size_t *value_size); + +/* grn_ts_table_has_key() returns whether or not a table has _key. */ +grn_ts_bool grn_ts_table_has_key(grn_ctx *ctx, grn_obj *table); + +/* grn_ts_table_has_value() returns whether or not a table has _value. */ +grn_ts_bool grn_ts_table_has_value(grn_ctx *ctx, grn_obj *table); + +/* + * grn_ts_table_get_value() gets a reference to a value (_value). On failure, + * this function returns NULL. + */ +const void *grn_ts_table_get_value(grn_ctx *ctx, grn_obj *table, grn_ts_id id); + +#ifdef __cplusplus +} +#endif + diff --git a/storage/mroonga/vendor/groonga/lib/type.c b/storage/mroonga/vendor/groonga/lib/type.c new file mode 100644 index 00000000..6696444a --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/type.c @@ -0,0 +1,87 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2009-2016 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_ctx_impl.h" +#include "grn_db.h" + +grn_bool +grn_type_id_is_builtin(grn_ctx *ctx, grn_id id) +{ + return id >= GRN_DB_OBJECT && id <= GRN_DB_WGS84_GEO_POINT; +} + +grn_bool +grn_type_id_is_number_family(grn_ctx *ctx, grn_id id) +{ + return GRN_DB_INT8 <= id && id <= GRN_DB_FLOAT; +} + +grn_bool +grn_type_id_is_text_family(grn_ctx *ctx, grn_id id) +{ + return GRN_DB_SHORT_TEXT <= id && id <= GRN_DB_LONG_TEXT; +} + +grn_obj * +grn_type_create(grn_ctx *ctx, const char *name, unsigned int name_size, + grn_obj_flags flags, unsigned int size) +{ + grn_id id; + struct _grn_type *res = NULL; + grn_obj *db; + if (!ctx || !ctx->impl || !(db = ctx->impl->db)) { + ERR(GRN_INVALID_ARGUMENT, "db not initialized"); + return NULL; + } + GRN_API_ENTER; + if (grn_db_check_name(ctx, name, name_size)) { + GRN_DB_CHECK_NAME_ERR("[type][create]", name, name_size); + GRN_API_RETURN(NULL); + } + if (!GRN_DB_P(db)) { + ERR(GRN_INVALID_ARGUMENT, "invalid db assigned"); + GRN_API_RETURN(NULL); + } + id = grn_obj_register(ctx, db, name, name_size); + if (id && (res = GRN_MALLOC(sizeof(grn_db_obj)))) { + GRN_DB_OBJ_SET_TYPE(res, GRN_TYPE); + res->obj.header.flags = flags; + res->obj.header.domain = GRN_ID_NIL; + GRN_TYPE_SIZE(&res->obj) = size; + if (grn_db_obj_init(ctx, db, id, DB_OBJ(res))) { + // grn_obj_delete(ctx, db, id); + GRN_FREE(res); + GRN_API_RETURN(NULL); + } + } + GRN_API_RETURN((grn_obj *)res); +} + +uint32_t +grn_type_size(grn_ctx *ctx, grn_obj *type) +{ + uint32_t size; + + GRN_API_ENTER; + if (!type) { + ERR(GRN_INVALID_ARGUMENT, "[type][size] type is NULL"); + GRN_API_RETURN(0); + } + size = GRN_TYPE_SIZE(DB_OBJ(type)); + GRN_API_RETURN(size); +} diff --git a/storage/mroonga/vendor/groonga/lib/util.c b/storage/mroonga/vendor/groonga/lib/util.c new file mode 100644 index 00000000..43066c3f --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/util.c @@ -0,0 +1,1643 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_db.h" +#include "grn_pat.h" +#include "grn_ii.h" +#include "grn_util.h" +#include "grn_string.h" +#include "grn_expr.h" +#include "grn_load.h" + +#include +#include +#include +#include +#include + +#ifdef WIN32 +# include +# include +#endif /* WIN32 */ + +grn_rc +grn_normalize_offset_and_limit(grn_ctx *ctx, int size, int *p_offset, int *p_limit) +{ + int end; + int offset = *p_offset; + int limit = *p_limit; + + if (offset < 0) { + offset += size; + if (offset < 0) { + *p_offset = 0; + *p_limit = 0; + return GRN_TOO_SMALL_OFFSET; + } + } else if (offset != 0 && offset >= size) { + *p_offset = 0; + *p_limit = 0; + return GRN_TOO_LARGE_OFFSET; + } + + if (limit < 0) { + limit += size + 1; + if (limit < 0) { + *p_offset = 0; + *p_limit = 0; + return GRN_TOO_SMALL_LIMIT; + } + } else if (limit > size) { + limit = size; + } + + /* At this point, offset and limit must be zero or positive. */ + end = offset + limit; + if (end > size) { + limit -= end - size; + } + *p_offset = offset; + *p_limit = limit; + return GRN_SUCCESS; +} + +grn_obj * +grn_inspect_name(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + int name_size; + + name_size = grn_obj_name(ctx, obj, NULL, 0); + if (name_size > 0) { + grn_bulk_space(ctx, buf, name_size); + grn_obj_name(ctx, obj, GRN_BULK_CURR(buf) - name_size, name_size); + } else { + grn_id id; + + id = grn_obj_id(ctx, obj); + if (id == GRN_ID_NIL) { + GRN_TEXT_PUTS(ctx, buf, "(nil)"); + } else { + GRN_TEXT_PUTS(ctx, buf, "(anonymous:"); + grn_text_lltoa(ctx, buf, id); + GRN_TEXT_PUTS(ctx, buf, ")"); + } + } + + return buf; +} + +grn_obj * +grn_inspect_encoding(grn_ctx *ctx, grn_obj *buf, grn_encoding encoding) +{ + switch (encoding) { + case GRN_ENC_DEFAULT : + GRN_TEXT_PUTS(ctx, buf, "default("); + grn_inspect_encoding(ctx, buf, grn_get_default_encoding()); + GRN_TEXT_PUTS(ctx, buf, ")"); + break; + case GRN_ENC_NONE : + GRN_TEXT_PUTS(ctx, buf, "none"); + break; + case GRN_ENC_EUC_JP : + GRN_TEXT_PUTS(ctx, buf, "EUC-JP"); + break; + case GRN_ENC_UTF8 : + GRN_TEXT_PUTS(ctx, buf, "UTF-8"); + break; + case GRN_ENC_SJIS : + GRN_TEXT_PUTS(ctx, buf, "Shift_JIS"); + break; + case GRN_ENC_LATIN1 : + GRN_TEXT_PUTS(ctx, buf, "Latin-1"); + break; + case GRN_ENC_KOI8R : + GRN_TEXT_PUTS(ctx, buf, "KOI8-R"); + break; + default : + GRN_TEXT_PUTS(ctx, buf, "unknown("); + grn_text_itoa(ctx, buf, encoding); + GRN_TEXT_PUTS(ctx, buf, ")"); + break; + } + + return buf; +} + +grn_obj * +grn_inspect_type(grn_ctx *ctx, grn_obj *buf, unsigned char type) +{ + switch (type) { + case GRN_VOID : + GRN_TEXT_PUTS(ctx, buf, "GRN_VOID"); + break; + case GRN_BULK : + GRN_TEXT_PUTS(ctx, buf, "GRN_BULK"); + break; + case GRN_PTR : + GRN_TEXT_PUTS(ctx, buf, "GRN_PTR"); + break; + case GRN_UVECTOR : + GRN_TEXT_PUTS(ctx, buf, "GRN_UVECTOR"); + break; + case GRN_PVECTOR : + GRN_TEXT_PUTS(ctx, buf, "GRN_PVECTOR"); + break; + case GRN_VECTOR : + GRN_TEXT_PUTS(ctx, buf, "GRN_VECTOR"); + break; + case GRN_MSG : + GRN_TEXT_PUTS(ctx, buf, "GRN_MSG"); + break; + case GRN_QUERY : + GRN_TEXT_PUTS(ctx, buf, "GRN_QUERY"); + break; + case GRN_ACCESSOR : + GRN_TEXT_PUTS(ctx, buf, "GRN_ACCESSOR"); + break; + case GRN_SNIP : + GRN_TEXT_PUTS(ctx, buf, "GRN_SNIP"); + break; + case GRN_PATSNIP : + GRN_TEXT_PUTS(ctx, buf, "GRN_PATSNIP"); + break; + case GRN_STRING : + GRN_TEXT_PUTS(ctx, buf, "GRN_STRING"); + break; + case GRN_CURSOR_TABLE_HASH_KEY : + GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_HASH_KEY"); + break; + case GRN_CURSOR_TABLE_PAT_KEY : + GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_PAT_KEY"); + break; + case GRN_CURSOR_TABLE_DAT_KEY : + GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_DAT_KEY"); + break; + case GRN_CURSOR_TABLE_NO_KEY : + GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_TABLE_NO_KEY"); + break; + case GRN_CURSOR_COLUMN_INDEX : + GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_COLUMN_INDEX"); + break; + case GRN_CURSOR_COLUMN_GEO_INDEX : + GRN_TEXT_PUTS(ctx, buf, "GRN_CURSOR_COLUMN_GEO_INDEX"); + break; + case GRN_TYPE : + GRN_TEXT_PUTS(ctx, buf, "GRN_TYPE"); + break; + case GRN_PROC : + GRN_TEXT_PUTS(ctx, buf, "GRN_PROC"); + break; + case GRN_EXPR : + GRN_TEXT_PUTS(ctx, buf, "GRN_EXPR"); + break; + case GRN_TABLE_HASH_KEY : + GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_HASH_KEY"); + break; + case GRN_TABLE_PAT_KEY : + GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_PAT_KEY"); + break; + case GRN_TABLE_DAT_KEY : + GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_DAT_KEY"); + break; + case GRN_TABLE_NO_KEY : + GRN_TEXT_PUTS(ctx, buf, "GRN_TABLE_NO_KEY"); + break; + case GRN_DB : + GRN_TEXT_PUTS(ctx, buf, "GRN_DB"); + break; + case GRN_COLUMN_FIX_SIZE : + GRN_TEXT_PUTS(ctx, buf, "GRN_COLUMN_FIX_SIZE"); + break; + case GRN_COLUMN_VAR_SIZE : + GRN_TEXT_PUTS(ctx, buf, "GRN_COLUMN_VAR_SIZE"); + break; + case GRN_COLUMN_INDEX : + GRN_TEXT_PUTS(ctx, buf, "GRN_COLUMN_INDEX"); + break; + default: + { +#define TYPE_IN_HEX_SIZE 5 /* "0xXX" */ + char type_in_hex[TYPE_IN_HEX_SIZE]; + grn_snprintf(type_in_hex, + TYPE_IN_HEX_SIZE, + TYPE_IN_HEX_SIZE, + "%#02x", type); +#undef TYPE_IN_HEX_SIZE + GRN_TEXT_PUTS(ctx, buf, "(unknown: "); + GRN_TEXT_PUTS(ctx, buf, type_in_hex); + GRN_TEXT_PUTS(ctx, buf, ")"); + } + break; + } + + return buf; +} + + +grn_obj * +grn_inspect_query_log_flags(grn_ctx *ctx, grn_obj *buffer, unsigned int flags) +{ + grn_bool have_content = GRN_FALSE; + + if (flags == GRN_QUERY_LOG_NONE) { + GRN_TEXT_PUTS(ctx, buffer, "NONE"); + return buffer; + } + +#define CHECK_FLAG(NAME) do { \ + if (flags & GRN_QUERY_LOG_ ## NAME) { \ + if (have_content) { \ + GRN_TEXT_PUTS(ctx, buffer, "|"); \ + } \ + GRN_TEXT_PUTS(ctx, buffer, #NAME); \ + have_content = GRN_TRUE; \ + } \ + } while (GRN_FALSE) + + CHECK_FLAG(COMMAND); + CHECK_FLAG(RESULT_CODE); + CHECK_FLAG(DESTINATION); + CHECK_FLAG(CACHE); + CHECK_FLAG(SIZE); + CHECK_FLAG(SCORE); + +#undef CHECK_FALG + + return buffer; +} + +static grn_rc +grn_proc_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_proc *proc = (grn_proc *)obj; + uint32_t i; + + GRN_TEXT_PUTS(ctx, buf, "#type) { + case GRN_PROC_INVALID : + GRN_TEXT_PUTS(ctx, buf, "invalid"); + GRN_TEXT_PUTS(ctx, buf, ">"); + return GRN_SUCCESS; + break; + case GRN_PROC_TOKENIZER : + GRN_TEXT_PUTS(ctx, buf, "tokenizer"); + break; + case GRN_PROC_COMMAND : + GRN_TEXT_PUTS(ctx, buf, "command"); + break; + case GRN_PROC_FUNCTION : + GRN_TEXT_PUTS(ctx, buf, "function"); + break; + case GRN_PROC_HOOK : + GRN_TEXT_PUTS(ctx, buf, "hook"); + break; + case GRN_PROC_NORMALIZER : + GRN_TEXT_PUTS(ctx, buf, "normalizer"); + break; + case GRN_PROC_TOKEN_FILTER : + GRN_TEXT_PUTS(ctx, buf, "token-filter"); + break; + case GRN_PROC_SCORER : + GRN_TEXT_PUTS(ctx, buf, "scorer"); + break; + case GRN_PROC_WINDOW_FUNCTION : + GRN_TEXT_PUTS(ctx, buf, "window-function"); + break; + } + GRN_TEXT_PUTS(ctx, buf, " "); + + grn_inspect_name(ctx, buf, obj); + GRN_TEXT_PUTS(ctx, buf, " "); + + GRN_TEXT_PUTS(ctx, buf, "arguments:["); + for (i = 0; i < proc->nvars; i++) { + grn_expr_var *var = proc->vars + i; + if (i != 0) { + GRN_TEXT_PUTS(ctx, buf, ", "); + } + GRN_TEXT_PUT(ctx, buf, var->name, var->name_size); + } + GRN_TEXT_PUTS(ctx, buf, "]"); + + GRN_TEXT_PUTS(ctx, buf, ">"); + + return GRN_SUCCESS; +} + +grn_rc +grn_expr_code_inspect_indented(grn_ctx *ctx, + grn_obj *buffer, + grn_expr_code *code, + const char *indent) +{ + if (!code) { + GRN_TEXT_PUTS(ctx, buffer, "(NULL)"); + return GRN_SUCCESS; + } + + GRN_TEXT_PUTS(ctx, buffer, "<"); + GRN_TEXT_PUTS(ctx, buffer, grn_operator_to_string(code->op)); + GRN_TEXT_PUTS(ctx, buffer, " "); + GRN_TEXT_PUTS(ctx, buffer, "n_args:"); + grn_text_itoa(ctx, buffer, code->nargs); + GRN_TEXT_PUTS(ctx, buffer, ", "); + GRN_TEXT_PUTS(ctx, buffer, "flags:"); + grn_text_itoh(ctx, buffer, code->flags, 1); + GRN_TEXT_PUTS(ctx, buffer, ", "); + GRN_TEXT_PUTS(ctx, buffer, "modify:"); + grn_text_itoa(ctx, buffer, code->modify); + GRN_TEXT_PUTS(ctx, buffer, ", "); + GRN_TEXT_PUTS(ctx, buffer, "value:"); + grn_inspect_indented(ctx, buffer, code->value, " "); + GRN_TEXT_PUTS(ctx, buffer, ">"); + + return GRN_SUCCESS; +} + +grn_rc +grn_expr_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *expr) +{ + grn_expr *e = (grn_expr *)expr; + + GRN_TEXT_PUTS(ctx, buffer, "#codes; i < e->codes_curr; i++, code++) { + if (i) { GRN_TEXT_PUTC(ctx, buffer, ','); } + GRN_TEXT_PUTS(ctx, buffer, "\n "); + grn_text_itoa(ctx, buffer, i); + GRN_TEXT_PUTS(ctx, buffer, ":"); + grn_expr_code_inspect_indented(ctx, buffer, code, " "); + } + GRN_TEXT_PUTS(ctx, buffer, "\n }"); + } + + GRN_TEXT_PUTS(ctx, buffer, "\n>"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_ptr_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *ptr) +{ + size_t size; + + GRN_TEXT_PUTS(ctx, buffer, "#= sizeof(grn_obj *)) { + grn_obj *content = GRN_PTR_VALUE(ptr); + grn_inspect(ctx, buffer, content); + if (size > sizeof(grn_obj *)) { + grn_text_printf(ctx, buffer, + " (and more data: %" GRN_FMT_SIZE ")", + size - sizeof(grn_obj *)); + } + } + GRN_TEXT_PUTS(ctx, buffer, ">"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_pvector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *pvector) +{ + int i, n; + + GRN_TEXT_PUTS(ctx, buffer, "["); + n = GRN_BULK_VSIZE(pvector) / sizeof(grn_obj *); + for (i = 0; i < n; i++) { + grn_obj *element = GRN_PTR_VALUE_AT(pvector, i); + + if (i > 0) { + GRN_TEXT_PUTS(ctx, buffer, ", "); + } + + grn_inspect(ctx, buffer, element); + } + GRN_TEXT_PUTS(ctx, buffer, "]"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_vector_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *vector) +{ + int i; + grn_obj *body = vector->u.v.body; + + GRN_TEXT_PUTS(ctx, buffer, "["); + for (i = 0; i < vector->u.v.n_sections; i++) { + grn_section *section = &(vector->u.v.sections[i]); + const char *value_raw; + + if (i > 0) { + GRN_TEXT_PUTS(ctx, buffer, ", "); + } + + value_raw = GRN_BULK_HEAD(body) + section->offset; + GRN_TEXT_PUTS(ctx, buffer, "{"); + GRN_TEXT_PUTS(ctx, buffer, "\"value\":"); + { + grn_obj value_object; + GRN_OBJ_INIT(&value_object, GRN_BULK, GRN_OBJ_DO_SHALLOW_COPY, + section->domain); + GRN_TEXT_SET(ctx, &value_object, value_raw, section->length); + grn_inspect(ctx, buffer, &value_object); + GRN_OBJ_FIN(ctx, &value_object); + } + GRN_TEXT_PUTS(ctx, buffer, ", \"weight\":"); + grn_text_itoa(ctx, buffer, section->weight); + GRN_TEXT_PUTS(ctx, buffer, "}"); + } + GRN_TEXT_PUTS(ctx, buffer, "]"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_accessor_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_accessor *accessor = (grn_accessor *)obj; + + GRN_TEXT_PUTS(ctx, buf, "#next) { + grn_bool show_obj_name = GRN_FALSE; + grn_bool show_obj_domain_name = GRN_FALSE; + + if (accessor != (grn_accessor *)obj) { + GRN_TEXT_PUTS(ctx, buf, "."); + } + switch (accessor->action) { + case GRN_ACCESSOR_GET_ID : + GRN_TEXT_PUT(ctx, + buf, + GRN_COLUMN_NAME_ID, + GRN_COLUMN_NAME_ID_LEN); + show_obj_name = GRN_TRUE; + break; + case GRN_ACCESSOR_GET_KEY : + GRN_TEXT_PUT(ctx, + buf, + GRN_COLUMN_NAME_KEY, + GRN_COLUMN_NAME_KEY_LEN); + show_obj_name = GRN_TRUE; + break; + case GRN_ACCESSOR_GET_VALUE : + GRN_TEXT_PUT(ctx, + buf, + GRN_COLUMN_NAME_VALUE, + GRN_COLUMN_NAME_VALUE_LEN); + show_obj_name = GRN_TRUE; + break; + case GRN_ACCESSOR_GET_SCORE : + GRN_TEXT_PUT(ctx, + buf, + GRN_COLUMN_NAME_SCORE, + GRN_COLUMN_NAME_SCORE_LEN); + break; + case GRN_ACCESSOR_GET_NSUBRECS : + GRN_TEXT_PUT(ctx, + buf, + GRN_COLUMN_NAME_NSUBRECS, + GRN_COLUMN_NAME_NSUBRECS_LEN); + break; + case GRN_ACCESSOR_GET_MAX : + GRN_TEXT_PUT(ctx, + buf, + GRN_COLUMN_NAME_MAX, + GRN_COLUMN_NAME_MAX_LEN); + break; + case GRN_ACCESSOR_GET_MIN : + GRN_TEXT_PUT(ctx, + buf, + GRN_COLUMN_NAME_MIN, + GRN_COLUMN_NAME_MIN_LEN); + break; + case GRN_ACCESSOR_GET_SUM : + GRN_TEXT_PUT(ctx, + buf, + GRN_COLUMN_NAME_SUM, + GRN_COLUMN_NAME_SUM_LEN); + break; + case GRN_ACCESSOR_GET_AVG : + GRN_TEXT_PUT(ctx, + buf, + GRN_COLUMN_NAME_AVG, + GRN_COLUMN_NAME_AVG_LEN); + break; + case GRN_ACCESSOR_GET_COLUMN_VALUE : + grn_column_name_(ctx, accessor->obj, buf); + show_obj_domain_name = GRN_TRUE; + break; + case GRN_ACCESSOR_GET_DB_OBJ : + grn_text_printf(ctx, buf, "(_db)"); + break; + case GRN_ACCESSOR_LOOKUP : + grn_text_printf(ctx, buf, "(_lookup)"); + break; + case GRN_ACCESSOR_FUNCALL : + grn_text_printf(ctx, buf, "(_funcall)"); + break; + default : + grn_text_printf(ctx, buf, "(unknown:%u)", accessor->action); + break; + } + + if (show_obj_name || show_obj_domain_name) { + grn_obj *target = accessor->obj; + char name[GRN_TABLE_MAX_KEY_SIZE]; + int name_size; + + if (show_obj_domain_name) { + target = grn_ctx_at(ctx, target->header.domain); + } + + name_size = grn_obj_name(ctx, + target, + name, + GRN_TABLE_MAX_KEY_SIZE); + GRN_TEXT_PUTS(ctx, buf, "("); + if (name_size == 0) { + GRN_TEXT_PUTS(ctx, buf, "anonymous"); + } else { + GRN_TEXT_PUT(ctx, buf, name, name_size); + } + GRN_TEXT_PUTS(ctx, buf, ")"); + } + } + GRN_TEXT_PUTS(ctx, buf, ">"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_type_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_id range_id; + + GRN_TEXT_PUTS(ctx, buf, "#header.flags & GRN_OBJ_KEY_VAR_SIZE) { + GRN_TEXT_PUTS(ctx, buf, "var_size"); + } else { + switch (obj->header.flags & GRN_OBJ_KEY_MASK) { + case GRN_OBJ_KEY_UINT : + GRN_TEXT_PUTS(ctx, buf, "uint"); + break; + case GRN_OBJ_KEY_INT : + GRN_TEXT_PUTS(ctx, buf, "int"); + break; + case GRN_OBJ_KEY_FLOAT : + GRN_TEXT_PUTS(ctx, buf, "float"); + break; + case GRN_OBJ_KEY_GEO_POINT : + GRN_TEXT_PUTS(ctx, buf, "geo_point"); + break; + default : + break; + } + } + + GRN_TEXT_PUTS(ctx, buf, ">"); + return GRN_SUCCESS; +} + +static grn_rc +grn_column_inspect_common(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_id range_id; + + grn_inspect_name(ctx, buf, obj); + + range_id = grn_obj_get_range(ctx, obj); + if (range_id) { + grn_obj *range = grn_ctx_at(ctx, range_id); + GRN_TEXT_PUTS(ctx, buf, " range:"); + if (range) { + grn_inspect_name(ctx, buf, range); + } else { + grn_text_lltoa(ctx, buf, range_id); + } + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_store_inspect_body(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_column_inspect_common(ctx, buf, obj); + GRN_TEXT_PUTS(ctx, buf, " type:"); + switch (obj->header.flags & GRN_OBJ_COLUMN_TYPE_MASK) { + case GRN_OBJ_COLUMN_VECTOR : + GRN_TEXT_PUTS(ctx, buf, "vector"); + break; + case GRN_OBJ_COLUMN_SCALAR : + GRN_TEXT_PUTS(ctx, buf, "scalar"); + break; + default: + break; + } + + GRN_TEXT_PUTS(ctx, buf, " compress:"); + switch (obj->header.flags & GRN_OBJ_COMPRESS_MASK) { + case GRN_OBJ_COMPRESS_NONE : + GRN_TEXT_PUTS(ctx, buf, "none"); + break; + case GRN_OBJ_COMPRESS_ZLIB : + GRN_TEXT_PUTS(ctx, buf, "zlib"); + break; + case GRN_OBJ_COMPRESS_LZ4 : + GRN_TEXT_PUTS(ctx, buf, "lz4"); + break; + case GRN_OBJ_COMPRESS_ZSTD : + GRN_TEXT_PUTS(ctx, buf, "zstd"); + break; + default: + break; + } + + if (obj->header.flags & GRN_OBJ_RING_BUFFER) { + GRN_TEXT_PUTS(ctx, buf, " ring_buffer:true"); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_ra_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + GRN_TEXT_PUTS(ctx, buf, "#"); + return GRN_SUCCESS; +} + +static grn_rc +grn_ja_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + GRN_TEXT_PUTS(ctx, buf, "#"); + return GRN_SUCCESS; +} + +static grn_rc +grn_ii_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_obj sources; + int i, n, have_flags = 0; + grn_id *source_ids; + + GRN_TEXT_PUTS(ctx, buf, "#header.flags & GRN_OBJ_WITH_SECTION) { + GRN_TEXT_PUTS(ctx, buf, "SECTION"); + have_flags = 1; + } + if (obj->header.flags & GRN_OBJ_WITH_WEIGHT) { + if (have_flags) { GRN_TEXT_PUTS(ctx, buf, "|"); } + GRN_TEXT_PUTS(ctx, buf, "WEIGHT"); + have_flags = 1; + } + if (obj->header.flags & GRN_OBJ_WITH_POSITION) { + if (have_flags) { GRN_TEXT_PUTS(ctx, buf, "|"); } + GRN_TEXT_PUTS(ctx, buf, "POSITION"); + have_flags = 1; + } + if (!have_flags) { + GRN_TEXT_PUTS(ctx, buf, "NONE"); + } + + GRN_TEXT_PUTS(ctx, buf, ">"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_type_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + switch (obj->header.type) { + case GRN_TABLE_HASH_KEY: + GRN_TEXT_PUTS(ctx, buf, "hash"); + break; + case GRN_TABLE_PAT_KEY: + GRN_TEXT_PUTS(ctx, buf, "pat"); + break; + case GRN_TABLE_DAT_KEY: + GRN_TEXT_PUTS(ctx, buf, "dat"); + break; + case GRN_TABLE_NO_KEY: + GRN_TEXT_PUTS(ctx, buf, "no_key"); + break; + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_key_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_obj *domain; + grn_id domain_id; + + GRN_TEXT_PUTS(ctx, buf, "key:"); + domain_id = obj->header.domain; + domain = grn_ctx_at(ctx, domain_id); + if (domain) { + grn_inspect_name(ctx, buf, domain); + } else if (domain_id) { + grn_text_lltoa(ctx, buf, domain_id); + } else { + GRN_TEXT_PUTS(ctx, buf, "(nil)"); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_columns_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_hash *cols; + + GRN_TEXT_PUTS(ctx, buf, "columns:["); + if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { + if (grn_table_columns(ctx, obj, "", 0, (grn_obj *)cols)) { + int i = 0; + grn_id *key; + GRN_HASH_EACH(ctx, cols, id, &key, NULL, NULL, { + grn_obj *col = grn_ctx_at(ctx, *key); + if (col) { + if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); } + grn_column_name_(ctx, col, buf); + } + }); + } + grn_hash_close(ctx, cols); + } + GRN_TEXT_PUTS(ctx, buf, "]"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_ids_and_values_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + int i = 0; + grn_obj value; + + GRN_VALUE_FIX_SIZE_INIT(&value, 0, grn_obj_get_range(ctx, obj)); + + GRN_TEXT_PUTS(ctx, buf, "ids&values:["); + GRN_TABLE_EACH_BEGIN(ctx, obj, cursor, id) { + void *value_buffer; + int value_size; + + if (i++ > 0) { + GRN_TEXT_PUTS(ctx, buf, ", "); + } + + GRN_TEXT_PUTS(ctx, buf, "\n "); + grn_text_lltoa(ctx, buf, id); + GRN_TEXT_PUTS(ctx, buf, ":"); + value_size = grn_table_cursor_get_value(ctx, cursor, &value_buffer); + grn_bulk_write_from(ctx, &value, value_buffer, 0, value_size); + grn_inspect(ctx, buf, &value); + } GRN_TABLE_EACH_END(ctx, cursor); + GRN_TEXT_PUTS(ctx, buf, "\n]"); + + GRN_OBJ_FIN(ctx, &value); + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_ids_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_table_cursor *tc; + + GRN_TEXT_PUTS(ctx, buf, "ids:["); + tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, + 0, -1, GRN_CURSOR_ASCENDING); + if (tc) { + int i = 0; + grn_id id; + while ((id = grn_table_cursor_next(ctx, tc))) { + if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); } + grn_text_lltoa(ctx, buf, id); + } + grn_table_cursor_close(ctx, tc); + } + GRN_TEXT_PUTS(ctx, buf, "]"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_default_tokenizer_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_obj *default_tokenizer; + + GRN_TEXT_PUTS(ctx, buf, "default_tokenizer:"); + default_tokenizer = grn_obj_get_info(ctx, obj, + GRN_INFO_DEFAULT_TOKENIZER, NULL); + if (default_tokenizer) { + grn_inspect_name(ctx, buf, default_tokenizer); + } else { + GRN_TEXT_PUTS(ctx, buf, "(nil)"); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_normalizer_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_obj *normalizer; + + GRN_TEXT_PUTS(ctx, buf, "normalizer:"); + normalizer = grn_obj_get_info(ctx, obj, GRN_INFO_NORMALIZER, NULL); + if (normalizer) { + grn_inspect_name(ctx, buf, normalizer); + } else { + GRN_TEXT_PUTS(ctx, buf, "(nil)"); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_keys_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_table_cursor *tc; + int max_n_keys = 10; + + /* TODO */ + /* max_n_keys = grn_atoi(grn_getenv("GRN_INSPECT_TABLE_MAX_N_KEYS")); */ + + GRN_TEXT_PUTS(ctx, buf, "keys:["); + tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, + 0, -1, GRN_CURSOR_ASCENDING); + if (tc) { + int i = 0; + grn_id id; + grn_obj key; + GRN_OBJ_INIT(&key, GRN_BULK, 0, obj->header.domain); + while ((id = grn_table_cursor_next(ctx, tc))) { + if (max_n_keys > 0 && i >= max_n_keys) { + GRN_TEXT_PUTS(ctx, buf, ", ..."); + break; + } + if (i++ > 0) { GRN_TEXT_PUTS(ctx, buf, ", "); } + grn_table_get_key2(ctx, obj, id, &key); + grn_inspect(ctx, buf, &key); + GRN_BULK_REWIND(&key); + } + GRN_OBJ_FIN(ctx, &key); + grn_table_cursor_close(ctx, tc); + } + GRN_TEXT_PUTS(ctx, buf, "]"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_subrec_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + GRN_TEXT_PUTS(ctx, buf, "subrec:"); + if (obj->header.flags & GRN_OBJ_WITH_SUBREC) { + switch (obj->header.flags & GRN_OBJ_UNIT_MASK) { + case GRN_OBJ_UNIT_DOCUMENT_NONE : + GRN_TEXT_PUTS(ctx, buf, "document:none"); + break; + case GRN_OBJ_UNIT_DOCUMENT_SECTION : + GRN_TEXT_PUTS(ctx, buf, "document:section"); + break; + case GRN_OBJ_UNIT_DOCUMENT_POSITION : + GRN_TEXT_PUTS(ctx, buf, "document:position"); + break; + case GRN_OBJ_UNIT_SECTION_NONE : + GRN_TEXT_PUTS(ctx, buf, "section:none"); + break; + case GRN_OBJ_UNIT_SECTION_POSITION : + GRN_TEXT_PUTS(ctx, buf, "section:popsition"); + break; + case GRN_OBJ_UNIT_POSITION_NONE : + GRN_TEXT_PUTS(ctx, buf, "section:none"); + break; + case GRN_OBJ_UNIT_USERDEF_DOCUMENT : + GRN_TEXT_PUTS(ctx, buf, "userdef:document"); + break; + case GRN_OBJ_UNIT_USERDEF_SECTION : + GRN_TEXT_PUTS(ctx, buf, "userdef:section"); + break; + case GRN_OBJ_UNIT_USERDEF_POSITION : + GRN_TEXT_PUTS(ctx, buf, "userdef:position"); + break; + } + } else { + GRN_TEXT_PUTS(ctx, buf, "none"); + } + + return GRN_SUCCESS; +} + +static grn_rc +grn_table_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_id range_id; + grn_obj *range; + + GRN_TEXT_PUTS(ctx, buf, "#header.type != GRN_TABLE_NO_KEY) { + GRN_TEXT_PUTS(ctx, buf, " "); + grn_table_key_inspect(ctx, buf, obj); + } + + GRN_TEXT_PUTS(ctx, buf, " value:"); + range_id = grn_obj_get_range(ctx, obj); + range = grn_ctx_at(ctx, range_id); + if (range) { + grn_inspect_name(ctx, buf, range); + } else if (range_id) { + grn_text_lltoa(ctx, buf, range_id); + } else { + GRN_TEXT_PUTS(ctx, buf, "(nil)"); + } + + GRN_TEXT_PUTS(ctx, buf, " size:"); + grn_text_lltoa(ctx, buf, grn_table_size(ctx, obj)); + + GRN_TEXT_PUTS(ctx, buf, " "); + grn_table_columns_inspect(ctx, buf, obj); + + if (obj->header.type == GRN_TABLE_NO_KEY) { + GRN_TEXT_PUTS(ctx, buf, " "); + if (range) { + grn_table_ids_and_values_inspect(ctx, buf, obj); + } else { + grn_table_ids_inspect(ctx, buf, obj); + } + } else { + GRN_TEXT_PUTS(ctx, buf, " "); + grn_table_default_tokenizer_inspect(ctx, buf, obj); + + GRN_TEXT_PUTS(ctx, buf, " "); + grn_table_normalizer_inspect(ctx, buf, obj); + + GRN_TEXT_PUTS(ctx, buf, " "); + grn_table_keys_inspect(ctx, buf, obj); + } + + GRN_TEXT_PUTS(ctx, buf, " "); + grn_table_subrec_inspect(ctx, buf, obj); + + if (obj->header.type == GRN_TABLE_PAT_KEY) { + GRN_TEXT_PUTS(ctx, buf, " nodes:"); + grn_pat_inspect_nodes(ctx, (grn_pat *)obj, buf); + } + + GRN_TEXT_PUTS(ctx, buf, ">"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_db_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_db *db = (grn_db *)obj; + + GRN_TEXT_PUTS(ctx, buf, "#keys); + + GRN_TEXT_PUTS(ctx, buf, " size:"); + grn_text_lltoa(ctx, buf, grn_table_size(ctx, obj)); + + GRN_TEXT_PUTS(ctx, buf, ">"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_time_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj) +{ + int64_t time_raw; + int64_t sec; + int32_t usec; + + time_raw = GRN_TIME_VALUE(obj); + GRN_TIME_UNPACK(time_raw, sec, usec); + grn_text_printf(ctx, buffer, + "%" GRN_FMT_INT64D ".%d", + sec, usec); + + return GRN_SUCCESS; +} + +static grn_rc +grn_geo_point_inspect_point(grn_ctx *ctx, grn_obj *buf, int point) +{ + GRN_TEXT_PUTS(ctx, buf, "("); + grn_text_itoa(ctx, buf, point / 1000 / 3600 % 3600); + GRN_TEXT_PUTS(ctx, buf, ", "); + grn_text_itoa(ctx, buf, point / 1000 / 60 % 60); + GRN_TEXT_PUTS(ctx, buf, ", "); + grn_text_itoa(ctx, buf, point / 1000 % 60); + GRN_TEXT_PUTS(ctx, buf, ", "); + grn_text_itoa(ctx, buf, point % 1000); + GRN_TEXT_PUTS(ctx, buf, ")"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_geo_point_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + int latitude, longitude; + + GRN_GEO_POINT_VALUE(obj, latitude, longitude); + + GRN_TEXT_PUTS(ctx, buf, "["); + GRN_TEXT_PUTS(ctx, buf, "("); + grn_text_itoa(ctx, buf, latitude); + GRN_TEXT_PUTS(ctx, buf, ","); + grn_text_itoa(ctx, buf, longitude); + GRN_TEXT_PUTS(ctx, buf, ")"); + + GRN_TEXT_PUTS(ctx, buf, " ("); + grn_geo_point_inspect_point(ctx, buf, latitude); + GRN_TEXT_PUTS(ctx, buf, ","); + grn_geo_point_inspect_point(ctx, buf, longitude); + GRN_TEXT_PUTS(ctx, buf, ")"); + + { + int i, j; + grn_geo_point point; + uint8_t encoded[sizeof(grn_geo_point)]; + + GRN_TEXT_PUTS(ctx, buf, " ["); + point.latitude = latitude; + point.longitude = longitude; + grn_gton(encoded, &point, sizeof(grn_geo_point)); + for (i = 0; i < sizeof(grn_geo_point); i++) { + if (i != 0) { + GRN_TEXT_PUTS(ctx, buf, " "); + } + for (j = 0; j < 8; j++) { + grn_text_itoa(ctx, buf, (encoded[i] >> (7 - j)) & 1); + } + } + GRN_TEXT_PUTS(ctx, buf, "]"); + } + + GRN_TEXT_PUTS(ctx, buf, "]"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_json_load_open_bracket_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + uint32_t i, n; + + n = GRN_UINT32_VALUE(obj); + + GRN_TEXT_PUTS(ctx, buf, "["); + for (i = 0; i < n; i++) { + grn_obj *value; + value = obj + 1 + i; + if (i > 0) { + GRN_TEXT_PUTS(ctx, buf, ", "); + } + grn_inspect(ctx, buf, value); + } + GRN_TEXT_PUTS(ctx, buf, "]"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_json_load_open_brace_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + uint32_t i, n; + + n = GRN_UINT32_VALUE(obj); + + GRN_TEXT_PUTS(ctx, buf, "{"); + for (i = 0; i < n; i += 2) { + grn_obj *key, *value; + key = obj + 1 + i; + value = key + 1; + if (i > 0) { + GRN_TEXT_PUTS(ctx, buf, ", "); + } + grn_inspect(ctx, buf, key); + GRN_TEXT_PUTS(ctx, buf, ": "); + grn_inspect(ctx, buf, value); + } + GRN_TEXT_PUTS(ctx, buf, "}"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + grn_obj *table; + grn_hash *cols; + + table = grn_ctx_at(ctx, obj->header.domain); + GRN_TEXT_PUTS(ctx, buf, "#header.domain); + GRN_TEXT_PUTS(ctx, buf, ")"); + } + + GRN_TEXT_PUTS(ctx, buf, " id:"); + if (GRN_BULK_VSIZE(obj) == 0) { + GRN_TEXT_PUTS(ctx, buf, "(no value)"); + } else { + grn_id id; + + id = GRN_RECORD_VALUE(obj); + grn_text_lltoa(ctx, buf, id); + + if (table && grn_table_at(ctx, table, id)) { + if (table->header.type != GRN_TABLE_NO_KEY) { + grn_obj key; + GRN_TEXT_PUTS(ctx, buf, " key:"); + GRN_OBJ_INIT(&key, GRN_BULK, 0, table->header.domain); + grn_table_get_key2(ctx, table, id, &key); + grn_inspect(ctx, buf, &key); + GRN_OBJ_FIN(ctx, &key); + } + if ((cols = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, + GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY))) { + if (grn_table_columns(ctx, table, "", 0, (grn_obj *)cols)) { + grn_id *key; + GRN_HASH_EACH(ctx, cols, column_id, &key, NULL, NULL, { + grn_obj *col = grn_ctx_at(ctx, *key); + if (col) { + grn_obj value; + GRN_TEXT_INIT(&value, 0); + GRN_TEXT_PUTS(ctx, buf, " "); + grn_column_name_(ctx, col, buf); + GRN_TEXT_PUTS(ctx, buf, ":"); + grn_obj_get_value(ctx, col, id, &value); + grn_inspect(ctx, buf, &value); + GRN_OBJ_FIN(ctx, &value); + } + }); + } + grn_hash_close(ctx, cols); + } + } else { + GRN_TEXT_PUTS(ctx, buf, "(nonexistent)"); + } + } + + GRN_TEXT_PUTS(ctx, buf, ">"); + + return GRN_SUCCESS; +} + +static grn_rc +grn_uvector_record_inspect(grn_ctx *ctx, grn_obj *buf, grn_obj *obj) +{ + unsigned int i, n = 0; + grn_obj record; + + GRN_RECORD_INIT(&record, 0, obj->header.domain); + GRN_TEXT_PUTS(ctx, buf, "["); + n = grn_vector_size(ctx, obj); + for (i = 0; i < n; i++) { + grn_id id; + unsigned int weight; + + if (i > 0) { + GRN_TEXT_PUTS(ctx, buf, ", "); + } + + id = grn_uvector_get_element(ctx, obj, i, &weight); + GRN_TEXT_PUTS(ctx, buf, "#", weight); + } + GRN_TEXT_PUTS(ctx, buf, "]"); + GRN_OBJ_FIN(ctx, &record); + + return GRN_SUCCESS; +} + +grn_obj * +grn_inspect(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj) +{ + grn_obj *domain; + + if (!buffer) { + buffer = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT); + } + + if (!obj) { + GRN_TEXT_PUTS(ctx, buffer, "(NULL)"); + return buffer; + } + + switch (obj->header.type) { + case GRN_VOID : + /* TODO */ + break; + case GRN_BULK : + switch (obj->header.domain) { + case GRN_DB_TIME : + grn_time_inspect(ctx, buffer, obj); + return buffer; + case GRN_DB_TOKYO_GEO_POINT : + case GRN_DB_WGS84_GEO_POINT : + grn_geo_point_inspect(ctx, buffer, obj); + return buffer; + case GRN_JSON_LOAD_OPEN_BRACKET : + grn_json_load_open_bracket_inspect(ctx, buffer, obj); + return buffer; + case GRN_JSON_LOAD_OPEN_BRACE : + grn_json_load_open_brace_inspect(ctx, buffer, obj); + return buffer; + default : + domain = grn_ctx_at(ctx, obj->header.domain); + if (domain) { + grn_id type = domain->header.type; + switch (type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_NO_KEY : + grn_record_inspect(ctx, buffer, obj); + return buffer; + default : + break; + } + } + } + break; + case GRN_PTR : + grn_ptr_inspect(ctx, buffer, obj); + break; + case GRN_UVECTOR : + domain = grn_ctx_at(ctx, obj->header.domain); + if (domain) { + grn_id type = domain->header.type; + switch (type) { + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_NO_KEY : + grn_uvector_record_inspect(ctx, buffer, obj); + return buffer; + default : + break; + } + } + break; + case GRN_PVECTOR : + grn_pvector_inspect(ctx, buffer, obj); + return buffer; + case GRN_VECTOR : + grn_vector_inspect(ctx, buffer, obj); + return buffer; + case GRN_MSG : + /* TODO */ + break; + case GRN_ACCESSOR : + grn_accessor_inspect(ctx, buffer, obj); + return buffer; + case GRN_SNIP : + case GRN_PATSNIP : + /* TODO */ + break; + case GRN_STRING : + grn_string_inspect(ctx, buffer, obj); + break; + case GRN_CURSOR_TABLE_HASH_KEY : + /* TODO */ + break; + case GRN_CURSOR_TABLE_PAT_KEY : + grn_pat_cursor_inspect(ctx, (grn_pat_cursor *)obj, buffer); + return buffer; + case GRN_CURSOR_TABLE_DAT_KEY : + case GRN_CURSOR_TABLE_NO_KEY : + case GRN_CURSOR_COLUMN_INDEX : + case GRN_CURSOR_COLUMN_GEO_INDEX : + /* TODO */ + break; + case GRN_TYPE : + grn_type_inspect(ctx, buffer, obj); + return buffer; + case GRN_PROC : + grn_proc_inspect(ctx, buffer, obj); + return buffer; + case GRN_EXPR : + grn_expr_inspect(ctx, buffer, obj); + return buffer; + case GRN_TABLE_HASH_KEY : + case GRN_TABLE_PAT_KEY : + case GRN_TABLE_DAT_KEY : + case GRN_TABLE_NO_KEY : + grn_table_inspect(ctx, buffer, obj); + return buffer; + case GRN_DB : + grn_db_inspect(ctx, buffer, obj); + break; + case GRN_COLUMN_FIX_SIZE : + grn_ra_inspect(ctx, buffer, obj); + return buffer; + case GRN_COLUMN_VAR_SIZE : + grn_ja_inspect(ctx, buffer, obj); + return buffer; + case GRN_COLUMN_INDEX : + grn_ii_inspect(ctx, buffer, obj); + return buffer; + default : + break; + } + + grn_text_otoj(ctx, buffer, obj, NULL); + return buffer; +} + +grn_obj * +grn_inspect_indented(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj, + const char *indent) +{ + grn_obj sub_buffer; + + GRN_TEXT_INIT(&sub_buffer, 0); + grn_inspect(ctx, &sub_buffer, obj); + { + const char *inspected = GRN_TEXT_VALUE(&sub_buffer); + size_t inspected_size = GRN_TEXT_LEN(&sub_buffer); + size_t i, line_start; + + if (!buffer) { + buffer = grn_obj_open(ctx, GRN_BULK, 0, GRN_DB_TEXT); + } + + line_start = 0; + for (i = 0; i < inspected_size; i++) { + if (inspected[i] == '\n') { + if (line_start != 0) { + GRN_TEXT_PUTS(ctx, buffer, indent); + } + GRN_TEXT_PUT(ctx, buffer, inspected + line_start, i + 1 - line_start); + line_start = i + 1; + } + } + if (line_start != 0) { + GRN_TEXT_PUTS(ctx, buffer, indent); + } + GRN_TEXT_PUT(ctx, buffer, + inspected + line_start, + inspected_size - line_start); + } + GRN_OBJ_FIN(ctx, &sub_buffer); + + return buffer; +} + +grn_obj * +grn_inspect_limited(grn_ctx *ctx, grn_obj *buffer, grn_obj *obj) +{ + grn_obj sub_buffer; + unsigned int max_size = GRN_CTX_MSGSIZE / 2; + + GRN_TEXT_INIT(&sub_buffer, 0); + grn_inspect(ctx, &sub_buffer, obj); + if (GRN_TEXT_LEN(&sub_buffer) > max_size) { + GRN_TEXT_PUT(ctx, buffer, GRN_TEXT_VALUE(&sub_buffer), max_size); + GRN_TEXT_PUTS(ctx, buffer, "...("); + grn_text_lltoa(ctx, buffer, GRN_TEXT_LEN(&sub_buffer)); + GRN_TEXT_PUTS(ctx, buffer, ")"); + } else { + GRN_TEXT_PUT(ctx, + buffer, + GRN_TEXT_VALUE(&sub_buffer), + GRN_TEXT_LEN(&sub_buffer)); + } + GRN_OBJ_FIN(ctx, &sub_buffer); + + return buffer; +} + +void +grn_p(grn_ctx *ctx, grn_obj *obj) +{ + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + grn_inspect(ctx, &buffer, obj); + printf("%.*s\n", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); +} + +void +grn_p_geo_point(grn_ctx *ctx, grn_geo_point *point) +{ + grn_obj obj; + + GRN_WGS84_GEO_POINT_INIT(&obj, 0); + GRN_GEO_POINT_SET(ctx, &obj, point->latitude, point->longitude); + grn_p(ctx, &obj); + GRN_OBJ_FIN(ctx, &obj); +} + +void +grn_p_ii_values(grn_ctx *ctx, grn_obj *ii) +{ + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + grn_ii_inspect_values(ctx, (grn_ii *)ii, &buffer); + printf("%.*s\n", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); +} + +void +grn_p_expr_code(grn_ctx *ctx, grn_expr_code *code) +{ + grn_obj buffer; + + GRN_TEXT_INIT(&buffer, 0); + grn_expr_code_inspect_indented(ctx, &buffer, code, ""); + printf("%.*s\n", (int)GRN_TEXT_LEN(&buffer), GRN_TEXT_VALUE(&buffer)); + GRN_OBJ_FIN(ctx, &buffer); +} + +void +grn_p_record(grn_ctx *ctx, grn_obj *table, grn_id id) +{ + grn_obj record; + + GRN_RECORD_INIT(&record, 0, grn_obj_id(ctx, table)); + GRN_RECORD_SET(ctx, &record, id); + grn_p(ctx, &record); + GRN_OBJ_FIN(ctx, &record); +} + +#ifdef WIN32 +int +grn_mkstemp(char *path_template) +{ + errno_t error; + size_t path_template_size; + int fd; + + path_template_size = strlen(path_template) + 1; + error = _mktemp_s(path_template, path_template_size); + if (error != 0) { + return -1; + } + + error = _sopen_s(&fd, + path_template, + _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY, + _SH_DENYNO, + _S_IREAD | _S_IWRITE); + if (error != 0) { + return -1; + } + + return fd; +} +#else /* WIN32 */ +int +grn_mkstemp(char *path_template) +{ +# ifdef HAVE_MKSTEMP + return mkstemp(path_template); +# else /* HAVE_MKSTEMP */ + mktemp(path_template); + return open(path_template, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); +# endif /* HAVE_MKSTEMP */ +} +#endif /* WIN32 */ + +grn_bool +grn_path_exist(const char *path) +{ + struct stat status; + return stat(path, &status) == 0; +} + +/* todo : refine */ +/* + * grn_tokenize splits a string into at most buf_size tokens and + * returns the number of tokens. The ending address of each token is + * written into tokbuf. Delimiters are ' ' and ','. + * Then, the address to the remaining is set to rest. + */ +int +grn_tokenize(const char *str, size_t str_len, + const char **tokbuf, int buf_size, + const char **rest) +{ + const char **tok = tokbuf, **tok_end = tokbuf + buf_size; + if (buf_size > 0) { + const char *str_end = str + str_len; + while (str < str_end && (' ' == *str || ',' == *str)) { str++; } + for (;;) { + if (str == str_end) { + *tok++ = str; + break; + } + if (' ' == *str || ',' == *str) { + /* *str = '\0'; */ + *tok++ = str; + if (tok == tok_end) { break; } + do { str++; } while (str < str_end && (' ' == *str || ',' == *str)); + } else { + str++; + } + } + } + if (rest) { *rest = str; } + return tok - tokbuf; +} diff --git a/storage/mroonga/vendor/groonga/lib/window_function.c b/storage/mroonga/vendor/groonga/lib/window_function.c new file mode 100644 index 00000000..27e8c9c8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/window_function.c @@ -0,0 +1,464 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_ctx.h" +#include "grn_db.h" +#include "grn_expr.h" +#include "grn_window_function.h" + +#include + +grn_rc +grn_window_init(grn_ctx *ctx, + grn_window *window, + grn_obj *table, + grn_bool is_sorted) +{ + GRN_API_ENTER; + + window->table = table; + GRN_RECORD_INIT(&(window->ids), GRN_OBJ_VECTOR, grn_obj_id(ctx, table)); + window->n_ids = 0; + window->current_index = 0; + window->direction = GRN_WINDOW_DIRECTION_ASCENDING; + window->is_sorted = is_sorted; + + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_rc +grn_window_fin(grn_ctx *ctx, grn_window *window) +{ + GRN_API_ENTER; + + GRN_OBJ_FIN(ctx, &(window->ids)); + + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_id +grn_window_next(grn_ctx *ctx, grn_window *window) +{ + grn_id next_id; + + GRN_API_ENTER; + + if (!window) { + GRN_API_RETURN(GRN_ID_NIL); + } + + if (window->direction == GRN_WINDOW_DIRECTION_ASCENDING) { + if (window->current_index >= window->n_ids) { + GRN_API_RETURN(GRN_ID_NIL); + } + } else { + if (window->current_index < 0) { + GRN_API_RETURN(GRN_ID_NIL); + } + } + + next_id = GRN_RECORD_VALUE_AT(&(window->ids), window->current_index); + if (window->direction == GRN_WINDOW_DIRECTION_ASCENDING) { + window->current_index++; + } else { + window->current_index--; + } + + GRN_API_RETURN(next_id); +} + +grn_rc +grn_window_rewind(grn_ctx *ctx, grn_window *window) +{ + GRN_API_ENTER; + + if (!window) { + ERR(GRN_INVALID_ARGUMENT, "[window][rewind] window is NULL"); + GRN_API_RETURN(ctx->rc); + } + + if (window->direction == GRN_WINDOW_DIRECTION_ASCENDING) { + window->current_index = 0; + } else { + window->current_index = window->n_ids - 1; + } + + GRN_API_RETURN(GRN_SUCCESS); +} + +grn_obj * +grn_window_get_table(grn_ctx *ctx, grn_window *window) +{ + GRN_API_ENTER; + + if (!window) { + ERR(GRN_INVALID_ARGUMENT, "[window][rewind] window is NULL"); + GRN_API_RETURN(NULL); + } + + GRN_API_RETURN(window->table); +} + +grn_rc +grn_window_set_direction(grn_ctx *ctx, + grn_window *window, + grn_window_direction direction) +{ + GRN_API_ENTER; + + if (!window) { + ERR(GRN_INVALID_ARGUMENT, "[window][set][direction] window is NULL"); + GRN_API_RETURN(ctx->rc); + } + + switch (direction) { + case GRN_WINDOW_DIRECTION_ASCENDING : + window->direction = direction; + window->current_index = 0; + break; + case GRN_WINDOW_DIRECTION_DESCENDING : + window->direction = direction; + window->current_index = window->n_ids - 1; + break; + default : + ERR(GRN_INVALID_ARGUMENT, + "[window][set][direction] direction must be " + "GRN_WINDOW_DIRECTION_ASCENDING(%d) or " + "GRN_WINDOW_DIRECTION_DESCENDING(%d): %d", + GRN_WINDOW_DIRECTION_ASCENDING, + GRN_WINDOW_DIRECTION_DESCENDING, + direction); + GRN_API_RETURN(ctx->rc); + break; + } + + GRN_API_RETURN(GRN_SUCCESS); +} + +static inline void +grn_window_reset(grn_ctx *ctx, + grn_window *window) +{ + GRN_BULK_REWIND(&(window->ids)); +} + +static inline void +grn_window_add_record(grn_ctx *ctx, + grn_window *window, + grn_id record_id) +{ + GRN_RECORD_PUT(ctx, &(window->ids), record_id); +} + +static inline grn_bool +grn_window_is_empty(grn_ctx *ctx, + grn_window *window) +{ + return GRN_BULK_VSIZE(&(window->ids)) == 0; +} + +grn_bool +grn_window_is_sorted(grn_ctx *ctx, grn_window *window) +{ + GRN_API_ENTER; + + if (!window) { + ERR(GRN_INVALID_ARGUMENT, "[window][is-sorted] window is NULL"); + GRN_API_RETURN(GRN_FALSE); + } + + GRN_API_RETURN(window->is_sorted); +} + +size_t +grn_window_get_size(grn_ctx *ctx, + grn_window *window) +{ + GRN_API_ENTER; + + GRN_API_RETURN(window->n_ids); +} + +grn_obj * +grn_window_function_create(grn_ctx *ctx, + const char *name, + int name_size, + grn_window_function_func func) +{ + grn_obj *window_function = NULL; + + GRN_API_ENTER; + + if (name_size == -1) { + name_size = strlen(name); + } + + window_function = grn_proc_create(ctx, + name, + name_size, + GRN_PROC_WINDOW_FUNCTION, + NULL, NULL, NULL, 0, NULL); + if (!window_function) { + ERR(GRN_WINDOW_FUNCTION_ERROR, + "[window-function][%.*s] failed to create proc: %s", + name_size, name, + ctx->errbuf); + GRN_API_RETURN(NULL); + } + + { + grn_proc *proc = (grn_proc *)window_function; + proc->callbacks.window_function = func; + } + + GRN_API_RETURN(window_function); +} + +static grn_bool +grn_expr_is_window_function_call(grn_ctx *ctx, + grn_obj *window_function_call) +{ + grn_expr *expr = (grn_expr *)window_function_call; + grn_expr_code *func; + grn_expr_code *call; + + func = &(expr->codes[0]); + call = &(expr->codes[expr->codes_curr - 1]); + + if (func->op != GRN_OP_PUSH) { + return GRN_FALSE; + } + if (!grn_obj_is_window_function_proc(ctx, func->value)) { + return GRN_FALSE; + } + + if (call->op != GRN_OP_CALL) { + return GRN_FALSE; + } + if (call->nargs != (expr->codes_curr - 1)) { + return GRN_FALSE; + } + + return GRN_TRUE; +} + +static grn_rc +grn_expr_call_window_function(grn_ctx *ctx, + grn_obj *output_column, + grn_window *window, + grn_obj *window_function_call) +{ + grn_rc rc; + grn_expr *expr = (grn_expr *)window_function_call; + grn_proc *proc; + int32_t i, n; + grn_obj args; + + proc = (grn_proc *)(expr->codes[0].value); + + GRN_PTR_INIT(&args, GRN_OBJ_VECTOR, GRN_ID_NIL); + n = expr->codes_curr - 1; + for (i = 1; i < n; i++) { + /* TODO: Check op. */ + GRN_PTR_PUT(ctx, &args, expr->codes[i].value); + } + window->n_ids = GRN_BULK_VSIZE(&(window->ids)) / sizeof(grn_id); + if (window->direction == GRN_WINDOW_DIRECTION_ASCENDING) { + window->current_index = 0; + } else { + window->current_index = window->n_ids - 1; + } + rc = proc->callbacks.window_function(ctx, + output_column, + window, + (grn_obj **)GRN_BULK_HEAD(&args), + GRN_BULK_VSIZE(&args) / sizeof(grn_obj *)); + GRN_OBJ_FIN(ctx, &args); + + return rc; +} + +grn_rc +grn_table_apply_window_function(grn_ctx *ctx, + grn_obj *table, + grn_obj *output_column, + grn_window_definition *definition, + grn_obj *window_function_call) +{ + GRN_API_ENTER; + + if (!table) { + ERR(GRN_INVALID_ARGUMENT, + "[table][apply][window-function] table is NULL"); + GRN_API_RETURN(ctx->rc); + } + + if (!grn_expr_is_window_function_call(ctx, window_function_call)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, window_function_call); + ERR(GRN_INVALID_ARGUMENT, + "[table][apply][window-function] must be window function call: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + GRN_API_RETURN(ctx->rc); + } + + { + size_t n_sort_keys; + grn_table_sort_key *sort_keys; + grn_obj *sorted; + grn_window window; + + n_sort_keys = definition->n_group_keys + definition->n_sort_keys; + sort_keys = GRN_MALLOCN(grn_table_sort_key, n_sort_keys); + if (!sort_keys) { + grn_rc rc = ctx->rc; + if (rc == GRN_SUCCESS) { + rc = GRN_NO_MEMORY_AVAILABLE; + } + ERR(rc, + "[table][apply][window-function] " + "failed to allocate internal sort keys: %s", + ctx->errbuf); + GRN_API_RETURN(ctx->rc); + } + { + size_t i; + for (i = 0; i < definition->n_group_keys; i++) { + sort_keys[i] = definition->group_keys[i]; + } + for (i = 0; i < definition->n_sort_keys; i++) { + sort_keys[i + definition->n_group_keys] = definition->sort_keys[i]; + } + } + sorted = grn_table_create(ctx, + NULL, 0, NULL, + GRN_OBJ_TABLE_NO_KEY, + NULL, + table); + if (!sorted) { + grn_rc rc = ctx->rc; + if (rc == GRN_SUCCESS) { + rc = GRN_NO_MEMORY_AVAILABLE; + } + GRN_FREE(sort_keys); + ERR(rc, + "[table][apply][window-function] " + "failed to allocate table to store sorted result: %s", + ctx->errbuf); + GRN_API_RETURN(ctx->rc); + } + grn_table_sort(ctx, + table, + 0, -1, + sorted, + sort_keys, n_sort_keys); + + grn_window_init(ctx, &window, table, definition->n_sort_keys > 0); + if (definition->n_group_keys > 0) { + grn_obj *previous_values; + grn_obj *current_values; + size_t i, n; + + previous_values = GRN_MALLOCN(grn_obj, definition->n_group_keys); + current_values = GRN_MALLOCN(grn_obj, definition->n_group_keys); + n = definition->n_group_keys; + + for (i = 0; i < n; i++) { + GRN_VOID_INIT(&(previous_values[i])); + GRN_VOID_INIT(&(current_values[i])); + } + + GRN_TABLE_EACH_BEGIN(ctx, sorted, cursor, id) { + void *value; + grn_id record_id; + grn_bool is_group_key_changed = GRN_FALSE; + + grn_table_cursor_get_value(ctx, cursor, &value); + record_id = *((grn_id *)value); + + for (i = 0; i < n; i++) { + size_t reverse_i = n - i - 1; + grn_obj *previous_value = &(previous_values[reverse_i]); + grn_obj *current_value = &(current_values[reverse_i]); + grn_obj *group_key = definition->group_keys[reverse_i].key; + + if (is_group_key_changed) { + GRN_BULK_REWIND(previous_value); + grn_obj_get_value(ctx, group_key, record_id, previous_value); + } else { + GRN_BULK_REWIND(current_value); + grn_obj_get_value(ctx, group_key, record_id, current_value); + if ((GRN_BULK_VSIZE(current_value) != + GRN_BULK_VSIZE(previous_value)) || + (memcmp(GRN_BULK_HEAD(current_value), + GRN_BULK_HEAD(previous_value), + GRN_BULK_VSIZE(current_value)) != 0)) { + is_group_key_changed = GRN_TRUE; + grn_bulk_write_from(ctx, + previous_value, + GRN_BULK_HEAD(current_value), + 0, + GRN_BULK_VSIZE(current_value)); + } + } + } + + if (is_group_key_changed && !grn_window_is_empty(ctx, &window)) { + grn_expr_call_window_function(ctx, + output_column, + &window, + window_function_call); + grn_window_reset(ctx, &window); + } + grn_window_add_record(ctx, &window, record_id); + } GRN_TABLE_EACH_END(ctx, cursor); + grn_expr_call_window_function(ctx, + output_column, + &window, + window_function_call); + + for (i = 0; i < definition->n_group_keys; i++) { + GRN_OBJ_FIN(ctx, &(previous_values[i])); + GRN_OBJ_FIN(ctx, &(current_values[i])); + } + GRN_FREE(previous_values); + GRN_FREE(current_values); + } else { + GRN_TABLE_EACH_BEGIN(ctx, sorted, cursor, id) { + void *value; + grn_id record_id; + + grn_table_cursor_get_value(ctx, cursor, &value); + record_id = *((grn_id *)value); + grn_window_add_record(ctx, &window, record_id); + } GRN_TABLE_EACH_END(ctx, cursor); + grn_expr_call_window_function(ctx, + output_column, + &window, + window_function_call); + } + grn_window_fin(ctx, &window); + + GRN_FREE(sort_keys); + } + + GRN_API_RETURN(ctx->rc); +} diff --git a/storage/mroonga/vendor/groonga/lib/window_functions.c b/storage/mroonga/vendor/groonga/lib/window_functions.c new file mode 100644 index 00000000..7a177cd8 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/window_functions.c @@ -0,0 +1,405 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_db.h" +#include "grn_window_functions.h" + +static grn_rc +window_record_number(grn_ctx *ctx, + grn_obj *output_column, + grn_window *window, + grn_obj **args, + int n_args) +{ + grn_id id; + uint32_t nth_record = 1; + grn_obj value; + + GRN_UINT32_INIT(&value, 0); + while ((id = grn_window_next(ctx, window))) { + GRN_UINT32_SET(ctx, &value, nth_record); + grn_obj_set_value(ctx, output_column, id, &value, GRN_OBJ_SET); + nth_record++; + } + GRN_OBJ_FIN(ctx, &value); + + return GRN_SUCCESS; +} + +static grn_rc +window_sum(grn_ctx *ctx, + grn_obj *output_column, + grn_window *window, + grn_obj **args, + int n_args) +{ + grn_id id; + grn_obj *target; + + if (n_args != 1) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "window_sum(): wrong number of arguments (%d for 1)", + n_args); + return ctx->rc; + } + + target = args[0]; + if (target->header.type != GRN_ACCESSOR) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, target); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "window_sum(): " + "the target column must be accessor: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return ctx->rc; + } + + { + const grn_id output_column_range_id = grn_obj_get_range(ctx, output_column); + const grn_id target_range_id = grn_obj_get_range(ctx, target); + grn_obj sum; + grn_obj value; + + switch (target_range_id) { + case GRN_DB_INT8 : + case GRN_DB_INT16 : + case GRN_DB_INT32 : + case GRN_DB_INT64 : + case GRN_DB_UINT8 : + case GRN_DB_UINT16 : + case GRN_DB_UINT32 : + case GRN_DB_UINT64 : + case GRN_DB_FLOAT : + break; + default : + { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, target); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "window_sum(): " + "the target column must be number column: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return ctx->rc; + } + break; + } + + switch (output_column_range_id) { + case GRN_DB_INT8 : + case GRN_DB_INT16 : + case GRN_DB_INT32 : + case GRN_DB_INT64 : + GRN_INT64_INIT(&sum, 0); + break; + case GRN_DB_UINT8 : + case GRN_DB_UINT16 : + case GRN_DB_UINT32 : + case GRN_DB_UINT64 : + GRN_UINT64_INIT(&sum, 0); + break; + case GRN_DB_FLOAT : + GRN_FLOAT_INIT(&sum, 0); + break; + default : + { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, output_column); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "window_sum(): " + "the output column must be number column: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return ctx->rc; + } + break; + } + GRN_VOID_INIT(&value); + + if (grn_window_is_sorted(ctx, window)) { + while ((id = grn_window_next(ctx, window))) { + GRN_BULK_REWIND(&value); + grn_obj_get_value(ctx, target, id, &value); + switch (target_range_id) { + case GRN_DB_INT8 : + GRN_INT64_SET(ctx, + &sum, + GRN_INT64_VALUE(&sum) + GRN_INT8_VALUE(&value)); + break; + case GRN_DB_INT16 : + GRN_INT64_SET(ctx, + &sum, + GRN_INT64_VALUE(&sum) + GRN_INT16_VALUE(&value)); + break; + case GRN_DB_INT32 : + GRN_INT64_SET(ctx, + &sum, + GRN_INT64_VALUE(&sum) + GRN_INT32_VALUE(&value)); + break; + case GRN_DB_INT64 : + GRN_INT64_SET(ctx, + &sum, + GRN_INT64_VALUE(&sum) + GRN_INT64_VALUE(&value)); + break; + case GRN_DB_UINT8 : + GRN_UINT64_SET(ctx, + &sum, + GRN_UINT64_VALUE(&sum) + GRN_UINT8_VALUE(&value)); + break; + case GRN_DB_UINT16 : + GRN_UINT64_SET(ctx, + &sum, + GRN_UINT64_VALUE(&sum) + GRN_UINT16_VALUE(&value)); + break; + case GRN_DB_UINT32 : + GRN_UINT64_SET(ctx, + &sum, + GRN_UINT64_VALUE(&sum) + GRN_UINT32_VALUE(&value)); + break; + case GRN_DB_UINT64 : + GRN_UINT64_SET(ctx, + &sum, + GRN_UINT64_VALUE(&sum) + GRN_UINT64_VALUE(&value)); + break; + case GRN_DB_FLOAT : + GRN_FLOAT_SET(ctx, + &sum, + GRN_FLOAT_VALUE(&sum) + GRN_FLOAT_VALUE(&value)); + break; + default : + break; + } + grn_obj_set_value(ctx, output_column, id, &sum, GRN_OBJ_SET); + } + } else { + int64_t sum_raw_int64 = 0; + uint64_t sum_raw_uint64 = 0; + double sum_raw_double = 0.0; + + while ((id = grn_window_next(ctx, window))) { + GRN_BULK_REWIND(&value); + grn_obj_get_value(ctx, target, id, &value); + switch (target_range_id) { + case GRN_DB_INT8 : + sum_raw_int64 += GRN_INT8_VALUE(&value); + break; + case GRN_DB_INT16 : + sum_raw_int64 += GRN_INT16_VALUE(&value); + break; + case GRN_DB_INT32 : + sum_raw_int64 += GRN_INT32_VALUE(&value); + break; + case GRN_DB_INT64 : + sum_raw_int64 += GRN_INT64_VALUE(&value); + break; + case GRN_DB_UINT8 : + sum_raw_uint64 += GRN_UINT8_VALUE(&value); + break; + case GRN_DB_UINT16 : + sum_raw_uint64 += GRN_UINT16_VALUE(&value); + break; + case GRN_DB_UINT32 : + sum_raw_uint64 += GRN_UINT32_VALUE(&value); + break; + case GRN_DB_UINT64 : + sum_raw_uint64 += GRN_UINT64_VALUE(&value); + break; + case GRN_DB_FLOAT : + sum_raw_double += GRN_FLOAT_VALUE(&value); + break; + default : + break; + } + } + + switch (output_column_range_id) { + case GRN_DB_INT8 : + case GRN_DB_INT16 : + case GRN_DB_INT32 : + case GRN_DB_INT64 : + GRN_INT64_SET(ctx, &sum, sum_raw_int64); + break; + case GRN_DB_UINT8 : + case GRN_DB_UINT16 : + case GRN_DB_UINT32 : + case GRN_DB_UINT64 : + GRN_UINT64_SET(ctx, &sum, sum_raw_uint64); + break; + case GRN_DB_FLOAT : + GRN_FLOAT_SET(ctx, &sum, sum_raw_double); + break; + } + + grn_window_rewind(ctx, window); + while ((id = grn_window_next(ctx, window))) { + grn_obj_set_value(ctx, output_column, id, &sum, GRN_OBJ_SET); + } + } + + GRN_OBJ_FIN(ctx, &value); + GRN_OBJ_FIN(ctx, &sum); + } + + return GRN_SUCCESS; +} + +static grn_rc +window_count(grn_ctx *ctx, + grn_obj *output_column, + grn_window *window, + grn_obj **args, + int n_args) +{ + grn_id id; + grn_id output_column_range_id; + grn_obj n_records; + uint32_t n_records_raw = 0; + + + if (n_args != 0) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "window_count(): wrong number of arguments (%d for 0)", + n_args); + return ctx->rc; + } + + output_column_range_id = grn_obj_get_range(ctx, output_column); + switch (output_column_range_id) { + case GRN_DB_INT8 : + case GRN_DB_INT16 : + case GRN_DB_INT32 : + case GRN_DB_INT64 : + GRN_INT64_INIT(&n_records, 0); + break; + case GRN_DB_UINT8 : + case GRN_DB_UINT16 : + case GRN_DB_UINT32 : + case GRN_DB_UINT64 : + GRN_UINT64_INIT(&n_records, 0); + break; + case GRN_DB_FLOAT : + GRN_FLOAT_INIT(&n_records, 0); + break; + default : + { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, output_column); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "window_count(): " + "the output column must be number column: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return ctx->rc; + } + break; + } + + if (grn_window_is_sorted(ctx, window)) { + while ((id = grn_window_next(ctx, window))) { + n_records_raw++; + switch (output_column_range_id) { + case GRN_DB_INT8 : + case GRN_DB_INT16 : + case GRN_DB_INT32 : + case GRN_DB_INT64 : + GRN_INT64_SET(ctx, &n_records, n_records_raw); + break; + case GRN_DB_UINT8 : + case GRN_DB_UINT16 : + case GRN_DB_UINT32 : + case GRN_DB_UINT64 : + GRN_UINT64_SET(ctx, &n_records, n_records_raw); + break; + case GRN_DB_FLOAT : + GRN_FLOAT_SET(ctx, &n_records, n_records_raw); + break; + default : + break; + } + grn_obj_set_value(ctx, output_column, id, &n_records, GRN_OBJ_SET); + } + } else { + while ((id = grn_window_next(ctx, window))) { + n_records_raw++; + } + + switch (output_column_range_id) { + case GRN_DB_INT8 : + case GRN_DB_INT16 : + case GRN_DB_INT32 : + case GRN_DB_INT64 : + GRN_INT64_SET(ctx, &n_records, n_records_raw); + break; + case GRN_DB_UINT8 : + case GRN_DB_UINT16 : + case GRN_DB_UINT32 : + case GRN_DB_UINT64 : + GRN_UINT64_SET(ctx, &n_records, n_records_raw); + break; + case GRN_DB_FLOAT : + GRN_FLOAT_SET(ctx, &n_records, n_records_raw); + break; + } + + grn_window_rewind(ctx, window); + while ((id = grn_window_next(ctx, window))) { + grn_obj_set_value(ctx, output_column, id, &n_records, GRN_OBJ_SET); + } + } + + GRN_OBJ_FIN(ctx, &n_records); + + return GRN_SUCCESS; +} + +grn_rc +grn_db_init_builtin_window_functions(grn_ctx *ctx) +{ + /* For backward compatibility. */ + grn_window_function_create(ctx, + "record_number", -1, + window_record_number); + grn_window_function_create(ctx, + "window_record_number", -1, + window_record_number); + + grn_window_function_create(ctx, + "window_sum", -1, + window_sum); + + grn_window_function_create(ctx, + "window_count", -1, + window_count); + + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/lib/windows.c b/storage/mroonga/vendor/groonga/lib/windows.c new file mode 100644 index 00000000..a363d711 --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/windows.c @@ -0,0 +1,104 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2010-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn.h" +#include "grn_windows.h" + +#ifdef WIN32 +static char *windows_base_dir = NULL; +const char * +grn_windows_base_dir(void) +{ + if (!windows_base_dir) { + HMODULE dll; + const wchar_t *dll_filename = GRN_DLL_FILENAME; + wchar_t absolute_dll_filename[MAX_PATH]; + DWORD absolute_dll_filename_size; + dll = GetModuleHandleW(dll_filename); + absolute_dll_filename_size = GetModuleFileNameW(dll, + absolute_dll_filename, + MAX_PATH); + if (absolute_dll_filename_size == 0) { + windows_base_dir = grn_strdup_raw("."); + } else { + DWORD ansi_dll_filename_size; + ansi_dll_filename_size = + WideCharToMultiByte(CP_ACP, 0, + absolute_dll_filename, absolute_dll_filename_size, + NULL, 0, NULL, NULL); + if (ansi_dll_filename_size == 0) { + windows_base_dir = grn_strdup_raw("."); + } else { + char *path; + windows_base_dir = malloc(ansi_dll_filename_size + 1); + WideCharToMultiByte(CP_ACP, 0, + absolute_dll_filename, absolute_dll_filename_size, + windows_base_dir, ansi_dll_filename_size, + NULL, NULL); + windows_base_dir[ansi_dll_filename_size] = '\0'; + if ((path = strrchr(windows_base_dir, '\\'))) { + *path = '\0'; + } + path = strrchr(windows_base_dir, '\\'); + if (path && (grn_strcasecmp(path + 1, "bin") == 0 || + grn_strcasecmp(path + 1, "lib") == 0)) { + *path = '\0'; + } else { + path = windows_base_dir + strlen(windows_base_dir); + *path = '\0'; + } + for (path = windows_base_dir; *path; path++) { + if (*path == '\\') { + *path = '/'; + } + } + } + } + } + return windows_base_dir; +} + +UINT +grn_windows_encoding_to_code_page(grn_encoding encoding) +{ + UINT code_page; + + switch (encoding) { + case GRN_ENC_EUC_JP : + code_page = 20932; + break; + case GRN_ENC_UTF8 : + code_page = CP_UTF8; + break; + case GRN_ENC_SJIS : + code_page = 932; + break; + case GRN_ENC_LATIN1 : + code_page = 1252; + break; + case GRN_ENC_KOI8R : + code_page = 20866; + break; + default : + code_page = CP_ACP; + break; + } + + return code_page; +} +#endif /* WIN32 */ diff --git a/storage/mroonga/vendor/groonga/lib/windows_event_logger.c b/storage/mroonga/vendor/groonga/lib/windows_event_logger.c new file mode 100644 index 00000000..fb8229ad --- /dev/null +++ b/storage/mroonga/vendor/groonga/lib/windows_event_logger.c @@ -0,0 +1,203 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2017 Brazil + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License version 2.1 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA +*/ + +#include "grn_logger.h" +#include "grn_ctx.h" +#include "grn_windows.h" + +#include + +#ifdef WIN32 + +typedef struct _grn_windows_event_logger_data { + char *event_source_name; + HANDLE event_source; +} grn_windows_event_logger_data; + +static void +windows_event_logger_log(grn_ctx *ctx, grn_log_level level, + const char *timestamp, const char *title, + const char *message, const char *location, + void *user_data) +{ + grn_windows_event_logger_data *data = user_data; + WORD type; + WORD category = 0; + DWORD event_id = 0; + PSID user_sid = NULL; + WORD n_strings = 1; + DWORD event_data_size = 0; + const WCHAR *strings[1]; + LPVOID event_data = NULL; + const char level_marks[] = " EACewnid-"; + grn_obj formatted_buffer; + UINT code_page; + DWORD convert_flags = 0; + int n_converted_chars; + + switch (level) { + case GRN_LOG_NONE : + return; + break; + case GRN_LOG_EMERG : + case GRN_LOG_ALERT : + case GRN_LOG_CRIT : + case GRN_LOG_ERROR : + type = EVENTLOG_ERROR_TYPE; + break; + case GRN_LOG_WARNING : + type = EVENTLOG_WARNING_TYPE; + break; + case GRN_LOG_NOTICE : + case GRN_LOG_INFO : + case GRN_LOG_DEBUG : + case GRN_LOG_DUMP : + type = EVENTLOG_INFORMATION_TYPE; + break; + default : + type = EVENTLOG_ERROR_TYPE; + break; + } + + if (data->event_source == INVALID_HANDLE_VALUE) { + data->event_source = RegisterEventSourceA(NULL, data->event_source_name); + if (data->event_source == INVALID_HANDLE_VALUE) { + return; + } + } + + GRN_TEXT_INIT(&formatted_buffer, 0); + if (location && location[0]) { + grn_text_printf(ctx, &formatted_buffer, "%s|%c|%s %s %s", + timestamp, level_marks[level], title, message, location); + } else { + grn_text_printf(ctx, &formatted_buffer, "%s|%c|%s %s", + timestamp, level_marks[level], title, message); + } + + code_page = grn_windows_encoding_to_code_page(ctx->encoding); + + n_converted_chars = MultiByteToWideChar(code_page, + convert_flags, + GRN_TEXT_VALUE(&formatted_buffer), + GRN_TEXT_LEN(&formatted_buffer), + NULL, + 0); +#define CONVERTED_BUFFER_SIZE 512 + if (n_converted_chars < CONVERTED_BUFFER_SIZE) { + WCHAR converted_buffer[CONVERTED_BUFFER_SIZE]; + n_converted_chars = MultiByteToWideChar(code_page, + convert_flags, + GRN_TEXT_VALUE(&formatted_buffer), + GRN_TEXT_LEN(&formatted_buffer), + converted_buffer, + CONVERTED_BUFFER_SIZE); + converted_buffer[n_converted_chars] = L'\0'; + strings[0] = converted_buffer; + ReportEventW(data->event_source, type, category, event_id, user_sid, + n_strings, event_data_size, + strings, event_data); +#undef CONVERTED_BUFFER_SIZE + } else { + WCHAR *converted; + converted = GRN_MALLOCN(WCHAR, n_converted_chars); + n_converted_chars = MultiByteToWideChar(code_page, + convert_flags, + GRN_TEXT_VALUE(&formatted_buffer), + GRN_TEXT_LEN(&formatted_buffer), + converted, + n_converted_chars); + converted[n_converted_chars] = L'\0'; + strings[0] = converted; + ReportEventW(data->event_source, type, category, event_id, user_sid, + n_strings, event_data_size, + strings, event_data); + GRN_FREE(converted); + } + GRN_OBJ_FIN(ctx, &formatted_buffer); +} + +static void +windows_event_logger_reopen(grn_ctx *ctx, void *user_data) +{ +} + +static void +windows_event_logger_fin(grn_ctx *ctx, void *user_data) +{ + grn_windows_event_logger_data *data = user_data; + + free(data->event_source_name); + if (data->event_source != INVALID_HANDLE_VALUE) { + DeregisterEventSource(data->event_source); + } + free(data); +} +#endif /* WIN32 */ + +grn_rc +grn_windows_event_logger_set(grn_ctx *ctx, const char *event_source_name) +{ +#ifdef WIN32 + grn_rc rc; + grn_logger windows_event_logger; + grn_windows_event_logger_data *data; + + if (ctx) { + GRN_API_ENTER; + } + + data = malloc(sizeof(grn_windows_event_logger_data)); + if (!data) { + if (ctx) { + ERR(GRN_NO_MEMORY_AVAILABLE, + "failed to allocate user data for Windows event logger"); + GRN_API_RETURN(ctx->rc); + } else { + return GRN_NO_MEMORY_AVAILABLE; + } + } + + if (event_source_name) { + data->event_source_name = grn_strdup_raw(event_source_name); + } else { + data->event_source_name = grn_strdup_raw("libgroonga"); + } + data->event_source = INVALID_HANDLE_VALUE; + + windows_event_logger.max_level = GRN_LOG_DEFAULT_LEVEL; + windows_event_logger.flags = GRN_LOG_TIME | GRN_LOG_MESSAGE; + windows_event_logger.user_data = data; + windows_event_logger.log = windows_event_logger_log; + windows_event_logger.reopen = windows_event_logger_reopen; + windows_event_logger.fin = windows_event_logger_fin; + + rc = grn_logger_set(ctx, &windows_event_logger); + if (rc != GRN_SUCCESS) { + windows_event_logger.fin(ctx, windows_event_logger.user_data); + } + + if (ctx) { + GRN_API_RETURN(rc); + } else { + return rc; + } +#else /* WIN32 */ + return GRN_FUNCTION_NOT_IMPLEMENTED; +#endif /* WIN32 */ +} -- cgit v1.2.3