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,263 @@
|
|
|
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 <stdio.h>
|
|
10
|
+
#include <stdlib.h>
|
|
11
|
+
#include <string.h>
|
|
12
|
+
#include <zsv/ext/implementation.h>
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* `zsv` can easily be extended by simply creating a shared library that
|
|
16
|
+
* implements the interface specified in zsv/ext/implementation.h
|
|
17
|
+
*
|
|
18
|
+
* This file is a template you can use to implement your own extension. All you
|
|
19
|
+
* need to do is customize the sections marked with the word `YOUR`
|
|
20
|
+
*
|
|
21
|
+
* e.g. `YOUR_COMMAND` or `... YOUR CODE GOES HERE ...`
|
|
22
|
+
*
|
|
23
|
+
* replace any occurrences of "YOUR_COMMAND" with your (first) command, and dupe
|
|
24
|
+
* any occurrences of "YOUR_COMMAND" for any additional commands
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Define our extension ID. You can make this anything you want, so long as it
|
|
29
|
+
* is comprised of two ascii characters. In the rest of this file commentary, XX
|
|
30
|
+
* refers to this extension ID
|
|
31
|
+
*/
|
|
32
|
+
#define ZSV_THIS_EXT_ID "xx" /* YOUR EXTENSION ID GOES HERE */
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Once the library file is created, you can run any commands it implements
|
|
36
|
+
* by naming the library file zsvext<id>, placing it in any folder that is
|
|
37
|
+
* in the system lib search path, or in the same folder as zsv, and running:
|
|
38
|
+
* `zsv XX-command`
|
|
39
|
+
*
|
|
40
|
+
* It's as simple as that!
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Below implements the following command(s):
|
|
45
|
+
* * `YOUR_COMMAND`: your first command description
|
|
46
|
+
* * [ ... `zsv XX-YOUR_COMMAND2` ]
|
|
47
|
+
* * [ ... ]
|
|
48
|
+
*
|
|
49
|
+
*
|
|
50
|
+
* in addition, users will see a brief description of our module if they execute:
|
|
51
|
+
* `zsv help` or `zsv help XX-<command>`
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* *Required*: define our extension id, which must be two characters in length
|
|
56
|
+
*/
|
|
57
|
+
const char *zsv_ext_id(void) {
|
|
58
|
+
return ZSV_THIS_EXT_ID;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* When our library is initialized, zsv will pass it the address of the zsvlib
|
|
63
|
+
* functions we will be using. We can keep track of this any way we want;
|
|
64
|
+
* in this example, we use a global variable to store the function pointers
|
|
65
|
+
*/
|
|
66
|
+
static struct zsv_ext_callbacks zsv_cb;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Each command must be implemented as a function with a signature
|
|
70
|
+
* as defined by `zsv_ext_main`. This is basically the same as a main() function,
|
|
71
|
+
* but with an additional preceding zsv_execution_context parameter.
|
|
72
|
+
* Here, we just declare the functions; we fully define them further below
|
|
73
|
+
*/
|
|
74
|
+
static enum zsv_ext_status YOUR_COMMAND_main(zsv_execution_context ctx, int argc, const char *argv[]);
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
static enum zsv_ext_status YOUR_COMMAND2_main(...);
|
|
78
|
+
static enum zsv_ext_status YOUR_COMMAND3_main(...);
|
|
79
|
+
...
|
|
80
|
+
*/
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* *Required*. Initialization is called when our extension is loaded. Our
|
|
84
|
+
* initialization routine uses `ext_add_command` to register our commands and
|
|
85
|
+
* `ext_set_help` to set the help text. For each registered command, we provide a
|
|
86
|
+
* `*_main()` callback for zsv to invoke when a user runs our command
|
|
87
|
+
*
|
|
88
|
+
* @param callbacks pointers to zsvlib functions that we must save for later use
|
|
89
|
+
* @param ctx context to be passed whenever we execute a zsvlib function from our init
|
|
90
|
+
* @return status code e.g. zsv_ext_status_ok
|
|
91
|
+
*/
|
|
92
|
+
enum zsv_ext_status zsv_ext_init(struct zsv_ext_callbacks *cb, zsv_execution_context ctx) {
|
|
93
|
+
zsv_cb = *cb;
|
|
94
|
+
zsv_cb.ext_set_help(ctx, "YOUR brief help message goes here");
|
|
95
|
+
zsv_cb.ext_set_license(ctx, "YOUR license text goes here");
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* In the common case where your extension uses third-party software, you can add
|
|
99
|
+
* the related licenses and acknowledgements here, which `zsv` will display whenever
|
|
100
|
+
* `zsv thirdparty` is invoked
|
|
101
|
+
*/
|
|
102
|
+
static const char *third_party_licenses[] = {"YOUR third-party licenses & acknowledgements go here", NULL};
|
|
103
|
+
zsv_cb.ext_set_thirdparty(ctx, third_party_licenses);
|
|
104
|
+
zsv_cb.ext_add_command(ctx, "YOUR_COMMAND", "YOUR command description", YOUR_COMMAND_main);
|
|
105
|
+
|
|
106
|
+
/* YOUR CODE GOES HERE if you will perform any one-time initialization / allocation */
|
|
107
|
+
return zsv_ext_status_ok;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* If you allocated resources in `zsv_ext_init()`
|
|
112
|
+
* then you can de-allocate them in `zsv_ext_exit()`
|
|
113
|
+
*/
|
|
114
|
+
enum zsv_ext_status zsv_ext_exit(void) {
|
|
115
|
+
/* YOUR CODE GOES HERE */
|
|
116
|
+
return zsv_ext_status_ok;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Now we are getting to the "meat" of our program. Each command will be defined by two
|
|
121
|
+
* functions:
|
|
122
|
+
* - a main routine, which initializes private data, calls the parser, then performs any final
|
|
123
|
+
* steps and/or cleanup
|
|
124
|
+
* - a row handler, which is called by the parser for each parsed row
|
|
125
|
+
*/
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Define a structure for our functions to store private state data
|
|
129
|
+
* which our functions can retrieve using the zsvlib callback `ext_get_context()`
|
|
130
|
+
*/
|
|
131
|
+
struct xx_data {
|
|
132
|
+
size_t rows; /* Replace this line with YOUR data fields */
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Callback to initialize our private data
|
|
137
|
+
*/
|
|
138
|
+
static void xx_data_init(struct xx_data *data) {
|
|
139
|
+
/* YOUR CODE GOES HERE */
|
|
140
|
+
memset(data, 0, sizeof(*data));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Callback to clean up our private data
|
|
145
|
+
*/
|
|
146
|
+
static void xx_data_free(struct xx_data *data) {
|
|
147
|
+
/* YOUR CODE GOES HERE */
|
|
148
|
+
(void)(data);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Our row handlers retrieve our state data and update and/or operate on it
|
|
153
|
+
* We can choose, in our main routine, for the ctx pointer it receives to be
|
|
154
|
+
* anything we want, but in most cases there is no reason to set it to anything
|
|
155
|
+
* other than the zsv_execution_context passed to main
|
|
156
|
+
*
|
|
157
|
+
* @param ctx a context pointer of our choice, typically set in the main() function
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
static void YOUR_COMMAND_rowhandler(void *ctx) {
|
|
161
|
+
/* get our private data */
|
|
162
|
+
struct xx_data *data = zsv_cb.ext_get_context(ctx);
|
|
163
|
+
data->rows++; /* replace this line with YOUR CODE */
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* In most cases, we will want to do something with the row that was just parsed,
|
|
167
|
+
* in which case we can use ext_get_parser(), column_count() and get_cell()
|
|
168
|
+
* to get a parser handle, the number of cells in our current row, and each
|
|
169
|
+
* cell's length and string (and other info)
|
|
170
|
+
*/
|
|
171
|
+
zsv_parser parser = zsv_cb.ext_get_parser(ctx);
|
|
172
|
+
unsigned cell_count = zsv_cb.column_count(parser);
|
|
173
|
+
for (unsigned i = 0; i < cell_count; i++) {
|
|
174
|
+
/**
|
|
175
|
+
* get_cell() returns a zsv_cell structure that holds a pointer to the text,
|
|
176
|
+
* the length (in bytes) of the data,
|
|
177
|
+
* and other parser-generated info (e.g. QUOTED flags)
|
|
178
|
+
*/
|
|
179
|
+
struct zsv_cell c = zsv_cb.get_cell(parser, i);
|
|
180
|
+
/* YOUR CODE HERE to process each cell e.g. `fwrite(c.str, 1, c.len, stdout)` */
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Our main routines are similar to normal main() functions, except that the first
|
|
186
|
+
* param is a zsvlib-generated zsv_execution_context pointer for use with other
|
|
187
|
+
* `ext_xxx` functions. All we do here is initialize our data, call the parser, and
|
|
188
|
+
* perform any final steps after all data has been processed
|
|
189
|
+
*/
|
|
190
|
+
static enum zsv_ext_status YOUR_COMMAND_main(zsv_execution_context ctx, int argc, const char *argv[]) {
|
|
191
|
+
/* initialize private data */
|
|
192
|
+
struct xx_data data;
|
|
193
|
+
xx_data_init(&data);
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* The following common parser options that are already handled by zsv (so long as we use
|
|
197
|
+
* either of the provided callbacks `ext_parse_all()` or `new_with_context()`), including:
|
|
198
|
+
* ```
|
|
199
|
+
* -B,--buff-size <N>
|
|
200
|
+
* -c,--max-column-count <N>
|
|
201
|
+
* -r,--max-row-size <N>
|
|
202
|
+
* -t,--tab-delim
|
|
203
|
+
* -O,--other-delim <C>
|
|
204
|
+
* -q,--no-quote
|
|
205
|
+
* -v,--verbose
|
|
206
|
+
* ```
|
|
207
|
+
*
|
|
208
|
+
* If we wanted our command to support parameters for modifying other
|
|
209
|
+
* `zsv_opts`, we could do so here by processing argc and argv[] and taking
|
|
210
|
+
* the appropriate actions to change our private data and/or modify our opts
|
|
211
|
+
* structure
|
|
212
|
+
*/
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* If your process needs only to read a single input table sequentially from
|
|
216
|
+
* a FILE pointer, you can simplify your code by using `ext_parse_all()`,
|
|
217
|
+
* a convenience function that:
|
|
218
|
+
* 1. binds our custom context (in this case, a pointer to our `xx_data`
|
|
219
|
+
* structure) to the execution context, so that our row handler can
|
|
220
|
+
* retrieve it using `ext_get_context()`
|
|
221
|
+
* 2. parses the specified input (in our case, the default which is stdin) and
|
|
222
|
+
* binds the parser to the execution context, so that our row handler can
|
|
223
|
+
* retrieve it (and the current row's data) using `ext_get_parser()`
|
|
224
|
+
* 3. cleans up / deallocates the parser and related resources
|
|
225
|
+
*/
|
|
226
|
+
enum zsv_ext_status stat = zsv_cb.ext_parse_all(ctx, &data, YOUR_COMMAND_rowhandler, NULL);
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Alternatively, for more granular control we could use the following:
|
|
230
|
+
* ```
|
|
231
|
+
* struct zsv_opts opts = zsv_cb.ext_parser_opts(ctx);
|
|
232
|
+
* zsv_parser parser = new_with_context(ctx, &opts);
|
|
233
|
+
* if(!parser)
|
|
234
|
+
* stat = zsv_ext_status_memory;
|
|
235
|
+
* else {
|
|
236
|
+
* opts.row = YOUR_COMMAND_rowhandler;
|
|
237
|
+
* // ... set other options here ...
|
|
238
|
+
* zsv_parser p = new_with_context(ctx, &opts);
|
|
239
|
+
* while((stat = zsv_parse_more(parser)) == zsv_status_ok) ;
|
|
240
|
+
* if(stat == zsv_status_ok)
|
|
241
|
+
* stat = zsv_finish(p);
|
|
242
|
+
* zsv_delete(p);
|
|
243
|
+
* }
|
|
244
|
+
* ```
|
|
245
|
+
*/
|
|
246
|
+
|
|
247
|
+
/* done parsing */
|
|
248
|
+
if (stat == zsv_ext_status_ok) {
|
|
249
|
+
/* Successful run. Replace the below line with YOUR CODE */
|
|
250
|
+
printf("Rows: %zu\n", data.rows > 0 ? data.rows - 1 : 0);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/* clean up */
|
|
254
|
+
xx_data_free(&data);
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* the return value of the main function will be passed on as the return value
|
|
258
|
+
* of this process invocation
|
|
259
|
+
*/
|
|
260
|
+
return stat;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
#undef ZSV_THIS_EXT_ID
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/* inih -- simple .INI file parser
|
|
2
|
+
|
|
3
|
+
SPDX-License-Identifier: BSD-3-Clause
|
|
4
|
+
|
|
5
|
+
Copyright (C) 2009-2020, Ben Hoyt
|
|
6
|
+
|
|
7
|
+
inih is released under the New BSD license (see LICENSE.txt). Go to the project
|
|
8
|
+
home page for more info:
|
|
9
|
+
|
|
10
|
+
https://github.com/benhoyt/inih
|
|
11
|
+
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
|
|
15
|
+
#define _CRT_SECURE_NO_WARNINGS
|
|
16
|
+
#endif
|
|
17
|
+
|
|
18
|
+
#include <stdio.h>
|
|
19
|
+
#include <ctype.h>
|
|
20
|
+
#include <string.h>
|
|
21
|
+
|
|
22
|
+
#include "ini.h"
|
|
23
|
+
|
|
24
|
+
#if !INI_USE_STACK
|
|
25
|
+
#if INI_CUSTOM_ALLOCATOR
|
|
26
|
+
#include <stddef.h>
|
|
27
|
+
void* ini_malloc(size_t size);
|
|
28
|
+
void ini_free(void* ptr);
|
|
29
|
+
void* ini_realloc(void* ptr, size_t size);
|
|
30
|
+
#else
|
|
31
|
+
#include <stdlib.h>
|
|
32
|
+
#define ini_malloc malloc
|
|
33
|
+
#define ini_free free
|
|
34
|
+
#define ini_realloc realloc
|
|
35
|
+
#endif
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
#define MAX_SECTION 50
|
|
39
|
+
#define MAX_NAME 50
|
|
40
|
+
|
|
41
|
+
/* Used by ini_parse_string() to keep track of string parsing state. */
|
|
42
|
+
typedef struct {
|
|
43
|
+
const char* ptr;
|
|
44
|
+
size_t num_left;
|
|
45
|
+
} ini_parse_string_ctx;
|
|
46
|
+
|
|
47
|
+
/* Strip whitespace chars off end of given string, in place. Return s. */
|
|
48
|
+
static char* rstrip(char* s)
|
|
49
|
+
{
|
|
50
|
+
char* p = s + strlen(s);
|
|
51
|
+
while (p > s && isspace((unsigned char)(*--p)))
|
|
52
|
+
*p = '\0';
|
|
53
|
+
return s;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Return pointer to first non-whitespace char in given string. */
|
|
57
|
+
static char* lskip(const char* s)
|
|
58
|
+
{
|
|
59
|
+
while (*s && isspace((unsigned char)(*s)))
|
|
60
|
+
s++;
|
|
61
|
+
return (char*)s;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* Return pointer to first char (of chars) or inline comment in given string,
|
|
65
|
+
or pointer to NUL at end of string if neither found. Inline comment must
|
|
66
|
+
be prefixed by a whitespace character to register as a comment. */
|
|
67
|
+
static char* find_chars_or_comment(const char* s, const char* chars)
|
|
68
|
+
{
|
|
69
|
+
#if INI_ALLOW_INLINE_COMMENTS
|
|
70
|
+
int was_space = 0;
|
|
71
|
+
while (*s && (!chars || !strchr(chars, *s)) &&
|
|
72
|
+
!(was_space && strchr(INI_INLINE_COMMENT_PREFIXES, *s))) {
|
|
73
|
+
was_space = isspace((unsigned char)(*s));
|
|
74
|
+
s++;
|
|
75
|
+
}
|
|
76
|
+
#else
|
|
77
|
+
while (*s && (!chars || !strchr(chars, *s))) {
|
|
78
|
+
s++;
|
|
79
|
+
}
|
|
80
|
+
#endif
|
|
81
|
+
return (char*)s;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Similar to strncpy, but ensures dest (size bytes) is
|
|
85
|
+
NUL-terminated, and doesn't pad with NULs. */
|
|
86
|
+
static char* strncpy0(char* dest, const char* src, size_t size)
|
|
87
|
+
{
|
|
88
|
+
/* Could use strncpy internally, but it causes gcc warnings (see issue #91) */
|
|
89
|
+
size_t i;
|
|
90
|
+
for (i = 0; i < size - 1 && src[i]; i++)
|
|
91
|
+
dest[i] = src[i];
|
|
92
|
+
dest[i] = '\0';
|
|
93
|
+
return dest;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* See documentation in header file. */
|
|
97
|
+
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
|
|
98
|
+
void* user)
|
|
99
|
+
{
|
|
100
|
+
/* Uses a fair bit of stack (use heap instead if you need to) */
|
|
101
|
+
#if INI_USE_STACK
|
|
102
|
+
char line[INI_MAX_LINE];
|
|
103
|
+
int max_line = INI_MAX_LINE;
|
|
104
|
+
#else
|
|
105
|
+
char* line;
|
|
106
|
+
size_t max_line = INI_INITIAL_ALLOC;
|
|
107
|
+
#endif
|
|
108
|
+
#if INI_ALLOW_REALLOC && !INI_USE_STACK
|
|
109
|
+
char* new_line;
|
|
110
|
+
size_t offset;
|
|
111
|
+
#endif
|
|
112
|
+
char section[MAX_SECTION] = "";
|
|
113
|
+
char prev_name[MAX_NAME] = "";
|
|
114
|
+
|
|
115
|
+
char* start;
|
|
116
|
+
char* end;
|
|
117
|
+
char* name;
|
|
118
|
+
char* value;
|
|
119
|
+
int lineno = 0;
|
|
120
|
+
int error = 0;
|
|
121
|
+
|
|
122
|
+
#if !INI_USE_STACK
|
|
123
|
+
line = (char*)ini_malloc(INI_INITIAL_ALLOC);
|
|
124
|
+
if (!line) {
|
|
125
|
+
return -2;
|
|
126
|
+
}
|
|
127
|
+
#endif
|
|
128
|
+
|
|
129
|
+
#if INI_HANDLER_LINENO
|
|
130
|
+
#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
|
|
131
|
+
#else
|
|
132
|
+
#define HANDLER(u, s, n, v) handler(u, s, n, v)
|
|
133
|
+
#endif
|
|
134
|
+
|
|
135
|
+
/* Scan through stream line by line */
|
|
136
|
+
while (reader(line, (int)max_line, stream) != NULL) {
|
|
137
|
+
#if INI_ALLOW_REALLOC && !INI_USE_STACK
|
|
138
|
+
offset = strlen(line);
|
|
139
|
+
while (offset == max_line - 1 && line[offset - 1] != '\n') {
|
|
140
|
+
max_line *= 2;
|
|
141
|
+
if (max_line > INI_MAX_LINE)
|
|
142
|
+
max_line = INI_MAX_LINE;
|
|
143
|
+
new_line = ini_realloc(line, max_line);
|
|
144
|
+
if (!new_line) {
|
|
145
|
+
ini_free(line);
|
|
146
|
+
return -2;
|
|
147
|
+
}
|
|
148
|
+
line = new_line;
|
|
149
|
+
if (reader(line + offset, (int)(max_line - offset), stream) == NULL)
|
|
150
|
+
break;
|
|
151
|
+
if (max_line >= INI_MAX_LINE)
|
|
152
|
+
break;
|
|
153
|
+
offset += strlen(line + offset);
|
|
154
|
+
}
|
|
155
|
+
#endif
|
|
156
|
+
|
|
157
|
+
lineno++;
|
|
158
|
+
|
|
159
|
+
start = line;
|
|
160
|
+
#if INI_ALLOW_BOM
|
|
161
|
+
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
|
|
162
|
+
(unsigned char)start[1] == 0xBB &&
|
|
163
|
+
(unsigned char)start[2] == 0xBF) {
|
|
164
|
+
start += 3;
|
|
165
|
+
}
|
|
166
|
+
#endif
|
|
167
|
+
start = lskip(rstrip(start));
|
|
168
|
+
|
|
169
|
+
if (strchr(INI_START_COMMENT_PREFIXES, *start)) {
|
|
170
|
+
/* Start-of-line comment */
|
|
171
|
+
}
|
|
172
|
+
#if INI_ALLOW_MULTILINE
|
|
173
|
+
else if (*prev_name && *start && start > line) {
|
|
174
|
+
/* Non-blank line with leading whitespace, treat as continuation
|
|
175
|
+
of previous name's value (as per Python configparser). */
|
|
176
|
+
if (!HANDLER(user, section, prev_name, start) && !error)
|
|
177
|
+
error = lineno;
|
|
178
|
+
}
|
|
179
|
+
#endif
|
|
180
|
+
else if (*start == '[') {
|
|
181
|
+
/* A "[section]" line */
|
|
182
|
+
end = find_chars_or_comment(start + 1, "]");
|
|
183
|
+
if (*end == ']') {
|
|
184
|
+
*end = '\0';
|
|
185
|
+
strncpy0(section, start + 1, sizeof(section));
|
|
186
|
+
*prev_name = '\0';
|
|
187
|
+
#if INI_CALL_HANDLER_ON_NEW_SECTION
|
|
188
|
+
if (!HANDLER(user, section, NULL, NULL) && !error)
|
|
189
|
+
error = lineno;
|
|
190
|
+
#endif
|
|
191
|
+
}
|
|
192
|
+
else if (!error) {
|
|
193
|
+
/* No ']' found on section line */
|
|
194
|
+
error = lineno;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
else if (*start) {
|
|
198
|
+
/* Not a comment, must be a name[=:]value pair */
|
|
199
|
+
end = find_chars_or_comment(start, "=:");
|
|
200
|
+
if (*end == '=' || *end == ':') {
|
|
201
|
+
*end = '\0';
|
|
202
|
+
name = rstrip(start);
|
|
203
|
+
value = end + 1;
|
|
204
|
+
#if INI_ALLOW_INLINE_COMMENTS
|
|
205
|
+
end = find_chars_or_comment(value, NULL);
|
|
206
|
+
if (*end)
|
|
207
|
+
*end = '\0';
|
|
208
|
+
#endif
|
|
209
|
+
value = lskip(value);
|
|
210
|
+
rstrip(value);
|
|
211
|
+
|
|
212
|
+
/* Valid name[=:]value pair found, call handler */
|
|
213
|
+
strncpy0(prev_name, name, sizeof(prev_name));
|
|
214
|
+
if (!HANDLER(user, section, name, value) && !error)
|
|
215
|
+
error = lineno;
|
|
216
|
+
}
|
|
217
|
+
else if (!error) {
|
|
218
|
+
/* No '=' or ':' found on name[=:]value line */
|
|
219
|
+
#if INI_ALLOW_NO_VALUE
|
|
220
|
+
*end = '\0';
|
|
221
|
+
name = rstrip(start);
|
|
222
|
+
if (!HANDLER(user, section, name, NULL) && !error)
|
|
223
|
+
error = lineno;
|
|
224
|
+
#else
|
|
225
|
+
error = lineno;
|
|
226
|
+
#endif
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
#if INI_STOP_ON_FIRST_ERROR
|
|
231
|
+
if (error)
|
|
232
|
+
break;
|
|
233
|
+
#endif
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
#if !INI_USE_STACK
|
|
237
|
+
ini_free(line);
|
|
238
|
+
#endif
|
|
239
|
+
|
|
240
|
+
return error;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* See documentation in header file. */
|
|
244
|
+
int ini_parse_file(FILE* file, ini_handler handler, void* user)
|
|
245
|
+
{
|
|
246
|
+
return ini_parse_stream((ini_reader)fgets, file, handler, user);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* See documentation in header file. */
|
|
250
|
+
int ini_parse(const char* filename, ini_handler handler, void* user)
|
|
251
|
+
{
|
|
252
|
+
FILE* file;
|
|
253
|
+
int error;
|
|
254
|
+
|
|
255
|
+
file = fopen(filename, "r");
|
|
256
|
+
if (!file)
|
|
257
|
+
return -1;
|
|
258
|
+
error = ini_parse_file(file, handler, user);
|
|
259
|
+
fclose(file);
|
|
260
|
+
return error;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/* An ini_reader function to read the next line from a string buffer. This
|
|
264
|
+
is the fgets() equivalent used by ini_parse_string(). */
|
|
265
|
+
static char* ini_reader_string(char* str, int num, void* stream) {
|
|
266
|
+
ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream;
|
|
267
|
+
const char* ctx_ptr = ctx->ptr;
|
|
268
|
+
size_t ctx_num_left = ctx->num_left;
|
|
269
|
+
char* strp = str;
|
|
270
|
+
char c;
|
|
271
|
+
|
|
272
|
+
if (ctx_num_left == 0 || num < 2)
|
|
273
|
+
return NULL;
|
|
274
|
+
|
|
275
|
+
while (num > 1 && ctx_num_left != 0) {
|
|
276
|
+
c = *ctx_ptr++;
|
|
277
|
+
ctx_num_left--;
|
|
278
|
+
*strp++ = c;
|
|
279
|
+
if (c == '\n')
|
|
280
|
+
break;
|
|
281
|
+
num--;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
*strp = '\0';
|
|
285
|
+
ctx->ptr = ctx_ptr;
|
|
286
|
+
ctx->num_left = ctx_num_left;
|
|
287
|
+
return str;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/* See documentation in header file. */
|
|
291
|
+
int ini_parse_string(const char* string, ini_handler handler, void* user) {
|
|
292
|
+
ini_parse_string_ctx ctx;
|
|
293
|
+
|
|
294
|
+
ctx.ptr = string;
|
|
295
|
+
ctx.num_left = strlen(string);
|
|
296
|
+
return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler,
|
|
297
|
+
user);
|
|
298
|
+
}
|