zsv 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +36 -0
- data/LICENSE +21 -0
- data/README.md +311 -0
- data/ext/zsv/common.h +34 -0
- data/ext/zsv/extconf.rb +137 -0
- data/ext/zsv/options.c +126 -0
- data/ext/zsv/options.h +31 -0
- data/ext/zsv/options_internal.h +8 -0
- data/ext/zsv/parser.c +300 -0
- data/ext/zsv/parser.h +62 -0
- data/ext/zsv/row.c +122 -0
- data/ext/zsv/row.h +39 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/2db.c +756 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/2json.c +381 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/2tsv.c +228 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/builtin/help.c +123 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/builtin/license.c +39 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/builtin/register.c +104 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/builtin/thirdparty.c +41 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/builtin/unregister.c +1 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/builtin/version.c +14 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/check/simdutf_wrapper.h +19 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/check/utf8.c +116 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/check.c +194 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/cli.c +796 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/cli_const.h +41 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/cli_export.h +16 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/cli_ini.c +280 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/cli_internal.h +36 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/compare.c +913 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/compare.h +23 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/compare_added_column.c +20 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/compare_internal.h +140 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/compare_sort.c +91 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/compare_unique_colname.c +81 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/count-pull.c +82 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/count.c +404 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/desc.c +569 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/echo.c +365 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/ext_example/my_extension.c +366 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/ext_example/mysheet_extension.c +341 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/ext_template/YOUR_EXTENSION_zsvext.c +263 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/inih/ini.c +298 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/inih/ini.h +157 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/json_numeric.c +177 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/jsonwriter.c +444 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/jsonwriter.h +145 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/utils.c +110 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/memfile-1.0/include/memfile.h +15 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/memfile-1.0/src/memfile.c +64 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sglib/sglib.h +1955 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/simdutf/simdutf.h +6802 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3.c +230517 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3.h +12174 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_and_csv_vtab.c +2 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab-mem.c +142 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab-mem.h +49 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab-zsv.c +485 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab.c +1015 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3ext.h +663 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/vtab_helper.c +85 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_common.h +75 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_gen.h +167 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_parse.h +228 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_tree.h +186 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_version.h +23 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_common.h +76 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_gen.h +167 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_parse.h +238 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_tree.h +186 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl.c +184 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_alloc.c +52 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_alloc.h +34 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_buf.c +103 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_buf.h +57 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_bytestack.h +69 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_encode.c +220 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_encode.h +34 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_gen.c +362 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_lex.c +764 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_lex.h +117 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_parser.c +508 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_parser.h +78 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_tree.c +505 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_version.c +7 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper/json_value.h +59 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper/yajl_helper.h +208 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper.c +795 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper_internal.h +28 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/flatten.c +851 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/jq.c +106 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/jq.h +6 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/mv.c +113 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/noop.c +90 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/overwrite.c +295 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/paste.c +175 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/pretty.c +693 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/prop.c +980 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/rm.c +131 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/fixed.c +130 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/internal.h +118 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/parallel.c +45 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/parallel.h +41 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/processing.c +107 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/rand.c +20 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/regex.c +61 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/search.c +14 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/selection.c +192 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select/usage.c +72 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select-pull.c +812 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/select.c +753 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/serialize.c +372 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/curses.h +15 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/cursor.c +119 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/errors.c +45 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/file.c +63 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/file.h +12 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/filter.c +166 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/handlers.c +214 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/handlers_internal.h +128 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/help.c +43 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/index.c +81 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/index.h +25 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/key-bindings.c +325 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/key-bindings.h +73 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/lexer.c +203 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/newline_handler.c +7 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/pivot.c +318 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/procedure.c +134 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/procedure.h +119 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/read-data.c +322 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/screen_buffer.c +203 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/screen_buffer.h +36 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/sheet-sql.c +167 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/sheet_internal.h +36 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/sqlfilter.c +153 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/terminfo.c +32 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/transformation.c +312 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/transformation.h +29 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/ui_buffer.c +266 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/usage.c +9 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet/utf8-width.c +60 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sheet.c +1007 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sql.c +453 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sql_internal.c +101 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/sql_internal.h +49 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/stack.c +393 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/arg.c +322 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/cache.c +228 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/cat.c +91 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/chunk.c +240 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/chunk.h +63 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/clock.c +57 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/db.c +148 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs-no-jq.c +2 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs.c +427 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs_from_json.c +253 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs_to_json.c +121 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/dl.c +20 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/emcc/fs_api.c +159 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/err.c +24 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/file-mem.c +180 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/file.c +256 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/index.c +197 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/index.h +49 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/jq.c +400 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/json.c +120 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/mem.c +18 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/memmem.c +132 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/os.c +178 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/overwrite.c +258 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/overwrite_writer.c +246 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/pcre2-8/pcre2-8-test.c +123 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/pcre2-8/pcre2-8.c +153 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/pcre2-8/pcre2-8.h +54 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/prop.c +267 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/signal.c +53 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/string.c +357 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/dir_exists_longpath.c +83 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/dl.c +33 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/fopen_longpath.c +184 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/foreach_dirent_longpath.c +292 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/io.c +259 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/io.h +13 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/mkdir_longpath.c +255 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/remove_longpath.c +96 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/utils/writer.c +361 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/zsv_command.h +40 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/zsv_command_standalone.c +16 -0
- data/ext/zsv/vendor/zsv-1.3.0/app/zsv_main.h +44 -0
- data/ext/zsv/vendor/zsv-1.3.0/examples/js/zsv_parser_api_dummy.c +3 -0
- data/ext/zsv/vendor/zsv-1.3.0/examples/lib/parse_by_chunk.c +100 -0
- data/ext/zsv/vendor/zsv-1.3.0/examples/lib/print_my_column.c +143 -0
- data/ext/zsv/vendor/zsv-1.3.0/examples/lib/pull.c +89 -0
- data/ext/zsv/vendor/zsv-1.3.0/examples/lib/simple.c +123 -0
- data/ext/zsv/vendor/zsv-1.3.0/fuzz/fuzz.c +16 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/api.h +336 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/common.h +361 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext/implementation.h +62 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext/implementation_private.h +113 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext/sheet.h +73 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext.h +329 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/arg.h +90 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/cache.h +49 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/clock.h +36 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/compiler.h +58 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/db.h +19 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/dirs.h +147 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/dl.h +22 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/emcc/fs_api.h +28 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/err.h +22 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/file-mem.h +17 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/file.h +99 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/jq.h +65 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/json.h +19 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/mem.h +19 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/memmem.h +13 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/os.h +54 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/overwrite.h +71 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/overwrite_writer.h +53 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/prop.h +107 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/signal.h +18 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/sql.h +11 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/string.h +148 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/utf8.h +41 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/win/dl.h +25 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/writer.h +101 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv/zsv_export.h +33 -0
- data/ext/zsv/vendor/zsv-1.3.0/include/zsv.h +20 -0
- data/ext/zsv/vendor/zsv-1.3.0/src/vector_delim.c +60 -0
- data/ext/zsv/vendor/zsv-1.3.0/src/zsv.c +484 -0
- data/ext/zsv/vendor/zsv-1.3.0/src/zsv_internal.c +731 -0
- data/ext/zsv/vendor/zsv-1.3.0/src/zsv_scan_delim.c +285 -0
- data/ext/zsv/vendor/zsv-1.3.0/src/zsv_scan_fixed.c +88 -0
- data/ext/zsv/vendor/zsv-1.3.0/src/zsv_strencode.c +51 -0
- data/ext/zsv/zsv_ext.c +343 -0
- data/lib/zsv/version.rb +5 -0
- data/lib/zsv.rb +81 -0
- metadata +340 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
2
|
+
#include <stdlib.h>
|
|
3
|
+
#include <string.h>
|
|
4
|
+
#include "./pcre2-8.h"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @brief Reads an entire file into a new buffer.
|
|
8
|
+
*
|
|
9
|
+
* @param filename The name of the file to read.
|
|
10
|
+
* @param out_size Pointer to a size_t to store the file size.
|
|
11
|
+
* @return A new buffer containing the file contents (must be free'd) or NULL on error.
|
|
12
|
+
*/
|
|
13
|
+
char *read_file_to_buffer(const char *filename, size_t *out_size) {
|
|
14
|
+
const char *tmp_filename = "./pcre2-8-test.temp";
|
|
15
|
+
if (!strcmp(filename, "-")) { // write stdin to temp file
|
|
16
|
+
FILE *tmp = fopen(tmp_filename, "wb");
|
|
17
|
+
if (!tmp) {
|
|
18
|
+
perror(tmp_filename);
|
|
19
|
+
return NULL;
|
|
20
|
+
}
|
|
21
|
+
size_t sz;
|
|
22
|
+
char buff[4096];
|
|
23
|
+
while ((sz = fread(buff, 1, sizeof(buff), stdin)) > 0)
|
|
24
|
+
fwrite(buff, 1, sz, tmp);
|
|
25
|
+
fclose(tmp);
|
|
26
|
+
filename = tmp_filename;
|
|
27
|
+
}
|
|
28
|
+
FILE *f = fopen(filename, "rb");
|
|
29
|
+
if (f == NULL) {
|
|
30
|
+
perror(filename);
|
|
31
|
+
return NULL;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Seek to end to find file size
|
|
35
|
+
if (fseek(f, 0, SEEK_END) != 0) {
|
|
36
|
+
perror("Error seeking in file");
|
|
37
|
+
fclose(f);
|
|
38
|
+
return NULL;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
long file_size = ftell(f);
|
|
42
|
+
if (file_size == -1) {
|
|
43
|
+
perror("Error getting file size");
|
|
44
|
+
fclose(f);
|
|
45
|
+
return NULL;
|
|
46
|
+
}
|
|
47
|
+
rewind(f); // Go back to the start
|
|
48
|
+
|
|
49
|
+
// Allocate buffer for file content + 1 for a null terminator
|
|
50
|
+
char *buffer = malloc(file_size + 1);
|
|
51
|
+
if (buffer == NULL) {
|
|
52
|
+
fprintf(stderr, "Error: Could not allocate memory for file.\n");
|
|
53
|
+
fclose(f);
|
|
54
|
+
return NULL;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Read the file
|
|
58
|
+
size_t bytes_read = fread(buffer, 1, file_size, f);
|
|
59
|
+
if (bytes_read != (size_t)file_size) {
|
|
60
|
+
fprintf(stderr, "Error reading file (read %zu, expected %ld).\n", bytes_read, file_size);
|
|
61
|
+
fclose(f);
|
|
62
|
+
free(buffer);
|
|
63
|
+
return NULL;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fclose(f);
|
|
67
|
+
buffer[file_size] = '\0'; // Null-terminate the string
|
|
68
|
+
*out_size = (size_t)file_size;
|
|
69
|
+
return buffer;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @brief Main entry point.
|
|
74
|
+
*
|
|
75
|
+
* Takes a regex pattern and a filename as command-line arguments.
|
|
76
|
+
*/
|
|
77
|
+
int main(int argc, char *argv[]) {
|
|
78
|
+
if (argc != 3) {
|
|
79
|
+
fprintf(stderr, "Usage: %s <pattern> <filename, or - for stdin>\n", argv[0]);
|
|
80
|
+
return 1;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const char *pattern_string = argv[1];
|
|
84
|
+
const char *filename = argv[2];
|
|
85
|
+
|
|
86
|
+
// Read file into memory
|
|
87
|
+
size_t file_size = 0;
|
|
88
|
+
char *file_content = read_file_to_buffer(filename, &file_size);
|
|
89
|
+
if (file_content == NULL) {
|
|
90
|
+
return 1; // Error already printed
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Compile the pattern (pass 0 for default options,
|
|
94
|
+
// PCRE2_UTF and PCRE2_MULTILINE are added by the library)
|
|
95
|
+
regex_handle_t *handle = zsv_pcre2_8_new(pattern_string, 0);
|
|
96
|
+
if (handle == NULL) {
|
|
97
|
+
fprintf(stderr, "Error compiling regex pattern.\n");
|
|
98
|
+
free(file_content);
|
|
99
|
+
return 1;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Check for anchors
|
|
103
|
+
if (zsv_pcre2_8_has_anchors(pattern_string)) {
|
|
104
|
+
printf("Pattern contains ^ or $ line anchors.\n");
|
|
105
|
+
} else {
|
|
106
|
+
printf("Pattern does not contain line anchors.\n");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Perform the match
|
|
110
|
+
int result = zsv_pcre2_8_match(handle, file_content, file_size);
|
|
111
|
+
|
|
112
|
+
if (result) {
|
|
113
|
+
printf("Match\n");
|
|
114
|
+
} else {
|
|
115
|
+
printf("No Match\n");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Clean up
|
|
119
|
+
zsv_pcre2_8_delete(handle);
|
|
120
|
+
free(file_content);
|
|
121
|
+
|
|
122
|
+
return 0;
|
|
123
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
#define PCRE2_CODE_UNIT_WIDTH 8
|
|
2
|
+
#include <pcre2.h>
|
|
3
|
+
#include <stdio.h>
|
|
4
|
+
#include <stdlib.h>
|
|
5
|
+
#include "pcre2-8.h"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @brief Defines the internal structure of the handle.
|
|
9
|
+
* We only need to store the compiled code.
|
|
10
|
+
*/
|
|
11
|
+
struct zsv_pcre2_handle {
|
|
12
|
+
pcre2_code *re;
|
|
13
|
+
pcre2_match_data *cached_match_data;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @brief Implementation of zsv_pcre2_8_new.
|
|
18
|
+
*/
|
|
19
|
+
regex_handle_t *zsv_pcre2_8_new(const char *pattern, uint32_t options) {
|
|
20
|
+
regex_handle_t *handle = calloc(1, sizeof(regex_handle_t));
|
|
21
|
+
if (handle == NULL) {
|
|
22
|
+
perror("zsv_pcre2_8_new");
|
|
23
|
+
return NULL;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
int error_number;
|
|
27
|
+
PCRE2_SIZE error_offset;
|
|
28
|
+
|
|
29
|
+
// utf-8 and multiline support
|
|
30
|
+
uint32_t compile_options = options | PCRE2_UTF | PCRE2_MULTILINE;
|
|
31
|
+
|
|
32
|
+
pcre2_compile_context *compile_context = pcre2_compile_context_create_8(NULL);
|
|
33
|
+
if (compile_context == NULL) {
|
|
34
|
+
printf("Error: Failed to create compile context.\n");
|
|
35
|
+
free(handle);
|
|
36
|
+
return NULL;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// set newline convention to '\0'
|
|
40
|
+
pcre2_set_newline_8(compile_context, PCRE2_NEWLINE_NUL);
|
|
41
|
+
|
|
42
|
+
handle->re = pcre2_compile_8((PCRE2_SPTR)pattern, // the pattern
|
|
43
|
+
PCRE2_ZERO_TERMINATED, // pattern is zero-terminated
|
|
44
|
+
compile_options, // user options + UTF + MULTILINE
|
|
45
|
+
&error_number, // for error number
|
|
46
|
+
&error_offset, // for error offset
|
|
47
|
+
compile_context // use our configured compile context
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// free the compile context (no longer needed)
|
|
51
|
+
pcre2_compile_context_free_8(compile_context);
|
|
52
|
+
|
|
53
|
+
if (handle->re == NULL) {
|
|
54
|
+
PCRE2_UCHAR buffer[256];
|
|
55
|
+
pcre2_get_error_message_8(error_number, buffer, sizeof(buffer));
|
|
56
|
+
printf("PCRE2 compilation failed for pattern \"%s\" at offset %d: %s\n", pattern, (int)error_offset, buffer);
|
|
57
|
+
free(handle);
|
|
58
|
+
return NULL;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
handle->cached_match_data = pcre2_match_data_create_from_pattern_8(handle->re, NULL);
|
|
62
|
+
|
|
63
|
+
return handle;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* @brief Implementation of zsv_pcre2_8_match.
|
|
68
|
+
*/
|
|
69
|
+
int zsv_pcre2_8_match(regex_handle_t *handle, const unsigned char *subject, size_t len) {
|
|
70
|
+
int rc = pcre2_match_8(handle->re, (PCRE2_SPTR)subject, len, 0, 0, handle->cached_match_data, NULL);
|
|
71
|
+
if (rc >= 0) // matched
|
|
72
|
+
return 1;
|
|
73
|
+
if (rc != PCRE2_ERROR_NOMATCH)
|
|
74
|
+
fprintf(stderr, "zsv_pcre2_8_match: match error %i\n", rc);
|
|
75
|
+
return 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* @brief Implementation of zsv_pcre2_8_has_anchors.
|
|
80
|
+
*/
|
|
81
|
+
int zsv_pcre2_8_has_anchors(const char *pattern) {
|
|
82
|
+
int in_char_class = 0;
|
|
83
|
+
|
|
84
|
+
if (pattern == NULL) {
|
|
85
|
+
return 0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
for (int i = 0; pattern[i] != '\0'; i++) {
|
|
89
|
+
// First, check for an escape character
|
|
90
|
+
if (pattern[i] == '\\') {
|
|
91
|
+
// Check how many backslashes precede this point
|
|
92
|
+
int backslash_count = 0;
|
|
93
|
+
for (int j = i - 1; j >= 0; j--) {
|
|
94
|
+
if (pattern[j] == '\\') {
|
|
95
|
+
backslash_count++;
|
|
96
|
+
} else {
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// If we are on an *escaped* backslash (e.g., "\\"),
|
|
101
|
+
// it doesn't escape the *next* character.
|
|
102
|
+
if (backslash_count % 2 == 0) {
|
|
103
|
+
// This backslash is NOT itself escaped, so it *will*
|
|
104
|
+
// escape the next character. Skip the next char.
|
|
105
|
+
i++;
|
|
106
|
+
if (pattern[i] == '\0') {
|
|
107
|
+
// Pattern ended with a backslash
|
|
108
|
+
return 0;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// If the backslash_count is odd, this backslash *is*
|
|
112
|
+
// escaped (e.g., "\\\^"), so it does NOT escape the
|
|
113
|
+
// next character. We just continue normally.
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// We are on a non-escaped character
|
|
118
|
+
if (in_char_class) {
|
|
119
|
+
if (pattern[i] == ']') {
|
|
120
|
+
in_char_class = 0;
|
|
121
|
+
}
|
|
122
|
+
// Inside a char class, all chars are treated as literals
|
|
123
|
+
// or class operators (like -), so we ignore ^ and $
|
|
124
|
+
} else {
|
|
125
|
+
switch (pattern[i]) {
|
|
126
|
+
case '[':
|
|
127
|
+
in_char_class = 1;
|
|
128
|
+
break;
|
|
129
|
+
case '^':
|
|
130
|
+
case '$':
|
|
131
|
+
// Found an unescaped anchor *outside* a char class
|
|
132
|
+
return 1;
|
|
133
|
+
default:
|
|
134
|
+
// Any other character
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return 0; // No anchors found
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* @brief Implementation of zsv_pcre2_8_delete.
|
|
144
|
+
*/
|
|
145
|
+
void zsv_pcre2_8_delete(regex_handle_t *handle) {
|
|
146
|
+
if (handle) {
|
|
147
|
+
if (handle->cached_match_data)
|
|
148
|
+
pcre2_match_data_free_8(handle->cached_match_data);
|
|
149
|
+
if (handle->re)
|
|
150
|
+
pcre2_code_free_8(handle->re);
|
|
151
|
+
free(handle);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#ifndef PCRE2_8_LIB_H
|
|
2
|
+
#define PCRE2_8_LIB_H
|
|
3
|
+
|
|
4
|
+
#include <stddef.h> // For size_t
|
|
5
|
+
#include <stdint.h> // For uint32_t
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @brief An opaque handle for a compiled regex pattern.
|
|
9
|
+
*/
|
|
10
|
+
typedef struct zsv_pcre2_handle regex_handle_t;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @brief Compiles a regex pattern into a handle for matching.
|
|
14
|
+
*
|
|
15
|
+
* This function automatically enables PCRE2_UTF, PCRE2_MULTILINE,
|
|
16
|
+
* and PCRE2_NEWLINE_NUL. This configures the multiline anchors (^ and $)
|
|
17
|
+
* to use '\0' (NULL) as the line delimiter.
|
|
18
|
+
*
|
|
19
|
+
* @param pattern The null-terminated, UTF-8 encoded regex pattern.
|
|
20
|
+
* @param options Additional PCRE2_COMPILE_... options to be OR'd in.
|
|
21
|
+
* @return A pointer to a handle, or NULL on compilation error.
|
|
22
|
+
*/
|
|
23
|
+
regex_handle_t *zsv_pcre2_8_new(const char *pattern, uint32_t options);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @brief Matches a compiled regex handle against a subject string.
|
|
27
|
+
*
|
|
28
|
+
* @param handle A valid handle returned from zsv_pcre2_8_new.
|
|
29
|
+
* @param subject The subject string to search.
|
|
30
|
+
* @param subject_length The length (in bytes) of the subject string.
|
|
31
|
+
* @return 1 if a match is found, 0 otherwise (no match or error).
|
|
32
|
+
*/
|
|
33
|
+
int zsv_pcre2_8_match(regex_handle_t *handle, const unsigned char *subject, size_t subject_length);
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @brief Checks if a pattern string contains any unescaped line anchors
|
|
37
|
+
* (^ or $) that are *not* inside a character class.
|
|
38
|
+
*
|
|
39
|
+
* This is a robust-enough check to see if a pattern is attempting
|
|
40
|
+
* line-based matching.
|
|
41
|
+
*
|
|
42
|
+
* @param pattern The null-terminated, UTF-8 encoded regex pattern.
|
|
43
|
+
* @return 1 if a line anchor is found, 0 otherwise.
|
|
44
|
+
*/
|
|
45
|
+
int zsv_pcre2_8_has_anchors(const char *pattern);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @brief Frees the resources associated with a regex handle.
|
|
49
|
+
*
|
|
50
|
+
* @param handle The handle to free.
|
|
51
|
+
*/
|
|
52
|
+
void zsv_pcre2_8_delete(regex_handle_t *handle);
|
|
53
|
+
|
|
54
|
+
#endif // PCRE2_8_LIB_H
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
#include <stdlib.h>
|
|
2
|
+
#include <string.h>
|
|
3
|
+
#include <limits.h>
|
|
4
|
+
#include <errno.h>
|
|
5
|
+
#include <zsv.h>
|
|
6
|
+
#include <zsv/utils/prop.h>
|
|
7
|
+
#include <zsv/utils/cache.h>
|
|
8
|
+
#include <zsv/utils/file.h>
|
|
9
|
+
#include <zsv/utils/overwrite.h>
|
|
10
|
+
#include <yajl_helper/yajl_helper.h>
|
|
11
|
+
|
|
12
|
+
#ifndef ZSVTLS
|
|
13
|
+
#ifndef NO_THREADING
|
|
14
|
+
#define ZSVTLS _Thread_local
|
|
15
|
+
#else
|
|
16
|
+
#define ZSVTLS
|
|
17
|
+
#endif
|
|
18
|
+
#endif
|
|
19
|
+
// see arg.c
|
|
20
|
+
|
|
21
|
+
static struct zsv_prop_handler *zsv_with_default_custom_prop_handler(char mode) {
|
|
22
|
+
ZSVTLS static char zsv_default_custom_prop_initd = 0;
|
|
23
|
+
ZSVTLS static struct zsv_prop_handler zsv_default_custom_prop_handler = {0};
|
|
24
|
+
|
|
25
|
+
switch (mode) {
|
|
26
|
+
case 'c': // clear
|
|
27
|
+
memset(&zsv_default_custom_prop_handler, 0, sizeof(zsv_default_custom_prop_handler));
|
|
28
|
+
zsv_default_custom_prop_initd = 0;
|
|
29
|
+
break;
|
|
30
|
+
case 'g': // get
|
|
31
|
+
if (!zsv_default_custom_prop_initd) {
|
|
32
|
+
zsv_default_custom_prop_initd = 1;
|
|
33
|
+
zsv_default_custom_prop_handler.handler = NULL;
|
|
34
|
+
zsv_default_custom_prop_handler.ctx = NULL;
|
|
35
|
+
}
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
return &zsv_default_custom_prop_handler;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
ZSV_EXPORT
|
|
42
|
+
void zsv_clear_default_custom_prop_handler(void) {
|
|
43
|
+
zsv_with_default_custom_prop_handler('c');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
ZSV_EXPORT
|
|
47
|
+
struct zsv_prop_handler zsv_get_default_custom_prop_handler(void) {
|
|
48
|
+
return *zsv_with_default_custom_prop_handler('g');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
ZSV_EXPORT
|
|
52
|
+
void zsv_set_default_custom_prop_handler(struct zsv_prop_handler custom_prop_handler) {
|
|
53
|
+
*zsv_with_default_custom_prop_handler(0) = custom_prop_handler;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// TO DO: import these through a proper header
|
|
57
|
+
static int zsv_properties_parse_process_value(yajl_helper_t yh, struct json_value *value);
|
|
58
|
+
|
|
59
|
+
struct zsv_properties_parser {
|
|
60
|
+
yajl_helper_t yh;
|
|
61
|
+
yajl_status stat;
|
|
62
|
+
|
|
63
|
+
// queryable data
|
|
64
|
+
struct zsv_file_properties *fp;
|
|
65
|
+
struct zsv_opts *opts;
|
|
66
|
+
struct zsv_prop_handler *custom_prop_handler;
|
|
67
|
+
const unsigned char *filepath; // path to this properties file
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const unsigned char *zsv_properties_parser_get_filepath(void *p_) {
|
|
71
|
+
struct zsv_properties_parser *p = p_;
|
|
72
|
+
return p ? p->filepath : NULL;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
void *zsv_properties_parser_get_custom_ctx(void *p_) {
|
|
76
|
+
struct zsv_properties_parser *p = p_;
|
|
77
|
+
return p && p->custom_prop_handler ? p->custom_prop_handler->ctx : NULL;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
struct zsv_opts *zsv_properties_parser_get_opts(void *p_) {
|
|
81
|
+
struct zsv_properties_parser *p = p_;
|
|
82
|
+
return p ? p->opts : NULL;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Create a new properties parser
|
|
87
|
+
*/
|
|
88
|
+
struct zsv_properties_parser *zsv_properties_parser_new(const unsigned char *path,
|
|
89
|
+
struct zsv_prop_handler *custom_prop_handler,
|
|
90
|
+
struct zsv_file_properties *fp, struct zsv_opts *opts) {
|
|
91
|
+
struct zsv_properties_parser *parser = calloc(1, sizeof(*parser));
|
|
92
|
+
if (parser) {
|
|
93
|
+
parser->yh = yajl_helper_new(32,
|
|
94
|
+
NULL, // start_map,
|
|
95
|
+
NULL, // end_map,
|
|
96
|
+
NULL, // map_key,
|
|
97
|
+
NULL, // start_array,
|
|
98
|
+
NULL, // end_array,
|
|
99
|
+
zsv_properties_parse_process_value, parser);
|
|
100
|
+
if (!parser->yh)
|
|
101
|
+
free(parser);
|
|
102
|
+
else {
|
|
103
|
+
parser->custom_prop_handler = custom_prop_handler;
|
|
104
|
+
parser->fp = fp;
|
|
105
|
+
parser->filepath = path;
|
|
106
|
+
parser->opts = opts;
|
|
107
|
+
parser->stat = yajl_status_ok;
|
|
108
|
+
return parser;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// error
|
|
112
|
+
return NULL;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Finished parsing
|
|
117
|
+
*/
|
|
118
|
+
enum zsv_status zsv_properties_parse_complete(struct zsv_properties_parser *parser) {
|
|
119
|
+
if (parser && parser->stat == yajl_status_ok)
|
|
120
|
+
parser->stat = yajl_complete_parse(yajl_helper_yajl(parser->yh));
|
|
121
|
+
return parser && parser->stat == yajl_status_ok ? zsv_status_ok : zsv_status_error;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Clean up
|
|
126
|
+
*/
|
|
127
|
+
enum zsv_status zsv_properties_parser_destroy(struct zsv_properties_parser *parser) {
|
|
128
|
+
yajl_helper_delete(parser->yh);
|
|
129
|
+
yajl_status stat = parser->stat;
|
|
130
|
+
free(parser);
|
|
131
|
+
return stat == yajl_status_ok ? zsv_status_ok : zsv_status_error;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Load cached file properties into a zsp_opts and/or zsv_file_properties struct
|
|
136
|
+
*
|
|
137
|
+
* @param data_filepath required file path
|
|
138
|
+
* @param opts (optional) parser options to load. will be updated to reflect
|
|
139
|
+
* what is actually used
|
|
140
|
+
* @param custom_prop_handler (optional) handler for custom properties
|
|
141
|
+
* @return zsv_status_ok on success
|
|
142
|
+
*/
|
|
143
|
+
struct zsv_file_properties zsv_cache_load_props(const char *data_filepath, struct zsv_opts *opts,
|
|
144
|
+
struct zsv_prop_handler *custom_prop_handler) {
|
|
145
|
+
// we need some memory to save the parsed properties
|
|
146
|
+
// if the caller did not provide that, use our own
|
|
147
|
+
struct zsv_file_properties tmp = {0};
|
|
148
|
+
if (!(data_filepath && *data_filepath))
|
|
149
|
+
return tmp; // e.g. input = stdin
|
|
150
|
+
|
|
151
|
+
struct zsv_file_properties *fp = &tmp;
|
|
152
|
+
struct zsv_properties_parser *p = NULL;
|
|
153
|
+
unsigned char *fn = zsv_cache_filepath((const unsigned char *)data_filepath, zsv_cache_type_property, 0, 0);
|
|
154
|
+
if (!fn)
|
|
155
|
+
tmp.stat = zsv_status_memory;
|
|
156
|
+
else {
|
|
157
|
+
FILE *f;
|
|
158
|
+
int err;
|
|
159
|
+
if (!zsv_file_readable((char *)fn, &err, &f)) {
|
|
160
|
+
if (err != ENOENT) {
|
|
161
|
+
perror((const char *)fn);
|
|
162
|
+
tmp.stat = zsv_status_error;
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
p = zsv_properties_parser_new(fn, custom_prop_handler, fp, opts);
|
|
166
|
+
if (!p)
|
|
167
|
+
tmp.stat = zsv_status_memory;
|
|
168
|
+
else if (p->stat != yajl_status_ok)
|
|
169
|
+
tmp.stat = zsv_status_error;
|
|
170
|
+
else {
|
|
171
|
+
unsigned char buff[1024];
|
|
172
|
+
size_t bytes_read;
|
|
173
|
+
while ((bytes_read = fread(buff, 1, sizeof(buff), f))) {
|
|
174
|
+
if ((p->stat = yajl_parse(yajl_helper_yajl(p->yh), buff, bytes_read)) != yajl_status_ok) {
|
|
175
|
+
tmp.stat = zsv_status_error;
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (tmp.stat == zsv_status_ok)
|
|
180
|
+
zsv_properties_parse_complete(p);
|
|
181
|
+
}
|
|
182
|
+
fclose(f);
|
|
183
|
+
}
|
|
184
|
+
free(fn);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (tmp.stat == zsv_status_ok) {
|
|
188
|
+
// warn if the loaded properties conflict with command-line options
|
|
189
|
+
if (fp->skip_specified) {
|
|
190
|
+
if (opts && opts->option_overrides.skip_head && opts->rows_to_ignore != fp->skip)
|
|
191
|
+
fprintf(stderr, "Warning: file property 'skip-head' overridden by command option\n");
|
|
192
|
+
else if (opts)
|
|
193
|
+
opts->rows_to_ignore = fp->skip;
|
|
194
|
+
}
|
|
195
|
+
if (fp->header_span_specified) {
|
|
196
|
+
if (opts && opts->option_overrides.header_row_span && opts->header_span != fp->header_span)
|
|
197
|
+
fprintf(stderr, "Warning: file property 'header-row-span' overridden by command option\n");
|
|
198
|
+
else if (opts)
|
|
199
|
+
opts->header_span = fp->header_span;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (p && tmp.stat == zsv_status_ok && zsv_properties_parser_destroy(p) != zsv_status_ok)
|
|
203
|
+
tmp.stat = zsv_status_error;
|
|
204
|
+
return tmp;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
static int zsv_properties_parse_process_value(yajl_helper_t yh, struct json_value *value) {
|
|
208
|
+
struct zsv_properties_parser *parser = yajl_helper_ctx(yh);
|
|
209
|
+
struct zsv_file_properties *fp = parser->fp;
|
|
210
|
+
if (yajl_helper_level_raw(yh) == 1) {
|
|
211
|
+
const char *prop_name = yajl_helper_get_map_key(yh, 0);
|
|
212
|
+
unsigned int *target = NULL;
|
|
213
|
+
if (!strcmp(prop_name, "skip-head")) {
|
|
214
|
+
target = &fp->skip;
|
|
215
|
+
fp->skip_specified = 1;
|
|
216
|
+
} else if (!strcmp(prop_name, "header-row-span")) {
|
|
217
|
+
target = &fp->header_span;
|
|
218
|
+
fp->header_span_specified = 1;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!target) {
|
|
222
|
+
int rc = 1;
|
|
223
|
+
struct zsv_prop_handler *custom_prop_handler = parser->custom_prop_handler;
|
|
224
|
+
if (custom_prop_handler && custom_prop_handler->handler)
|
|
225
|
+
rc = custom_prop_handler->handler(parser, prop_name, value);
|
|
226
|
+
if (rc) {
|
|
227
|
+
fprintf(stderr, "Unrecognized property: %s\n", prop_name);
|
|
228
|
+
fp->stat = zsv_status_error;
|
|
229
|
+
}
|
|
230
|
+
} else {
|
|
231
|
+
int err = 0;
|
|
232
|
+
long long i = json_value_long(value, &err);
|
|
233
|
+
if (err || i < 0 || i > UINT_MAX) {
|
|
234
|
+
fp->stat = zsv_status_error;
|
|
235
|
+
fprintf(stderr, "Invalid %s property value: should be an integer between 0 and %u", prop_name, UINT_MAX);
|
|
236
|
+
} else
|
|
237
|
+
*target = (unsigned int)i;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return 1;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* zsv_new_with_properties(): use in lieu of zsv_new() to also merge zsv options
|
|
245
|
+
* with any saved properties (such as rows_to_ignore or header_span) for the
|
|
246
|
+
* specified input file. In the event that saved properties conflict with a
|
|
247
|
+
* command-line option, the command-line option "wins" (the property value is
|
|
248
|
+
* ignored), but a warning is printed
|
|
249
|
+
*
|
|
250
|
+
* optional `struct zsv_file_properties` supports custom file property processing
|
|
251
|
+
*/
|
|
252
|
+
enum zsv_status zsv_new_with_properties(struct zsv_opts *opts, struct zsv_prop_handler *custom_prop_handler,
|
|
253
|
+
const char *input_path, zsv_parser *handle_out) {
|
|
254
|
+
*handle_out = NULL;
|
|
255
|
+
if (input_path) {
|
|
256
|
+
struct zsv_file_properties fp = zsv_cache_load_props(input_path, opts, custom_prop_handler);
|
|
257
|
+
if (fp.stat != zsv_status_ok)
|
|
258
|
+
return fp.stat;
|
|
259
|
+
}
|
|
260
|
+
#ifdef ZSV_EXTRAS
|
|
261
|
+
if (opts->overwrite_auto)
|
|
262
|
+
zsv_overwrite_auto(opts, input_path);
|
|
263
|
+
#endif
|
|
264
|
+
if ((*handle_out = zsv_new(opts)))
|
|
265
|
+
return zsv_status_ok;
|
|
266
|
+
return zsv_status_memory;
|
|
267
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2021 Liquidaty and the zsv/lib contributors
|
|
3
|
+
* All rights reserved
|
|
4
|
+
*
|
|
5
|
+
* This file is part of zsv/lib, distributed under the license defined at
|
|
6
|
+
* https://opensource.org/licenses/MIT
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#include <signal.h>
|
|
10
|
+
#include <stdio.h>
|
|
11
|
+
#include <string.h>
|
|
12
|
+
|
|
13
|
+
volatile sig_atomic_t zsv_signal_interrupted = 0;
|
|
14
|
+
|
|
15
|
+
#ifdef _WIN32
|
|
16
|
+
#include <windows.h>
|
|
17
|
+
|
|
18
|
+
static int consoleHandler(DWORD signal) {
|
|
19
|
+
if (signal == CTRL_C_EVENT) {
|
|
20
|
+
if (!zsv_signal_interrupted) {
|
|
21
|
+
zsv_signal_interrupted = 1;
|
|
22
|
+
fclose(stdin);
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void zsv_handle_ctrl_c_signal(void) {
|
|
30
|
+
if (!SetConsoleCtrlHandler(consoleHandler, 1))
|
|
31
|
+
fprintf(stderr, "Warning: unable to set signal handler\n");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#else
|
|
35
|
+
|
|
36
|
+
// handle signal interrupts: first Ctrl-C sets interrupt
|
|
37
|
+
// second reverts to default Ctrl-C behavior
|
|
38
|
+
|
|
39
|
+
static void INThandler(int sig) {
|
|
40
|
+
signal(sig, SIG_IGN); // ignore
|
|
41
|
+
if (!zsv_signal_interrupted) {
|
|
42
|
+
zsv_signal_interrupted = 1;
|
|
43
|
+
signal(SIGINT, NULL); // restore default handler
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void zsv_handle_ctrl_c_signal(void) {
|
|
48
|
+
// sigaction only ADDs the handler instead of REPLACING it
|
|
49
|
+
// so we will use signal() instead
|
|
50
|
+
signal(SIGINT, INThandler);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#endif
|