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,400 @@
|
|
|
1
|
+
#include <string.h>
|
|
2
|
+
#include <stdlib.h>
|
|
3
|
+
#include <zsv/utils/string.h>
|
|
4
|
+
#include <zsv/utils/writer.h>
|
|
5
|
+
#include <zsv/utils/jq.h>
|
|
6
|
+
#include <jq.h>
|
|
7
|
+
#include <jv.h>
|
|
8
|
+
|
|
9
|
+
// all jv_ functions defined here consume their jv value
|
|
10
|
+
// consumes:
|
|
11
|
+
// jv_string_length_bytes
|
|
12
|
+
// jv_dumpf
|
|
13
|
+
// jv_dump_string
|
|
14
|
+
//
|
|
15
|
+
// does not consume:
|
|
16
|
+
// jv_number_value
|
|
17
|
+
// jv_string_value
|
|
18
|
+
// jv_get_kind
|
|
19
|
+
|
|
20
|
+
static int jv_print_scalar_str(jv value, char inside_string, FILE *f, char as_csv) {
|
|
21
|
+
f = f ? f : stdout;
|
|
22
|
+
switch (jv_get_kind(value)) {
|
|
23
|
+
case JV_KIND_STRING: {
|
|
24
|
+
size_t len = jv_string_length_bytes(jv_copy(value));
|
|
25
|
+
const char *s = jv_string_value(value);
|
|
26
|
+
if (!as_csv)
|
|
27
|
+
fprintf(f, "%.*s", (int)len, s);
|
|
28
|
+
else {
|
|
29
|
+
unsigned char *csv = zsv_csv_quote((unsigned char *)s, len, NULL, 0);
|
|
30
|
+
if (!csv)
|
|
31
|
+
fprintf(f, "%.*s", (int)len, s);
|
|
32
|
+
else {
|
|
33
|
+
if (inside_string)
|
|
34
|
+
fprintf(f, "%s%.*s", inside_string > 1 ? ";" : "", (int)(strlen((char *)csv) - 2), csv + 1);
|
|
35
|
+
else
|
|
36
|
+
fprintf(f, "%s", csv);
|
|
37
|
+
free(csv);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
jv_free(value);
|
|
41
|
+
return 1;
|
|
42
|
+
} break;
|
|
43
|
+
default:
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
jv_free(value);
|
|
47
|
+
return 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static int jv_print_scalar(jv value, char inside_string, FILE *f, char as_csv) {
|
|
51
|
+
f = f ? f : stdout;
|
|
52
|
+
switch (jv_get_kind(value)) {
|
|
53
|
+
case JV_KIND_INVALID:
|
|
54
|
+
fprintf(f, "<invalid json>");
|
|
55
|
+
jv_free(value);
|
|
56
|
+
return 1;
|
|
57
|
+
case JV_KIND_NULL:
|
|
58
|
+
fprintf(f, "null");
|
|
59
|
+
jv_free(value);
|
|
60
|
+
return 1;
|
|
61
|
+
case JV_KIND_TRUE:
|
|
62
|
+
fprintf(f, "true");
|
|
63
|
+
jv_free(value);
|
|
64
|
+
return 1;
|
|
65
|
+
case JV_KIND_FALSE:
|
|
66
|
+
fprintf(f, "false");
|
|
67
|
+
jv_free(value);
|
|
68
|
+
return 1;
|
|
69
|
+
case JV_KIND_NUMBER: {
|
|
70
|
+
char s[64];
|
|
71
|
+
int n = snprintf(s, sizeof(s), "%lf", jv_number_value(value));
|
|
72
|
+
if (n > 0 && (size_t)n < sizeof(s))
|
|
73
|
+
fprintf(f, "%.*s", (int)zsv_strip_trailing_zeros(s, n), s);
|
|
74
|
+
}
|
|
75
|
+
jv_free(value);
|
|
76
|
+
return 1;
|
|
77
|
+
default:
|
|
78
|
+
return jv_print_scalar_str(value, inside_string, f, as_csv);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static void jv_to_csv_aux(jv value, FILE *f, int inside_string) {
|
|
83
|
+
f = f ? f : stdout;
|
|
84
|
+
if (!jv_print_scalar(jv_copy(value), inside_string, f, 1)) {
|
|
85
|
+
switch (jv_get_kind(value)) {
|
|
86
|
+
case JV_KIND_ARRAY:
|
|
87
|
+
// flatten
|
|
88
|
+
if (!inside_string)
|
|
89
|
+
fprintf(f, "\"");
|
|
90
|
+
jv_array_foreach(value, i, item) {
|
|
91
|
+
if (i)
|
|
92
|
+
fprintf(f, ";");
|
|
93
|
+
jv_to_csv_aux(item, f, 1);
|
|
94
|
+
}
|
|
95
|
+
if (!inside_string)
|
|
96
|
+
fprintf(f, "\"");
|
|
97
|
+
break;
|
|
98
|
+
case JV_KIND_OBJECT:
|
|
99
|
+
// flatten
|
|
100
|
+
if (!inside_string)
|
|
101
|
+
fprintf(f, "\"");
|
|
102
|
+
jv_object_foreach(value, key, item) {
|
|
103
|
+
jv_print_scalar(key, 1, f, 1);
|
|
104
|
+
fprintf(f, ":");
|
|
105
|
+
jv_to_csv_aux(item, f, 1);
|
|
106
|
+
fprintf(f, ";");
|
|
107
|
+
}
|
|
108
|
+
if (!inside_string)
|
|
109
|
+
fprintf(f, "\"");
|
|
110
|
+
break;
|
|
111
|
+
default:
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
jv_free(value);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
size_t zsv_jq_fwrite1(void *restrict FILE_ptr, const void *restrict buff, size_t len) {
|
|
119
|
+
return fwrite(buff, len, 1, FILE_ptr);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
void jv_to_json_func(jv value, void *ctx) {
|
|
123
|
+
struct jv_to_json_ctx *data = ctx;
|
|
124
|
+
if (data->output_started)
|
|
125
|
+
data->write1(data->ctx, "\n", 1);
|
|
126
|
+
data->output_started = 1;
|
|
127
|
+
if (data->write1 == zsv_jq_fwrite1) {
|
|
128
|
+
if (data->raw_output && jv_get_kind(value) == JV_KIND_STRING)
|
|
129
|
+
fwrite(jv_string_value(value), 1, jv_string_length_bytes(jv_copy(value)), data->ctx);
|
|
130
|
+
else
|
|
131
|
+
jv_dumpf(value, data->ctx, data->flags);
|
|
132
|
+
} else {
|
|
133
|
+
// jv_dump_string is memory-inefficient
|
|
134
|
+
// would be better to create custom dump function that, instead of writing to string buffer,
|
|
135
|
+
// could directly invoke func()
|
|
136
|
+
jv jv_s = jv_dump_string(value, data->flags);
|
|
137
|
+
const char *p = jv_string_value(jv_s);
|
|
138
|
+
size_t len = jv_string_length_bytes(jv_copy(jv_s));
|
|
139
|
+
if (len)
|
|
140
|
+
data->write1(data->ctx, p, len);
|
|
141
|
+
jv_free(jv_s);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
void jv_to_csv_multi(jv value, void *jv_to_csv_multi_ctx) {
|
|
146
|
+
struct jv_to_csv_multi_ctx *ctx = jv_to_csv_multi_ctx;
|
|
147
|
+
FILE *f = ctx->get_file(ctx->ctx);
|
|
148
|
+
jv_to_csv(value, f);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
void jv_to_csv(jv value, void *file) {
|
|
152
|
+
FILE *f = file;
|
|
153
|
+
f = f ? f : stdout;
|
|
154
|
+
if (jv_print_scalar(jv_copy(value), 0, f, 1))
|
|
155
|
+
fprintf(f, "\n");
|
|
156
|
+
else {
|
|
157
|
+
switch (jv_get_kind(value)) {
|
|
158
|
+
case JV_KIND_ARRAY:
|
|
159
|
+
jv_array_foreach(value, i, item) {
|
|
160
|
+
if (i)
|
|
161
|
+
fprintf(f, ",");
|
|
162
|
+
jv_to_csv_aux(item, f, 0);
|
|
163
|
+
}
|
|
164
|
+
fprintf(f, "\n");
|
|
165
|
+
break;
|
|
166
|
+
case JV_KIND_OBJECT:
|
|
167
|
+
jv_object_foreach(value, key, item) {
|
|
168
|
+
jv_print_scalar(key, 0, f, 1);
|
|
169
|
+
fprintf(f, ",");
|
|
170
|
+
jv_to_csv_aux(item, f, 0);
|
|
171
|
+
fprintf(f, "\n");
|
|
172
|
+
}
|
|
173
|
+
fprintf(f, "\n");
|
|
174
|
+
break;
|
|
175
|
+
default:
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
jv_free(value);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
static void jv_to_txt_aux(jv value, FILE *f) {
|
|
183
|
+
f = f ? f : stdout;
|
|
184
|
+
if (!jv_print_scalar(jv_copy(value), 0, f, 0)) {
|
|
185
|
+
switch (jv_get_kind(value)) {
|
|
186
|
+
case JV_KIND_ARRAY:
|
|
187
|
+
// flatten
|
|
188
|
+
fprintf(f, "[");
|
|
189
|
+
jv_array_foreach(value, i, item) {
|
|
190
|
+
if (i)
|
|
191
|
+
fprintf(f, ";");
|
|
192
|
+
jv_to_txt_aux(item, f);
|
|
193
|
+
}
|
|
194
|
+
fprintf(f, "]");
|
|
195
|
+
break;
|
|
196
|
+
case JV_KIND_OBJECT:
|
|
197
|
+
// flatten
|
|
198
|
+
fprintf(f, "{");
|
|
199
|
+
jv_object_foreach(value, key, item) {
|
|
200
|
+
jv_print_scalar(key, 1, f, 0);
|
|
201
|
+
fprintf(f, ":");
|
|
202
|
+
jv_to_txt_aux(item, f);
|
|
203
|
+
fprintf(f, ";");
|
|
204
|
+
}
|
|
205
|
+
fprintf(f, "}");
|
|
206
|
+
break;
|
|
207
|
+
default:
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
jv_free(value);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
void jv_to_txt(jv value, void *file) {
|
|
215
|
+
FILE *f = file;
|
|
216
|
+
f = f ? f : stdout;
|
|
217
|
+
if (jv_print_scalar(jv_copy(value), 0, f, 0))
|
|
218
|
+
fprintf(f, "\n");
|
|
219
|
+
else {
|
|
220
|
+
switch (jv_get_kind(value)) {
|
|
221
|
+
case JV_KIND_ARRAY:
|
|
222
|
+
jv_array_foreach(value, i, item) {
|
|
223
|
+
if (i)
|
|
224
|
+
fprintf(f, ",");
|
|
225
|
+
jv_to_txt_aux(item, f);
|
|
226
|
+
}
|
|
227
|
+
fprintf(f, "\n");
|
|
228
|
+
break;
|
|
229
|
+
case JV_KIND_OBJECT:
|
|
230
|
+
jv_object_foreach(value, key, item) {
|
|
231
|
+
jv_print_scalar(key, 0, f, 0);
|
|
232
|
+
fprintf(f, ",");
|
|
233
|
+
jv_to_txt_aux(item, f);
|
|
234
|
+
fprintf(f, "\n");
|
|
235
|
+
}
|
|
236
|
+
fprintf(f, "\n");
|
|
237
|
+
break;
|
|
238
|
+
default:
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
jv_free(value);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
void jv_to_lqjq(jv value, void *h) {
|
|
246
|
+
zsv_jq_handle lqjq = h;
|
|
247
|
+
|
|
248
|
+
// jv_dump_string is memory-inefficient
|
|
249
|
+
// would be better to create custom dump function that, instead of writing to string buffer,
|
|
250
|
+
// could directly invoke func()
|
|
251
|
+
jv jv_s = jv_dump_string(value, 0);
|
|
252
|
+
size_t len = jv_string_length_bytes(jv_copy(jv_s));
|
|
253
|
+
const char *p = jv_string_value(jv_s);
|
|
254
|
+
if (len)
|
|
255
|
+
zsv_jq_parse(lqjq, p, len);
|
|
256
|
+
jv_free(jv_s);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
struct zsv_jq_data {
|
|
260
|
+
void *jq;
|
|
261
|
+
struct jv_parser *parser;
|
|
262
|
+
void (*func)(jv, void *);
|
|
263
|
+
void *ctx;
|
|
264
|
+
|
|
265
|
+
FILE *trace;
|
|
266
|
+
enum zsv_jq_status status;
|
|
267
|
+
unsigned char non_null : 1;
|
|
268
|
+
unsigned char _ : 7;
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
static zsv_jq_handle zsv_jq_new_aux(const unsigned char *filter, void (*func)(jv, void *), void *ctx,
|
|
272
|
+
enum zsv_jq_status *statusp, int init_flags) {
|
|
273
|
+
enum zsv_jq_status status = zsv_jq_status_ok;
|
|
274
|
+
struct zsv_jq_data *d = calloc(1, sizeof(*d));
|
|
275
|
+
if (!d || !(d->jq = jq_init()) || !(d->parser = jv_parser_new(init_flags)))
|
|
276
|
+
status = zsv_jq_status_memory;
|
|
277
|
+
else if (!jq_compile(d->jq, (const char *)filter))
|
|
278
|
+
status = d->status = zsv_jq_status_compile;
|
|
279
|
+
if (status == zsv_jq_status_ok) {
|
|
280
|
+
d->func = func;
|
|
281
|
+
d->ctx = ctx;
|
|
282
|
+
} else {
|
|
283
|
+
zsv_jq_delete(d);
|
|
284
|
+
d = NULL;
|
|
285
|
+
}
|
|
286
|
+
if (statusp)
|
|
287
|
+
*statusp = status;
|
|
288
|
+
return d;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
zsv_jq_handle zsv_jq_new(const unsigned char *filter, void (*func)(jv, void *), void *ctx,
|
|
292
|
+
enum zsv_jq_status *statusp) {
|
|
293
|
+
return zsv_jq_new_aux(filter, func, ctx, statusp, 0);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
zsv_jq_handle zsv_jq_new_stream(const unsigned char *filter, void (*func)(jv, void *), void *ctx,
|
|
297
|
+
enum zsv_jq_status *statusp) {
|
|
298
|
+
return zsv_jq_new_aux(filter, func, ctx, statusp, JV_PARSE_STREAMING);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
void zsv_jq_delete(zsv_jq_handle h) {
|
|
302
|
+
if (h) {
|
|
303
|
+
if (h->parser)
|
|
304
|
+
jv_parser_free(h->parser);
|
|
305
|
+
if (h->jq)
|
|
306
|
+
jq_teardown((jq_state **)&h->jq);
|
|
307
|
+
free(h);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
static int zsv_jq_process(jq_state *jq, jv value, void (*func)(jv, void *), void *ctx);
|
|
312
|
+
|
|
313
|
+
size_t zsv_jq_write(const char *s, size_t n, size_t m, zsv_jq_handle h) {
|
|
314
|
+
zsv_jq_parse(h, s, n * m);
|
|
315
|
+
return n * m;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
enum zsv_jq_status zsv_jq_parse_file(zsv_jq_handle h, FILE *f) {
|
|
319
|
+
char buff[4096];
|
|
320
|
+
for (size_t bytes_read = fread(buff, 1, sizeof(buff), f); bytes_read && h->status == zsv_jq_status_ok;
|
|
321
|
+
bytes_read = fread(buff, 1, sizeof(buff), f)) {
|
|
322
|
+
zsv_jq_parse(h, buff, bytes_read);
|
|
323
|
+
if (feof(f))
|
|
324
|
+
break;
|
|
325
|
+
}
|
|
326
|
+
return h->status;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
enum zsv_jq_status zsv_jq_parse(zsv_jq_handle restrict h, const void *restrict s, size_t len) {
|
|
330
|
+
if (h->status != zsv_jq_status_ok)
|
|
331
|
+
return h->status;
|
|
332
|
+
|
|
333
|
+
jv_parser_set_buf(h->parser, (const char *)s, len, 1);
|
|
334
|
+
if (h->trace)
|
|
335
|
+
fwrite(s, len, 1, h->trace);
|
|
336
|
+
|
|
337
|
+
jv value;
|
|
338
|
+
while (jv_is_valid(value = jv_parser_next(h->parser))) {
|
|
339
|
+
if (!h->non_null && jv_get_kind(value) != JV_KIND_NULL)
|
|
340
|
+
h->non_null = 1;
|
|
341
|
+
zsv_jq_process(h->jq, value, h->func, h->ctx);
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
jv msg = jv_invalid_get_msg(value);
|
|
345
|
+
if (jv_get_kind(msg) == JV_KIND_STRING) {
|
|
346
|
+
fprintf(stderr, "jq: parse error: %s\n", jv_string_value(msg));
|
|
347
|
+
h->status = zsv_jq_status_error;
|
|
348
|
+
} else
|
|
349
|
+
jv_free(msg);
|
|
350
|
+
jv_free(value);
|
|
351
|
+
|
|
352
|
+
return h->status;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
void zsv_jq_trace(zsv_jq_handle h, FILE *trace) {
|
|
356
|
+
if (h)
|
|
357
|
+
h->trace = trace;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
enum zsv_jq_status zsv_jq_finish(zsv_jq_handle h) {
|
|
361
|
+
jv value;
|
|
362
|
+
jv_parser_set_buf(h->parser, "", 0, 0);
|
|
363
|
+
while (jv_is_valid(value = jv_parser_next(h->parser)))
|
|
364
|
+
zsv_jq_process(h->jq, value, h->func, h->ctx);
|
|
365
|
+
return zsv_jq_status_ok;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
static int zsv_jq_process(jq_state *jq,
|
|
369
|
+
jv value, // will be consumed
|
|
370
|
+
void (*func)(jv, void *), void *ctx) {
|
|
371
|
+
int ret = 14; // No valid results && -e -> exit(4)
|
|
372
|
+
jq_start(jq, value, 0); // consumes value
|
|
373
|
+
|
|
374
|
+
jv result;
|
|
375
|
+
while (jv_is_valid(result = jq_next(jq))) {
|
|
376
|
+
ret = 0;
|
|
377
|
+
func(result, ctx);
|
|
378
|
+
}
|
|
379
|
+
jv_free(result);
|
|
380
|
+
|
|
381
|
+
return ret;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
void jv_to_bool(jv value, void *char_result) {
|
|
385
|
+
char *c = char_result;
|
|
386
|
+
switch (jv_get_kind(value)) {
|
|
387
|
+
case JV_KIND_TRUE:
|
|
388
|
+
*c = 1;
|
|
389
|
+
break;
|
|
390
|
+
case JV_KIND_FALSE:
|
|
391
|
+
*c = 0;
|
|
392
|
+
break;
|
|
393
|
+
case JV_KIND_NUMBER:
|
|
394
|
+
*c = (jv_number_value(value) > 0);
|
|
395
|
+
break;
|
|
396
|
+
default:
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
jv_free(value);
|
|
400
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
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 <stdlib.h>
|
|
10
|
+
#include <string.h>
|
|
11
|
+
#include <stddef.h>
|
|
12
|
+
|
|
13
|
+
static inline char is_json_esc_char(unsigned char c) {
|
|
14
|
+
return (c == '"' || c == '\\' || c < 32);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static void str2hex(unsigned char *to, const unsigned char *p, size_t len) {
|
|
18
|
+
static const char *hex = "0123456789abcdef";
|
|
19
|
+
|
|
20
|
+
for (; len--; p++) {
|
|
21
|
+
*to++ = hex[p[0] >> 4];
|
|
22
|
+
*to++ = hex[p[0] & 0x0f];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
static inline unsigned json_esc_char(unsigned char c, char replace[]) {
|
|
27
|
+
unsigned replacelen;
|
|
28
|
+
char hex = 0;
|
|
29
|
+
switch (c) {
|
|
30
|
+
case '"':
|
|
31
|
+
replace[1] = '"';
|
|
32
|
+
break;
|
|
33
|
+
case '\\':
|
|
34
|
+
replace[1] = '\\';
|
|
35
|
+
break;
|
|
36
|
+
case '\b':
|
|
37
|
+
replace[1] = 'b';
|
|
38
|
+
break;
|
|
39
|
+
case '\f':
|
|
40
|
+
replace[1] = 'f';
|
|
41
|
+
break;
|
|
42
|
+
case '\n':
|
|
43
|
+
replace[1] = 'n';
|
|
44
|
+
break;
|
|
45
|
+
case '\r':
|
|
46
|
+
replace[1] = 'r';
|
|
47
|
+
break;
|
|
48
|
+
case '\t':
|
|
49
|
+
replace[1] = 't';
|
|
50
|
+
break;
|
|
51
|
+
default:
|
|
52
|
+
hex = 1;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
replace[0] = '\\';
|
|
56
|
+
if (hex) {
|
|
57
|
+
// unicode-hex: but 2/3 are not always zeroes...
|
|
58
|
+
replace[1] = 'u';
|
|
59
|
+
replace[2] = '0';
|
|
60
|
+
replace[3] = '0';
|
|
61
|
+
str2hex((unsigned char *)replace + 4, &c, 1);
|
|
62
|
+
replacelen = 6;
|
|
63
|
+
replace[6] = '\0';
|
|
64
|
+
} else {
|
|
65
|
+
replacelen = 2;
|
|
66
|
+
replace[2] = '\0';
|
|
67
|
+
}
|
|
68
|
+
return replacelen;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static unsigned json_escaped_str_len(const unsigned char *s, size_t len) {
|
|
72
|
+
unsigned count = 0;
|
|
73
|
+
for (size_t i = 0; i < len; i++, count++) {
|
|
74
|
+
switch (s[i]) {
|
|
75
|
+
case '"':
|
|
76
|
+
case '\\':
|
|
77
|
+
case '\b':
|
|
78
|
+
case '\f':
|
|
79
|
+
case '\n':
|
|
80
|
+
case '\r':
|
|
81
|
+
case '\t':
|
|
82
|
+
count++;
|
|
83
|
+
break;
|
|
84
|
+
default:
|
|
85
|
+
if (s[i] < 31)
|
|
86
|
+
count += 6;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return count + 2; // + 2 for surrounding quotation marks
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
unsigned char *zsv_json_from_str_n(const unsigned char *s, size_t len) {
|
|
94
|
+
size_t new_len = json_escaped_str_len(s, len);
|
|
95
|
+
unsigned char *new_s = calloc(new_len + 2, sizeof(*new_s));
|
|
96
|
+
if (new_s) {
|
|
97
|
+
new_s[0] = new_s[new_len - 1] = (unsigned char)'"';
|
|
98
|
+
if (new_len == len + 2)
|
|
99
|
+
memcpy(new_s + 1, s, len);
|
|
100
|
+
else {
|
|
101
|
+
char replace[8];
|
|
102
|
+
for (size_t i = 0, j = 1; i < len && j < new_len - 1; i++) {
|
|
103
|
+
if (!is_json_esc_char(s[i]))
|
|
104
|
+
new_s[j++] = s[i];
|
|
105
|
+
else {
|
|
106
|
+
size_t rlen = json_esc_char(s[i], replace);
|
|
107
|
+
memcpy(new_s + j, replace, rlen);
|
|
108
|
+
j += rlen;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return new_s;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
unsigned char *zsv_json_from_str(const unsigned char *s) {
|
|
117
|
+
if (!s)
|
|
118
|
+
return (unsigned char *)strdup("null");
|
|
119
|
+
return zsv_json_from_str_n(s, strlen((const char *)s));
|
|
120
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
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 <stdlib.h> // calloc
|
|
10
|
+
#include <string.h> // memcpy
|
|
11
|
+
|
|
12
|
+
/* zsv_memdup(): return copy with double-NULL terminator. caller must free() */
|
|
13
|
+
void *zsv_memdup(const void *src, size_t n) {
|
|
14
|
+
void *m = calloc(1, n + 2);
|
|
15
|
+
if (n)
|
|
16
|
+
memcpy(m, src, n);
|
|
17
|
+
return m;
|
|
18
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// from musl 1.37.5 system/lib/libc/musl/src/string/memmem.c
|
|
2
|
+
// clang-format off
|
|
3
|
+
#include <string.h>
|
|
4
|
+
#include <stdint.h>
|
|
5
|
+
static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
|
|
6
|
+
{
|
|
7
|
+
uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1];
|
|
8
|
+
for (h++, k--; k; k--, hw = hw<<8 | *++h)
|
|
9
|
+
if (hw == nw) return (char *)h-1;
|
|
10
|
+
return 0;
|
|
11
|
+
}
|
|
12
|
+
static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
|
|
13
|
+
{
|
|
14
|
+
uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8;
|
|
15
|
+
uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8;
|
|
16
|
+
for (h+=2, k-=2; k; k--, hw = (hw|*++h)<<8)
|
|
17
|
+
if (hw == nw) return (char *)h-2;
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n)
|
|
21
|
+
{
|
|
22
|
+
uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3];
|
|
23
|
+
uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3];
|
|
24
|
+
for (h+=3, k-=3; k; k--, hw = hw<<8 | *++h)
|
|
25
|
+
if (hw == nw) return (char *)h-3;
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
#define MAX(a,b) ((a)>(b)?(a):(b))
|
|
29
|
+
#define MIN(a,b) ((a)<(b)?(a):(b))
|
|
30
|
+
#define BITOP(a,b,op) \
|
|
31
|
+
((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a))))
|
|
32
|
+
static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const unsigned char *n, size_t l)
|
|
33
|
+
{
|
|
34
|
+
size_t i, ip, jp, k, p, ms, p0, mem, mem0;
|
|
35
|
+
size_t byteset[32 / sizeof(size_t)] = { 0 };
|
|
36
|
+
size_t shift[256];
|
|
37
|
+
/* Computing length of needle and fill shift table */
|
|
38
|
+
for (i=0; i<l; i++)
|
|
39
|
+
BITOP(byteset, n[i], |=), shift[n[i]] = i+1;
|
|
40
|
+
/* Compute maximal suffix */
|
|
41
|
+
ip = -1; jp = 0; k = p = 1;
|
|
42
|
+
while (jp+k<l) {
|
|
43
|
+
if (n[ip+k] == n[jp+k]) {
|
|
44
|
+
if (k == p) {
|
|
45
|
+
jp += p;
|
|
46
|
+
k = 1;
|
|
47
|
+
} else k++;
|
|
48
|
+
} else if (n[ip+k] > n[jp+k]) {
|
|
49
|
+
jp += k;
|
|
50
|
+
k = 1;
|
|
51
|
+
p = jp - ip;
|
|
52
|
+
} else {
|
|
53
|
+
ip = jp++;
|
|
54
|
+
k = p = 1;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
ms = ip;
|
|
58
|
+
p0 = p;
|
|
59
|
+
/* And with the opposite comparison */
|
|
60
|
+
ip = -1; jp = 0; k = p = 1;
|
|
61
|
+
while (jp+k<l) {
|
|
62
|
+
if (n[ip+k] == n[jp+k]) {
|
|
63
|
+
if (k == p) {
|
|
64
|
+
jp += p;
|
|
65
|
+
k = 1;
|
|
66
|
+
} else k++;
|
|
67
|
+
} else if (n[ip+k] < n[jp+k]) {
|
|
68
|
+
jp += k;
|
|
69
|
+
k = 1;
|
|
70
|
+
p = jp - ip;
|
|
71
|
+
} else {
|
|
72
|
+
ip = jp++;
|
|
73
|
+
k = p = 1;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (ip+1 > ms+1) ms = ip;
|
|
77
|
+
else p = p0;
|
|
78
|
+
/* Periodic needle? */
|
|
79
|
+
if (memcmp(n, n+p, ms+1)) {
|
|
80
|
+
mem0 = 0;
|
|
81
|
+
p = MAX(ms, l-ms-1) + 1;
|
|
82
|
+
} else mem0 = l-p;
|
|
83
|
+
mem = 0;
|
|
84
|
+
/* Search loop */
|
|
85
|
+
for (;;) {
|
|
86
|
+
/* If remainder of haystack is shorter than needle, done */
|
|
87
|
+
if (z-h < l) return 0;
|
|
88
|
+
/* Check last byte first; advance by shift on mismatch */
|
|
89
|
+
if (BITOP(byteset, h[l-1], &)) {
|
|
90
|
+
k = l-shift[h[l-1]];
|
|
91
|
+
if (k) {
|
|
92
|
+
if (mem0 && mem && k < p) k = l-p;
|
|
93
|
+
h += k;
|
|
94
|
+
mem = 0;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
h += l;
|
|
99
|
+
mem = 0;
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
/* Compare right half */
|
|
103
|
+
for (k=MAX(ms+1,mem); k<l && n[k] == h[k]; k++);
|
|
104
|
+
if (k < l) {
|
|
105
|
+
h += k-ms;
|
|
106
|
+
mem = 0;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
/* Compare left half */
|
|
110
|
+
for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--);
|
|
111
|
+
if (k <= mem) return (char *)h;
|
|
112
|
+
h += p;
|
|
113
|
+
mem = mem0;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
void *zsvmemmem(const void *h0, size_t k, const void *n0, size_t l)
|
|
117
|
+
{
|
|
118
|
+
const unsigned char *h = h0, *n = n0;
|
|
119
|
+
/* Return immediately on empty needle */
|
|
120
|
+
if (!l) return (void *)h;
|
|
121
|
+
/* Return immediately when needle is longer than haystack */
|
|
122
|
+
if (k<l) return 0;
|
|
123
|
+
/* Use faster algorithms for short needles */
|
|
124
|
+
h = memchr(h0, *n, k);
|
|
125
|
+
if (!h || l==1) return (void *)h;
|
|
126
|
+
k -= h - (const unsigned char *)h0;
|
|
127
|
+
if (k<l) return 0;
|
|
128
|
+
if (l==2) return twobyte_memmem(h, k, n);
|
|
129
|
+
if (l==3) return threebyte_memmem(h, k, n);
|
|
130
|
+
if (l==4) return fourbyte_memmem(h, k, n);
|
|
131
|
+
return twoway_memmem(h, h+k, n, l);
|
|
132
|
+
}
|