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.
Files changed (240) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +36 -0
  3. data/LICENSE +21 -0
  4. data/README.md +311 -0
  5. data/ext/zsv/common.h +34 -0
  6. data/ext/zsv/extconf.rb +137 -0
  7. data/ext/zsv/options.c +126 -0
  8. data/ext/zsv/options.h +31 -0
  9. data/ext/zsv/options_internal.h +8 -0
  10. data/ext/zsv/parser.c +300 -0
  11. data/ext/zsv/parser.h +62 -0
  12. data/ext/zsv/row.c +122 -0
  13. data/ext/zsv/row.h +39 -0
  14. data/ext/zsv/vendor/zsv-1.3.0/app/2db.c +756 -0
  15. data/ext/zsv/vendor/zsv-1.3.0/app/2json.c +381 -0
  16. data/ext/zsv/vendor/zsv-1.3.0/app/2tsv.c +228 -0
  17. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/help.c +123 -0
  18. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/license.c +39 -0
  19. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/register.c +104 -0
  20. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/thirdparty.c +41 -0
  21. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/unregister.c +1 -0
  22. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/version.c +14 -0
  23. data/ext/zsv/vendor/zsv-1.3.0/app/check/simdutf_wrapper.h +19 -0
  24. data/ext/zsv/vendor/zsv-1.3.0/app/check/utf8.c +116 -0
  25. data/ext/zsv/vendor/zsv-1.3.0/app/check.c +194 -0
  26. data/ext/zsv/vendor/zsv-1.3.0/app/cli.c +796 -0
  27. data/ext/zsv/vendor/zsv-1.3.0/app/cli_const.h +41 -0
  28. data/ext/zsv/vendor/zsv-1.3.0/app/cli_export.h +16 -0
  29. data/ext/zsv/vendor/zsv-1.3.0/app/cli_ini.c +280 -0
  30. data/ext/zsv/vendor/zsv-1.3.0/app/cli_internal.h +36 -0
  31. data/ext/zsv/vendor/zsv-1.3.0/app/compare.c +913 -0
  32. data/ext/zsv/vendor/zsv-1.3.0/app/compare.h +23 -0
  33. data/ext/zsv/vendor/zsv-1.3.0/app/compare_added_column.c +20 -0
  34. data/ext/zsv/vendor/zsv-1.3.0/app/compare_internal.h +140 -0
  35. data/ext/zsv/vendor/zsv-1.3.0/app/compare_sort.c +91 -0
  36. data/ext/zsv/vendor/zsv-1.3.0/app/compare_unique_colname.c +81 -0
  37. data/ext/zsv/vendor/zsv-1.3.0/app/count-pull.c +82 -0
  38. data/ext/zsv/vendor/zsv-1.3.0/app/count.c +404 -0
  39. data/ext/zsv/vendor/zsv-1.3.0/app/desc.c +569 -0
  40. data/ext/zsv/vendor/zsv-1.3.0/app/echo.c +365 -0
  41. data/ext/zsv/vendor/zsv-1.3.0/app/ext_example/my_extension.c +366 -0
  42. data/ext/zsv/vendor/zsv-1.3.0/app/ext_example/mysheet_extension.c +341 -0
  43. data/ext/zsv/vendor/zsv-1.3.0/app/ext_template/YOUR_EXTENSION_zsvext.c +263 -0
  44. data/ext/zsv/vendor/zsv-1.3.0/app/external/inih/ini.c +298 -0
  45. data/ext/zsv/vendor/zsv-1.3.0/app/external/inih/ini.h +157 -0
  46. data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/json_numeric.c +177 -0
  47. data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/jsonwriter.c +444 -0
  48. data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/jsonwriter.h +145 -0
  49. data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/utils.c +110 -0
  50. data/ext/zsv/vendor/zsv-1.3.0/app/external/memfile-1.0/include/memfile.h +15 -0
  51. data/ext/zsv/vendor/zsv-1.3.0/app/external/memfile-1.0/src/memfile.c +64 -0
  52. data/ext/zsv/vendor/zsv-1.3.0/app/external/sglib/sglib.h +1955 -0
  53. data/ext/zsv/vendor/zsv-1.3.0/app/external/simdutf/simdutf.h +6802 -0
  54. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3.c +230517 -0
  55. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3.h +12174 -0
  56. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_and_csv_vtab.c +2 -0
  57. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab-mem.c +142 -0
  58. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab-mem.h +49 -0
  59. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab-zsv.c +485 -0
  60. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab.c +1015 -0
  61. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3ext.h +663 -0
  62. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/vtab_helper.c +85 -0
  63. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_common.h +75 -0
  64. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_gen.h +167 -0
  65. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_parse.h +228 -0
  66. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_tree.h +186 -0
  67. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_version.h +23 -0
  68. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_common.h +76 -0
  69. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_gen.h +167 -0
  70. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_parse.h +238 -0
  71. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_tree.h +186 -0
  72. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl.c +184 -0
  73. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_alloc.c +52 -0
  74. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_alloc.h +34 -0
  75. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_buf.c +103 -0
  76. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_buf.h +57 -0
  77. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_bytestack.h +69 -0
  78. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_encode.c +220 -0
  79. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_encode.h +34 -0
  80. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_gen.c +362 -0
  81. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_lex.c +764 -0
  82. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_lex.h +117 -0
  83. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_parser.c +508 -0
  84. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_parser.h +78 -0
  85. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_tree.c +505 -0
  86. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_version.c +7 -0
  87. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper/json_value.h +59 -0
  88. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper/yajl_helper.h +208 -0
  89. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper.c +795 -0
  90. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper_internal.h +28 -0
  91. data/ext/zsv/vendor/zsv-1.3.0/app/flatten.c +851 -0
  92. data/ext/zsv/vendor/zsv-1.3.0/app/jq.c +106 -0
  93. data/ext/zsv/vendor/zsv-1.3.0/app/jq.h +6 -0
  94. data/ext/zsv/vendor/zsv-1.3.0/app/mv.c +113 -0
  95. data/ext/zsv/vendor/zsv-1.3.0/app/noop.c +90 -0
  96. data/ext/zsv/vendor/zsv-1.3.0/app/overwrite.c +295 -0
  97. data/ext/zsv/vendor/zsv-1.3.0/app/paste.c +175 -0
  98. data/ext/zsv/vendor/zsv-1.3.0/app/pretty.c +693 -0
  99. data/ext/zsv/vendor/zsv-1.3.0/app/prop.c +980 -0
  100. data/ext/zsv/vendor/zsv-1.3.0/app/rm.c +131 -0
  101. data/ext/zsv/vendor/zsv-1.3.0/app/select/fixed.c +130 -0
  102. data/ext/zsv/vendor/zsv-1.3.0/app/select/internal.h +118 -0
  103. data/ext/zsv/vendor/zsv-1.3.0/app/select/parallel.c +45 -0
  104. data/ext/zsv/vendor/zsv-1.3.0/app/select/parallel.h +41 -0
  105. data/ext/zsv/vendor/zsv-1.3.0/app/select/processing.c +107 -0
  106. data/ext/zsv/vendor/zsv-1.3.0/app/select/rand.c +20 -0
  107. data/ext/zsv/vendor/zsv-1.3.0/app/select/regex.c +61 -0
  108. data/ext/zsv/vendor/zsv-1.3.0/app/select/search.c +14 -0
  109. data/ext/zsv/vendor/zsv-1.3.0/app/select/selection.c +192 -0
  110. data/ext/zsv/vendor/zsv-1.3.0/app/select/usage.c +72 -0
  111. data/ext/zsv/vendor/zsv-1.3.0/app/select-pull.c +812 -0
  112. data/ext/zsv/vendor/zsv-1.3.0/app/select.c +753 -0
  113. data/ext/zsv/vendor/zsv-1.3.0/app/serialize.c +372 -0
  114. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/curses.h +15 -0
  115. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/cursor.c +119 -0
  116. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/errors.c +45 -0
  117. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/file.c +63 -0
  118. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/file.h +12 -0
  119. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/filter.c +166 -0
  120. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/handlers.c +214 -0
  121. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/handlers_internal.h +128 -0
  122. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/help.c +43 -0
  123. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/index.c +81 -0
  124. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/index.h +25 -0
  125. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/key-bindings.c +325 -0
  126. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/key-bindings.h +73 -0
  127. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/lexer.c +203 -0
  128. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/newline_handler.c +7 -0
  129. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/pivot.c +318 -0
  130. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/procedure.c +134 -0
  131. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/procedure.h +119 -0
  132. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/read-data.c +322 -0
  133. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/screen_buffer.c +203 -0
  134. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/screen_buffer.h +36 -0
  135. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/sheet-sql.c +167 -0
  136. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/sheet_internal.h +36 -0
  137. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/sqlfilter.c +153 -0
  138. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/terminfo.c +32 -0
  139. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/transformation.c +312 -0
  140. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/transformation.h +29 -0
  141. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/ui_buffer.c +266 -0
  142. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/usage.c +9 -0
  143. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/utf8-width.c +60 -0
  144. data/ext/zsv/vendor/zsv-1.3.0/app/sheet.c +1007 -0
  145. data/ext/zsv/vendor/zsv-1.3.0/app/sql.c +453 -0
  146. data/ext/zsv/vendor/zsv-1.3.0/app/sql_internal.c +101 -0
  147. data/ext/zsv/vendor/zsv-1.3.0/app/sql_internal.h +49 -0
  148. data/ext/zsv/vendor/zsv-1.3.0/app/stack.c +393 -0
  149. data/ext/zsv/vendor/zsv-1.3.0/app/utils/arg.c +322 -0
  150. data/ext/zsv/vendor/zsv-1.3.0/app/utils/cache.c +228 -0
  151. data/ext/zsv/vendor/zsv-1.3.0/app/utils/cat.c +91 -0
  152. data/ext/zsv/vendor/zsv-1.3.0/app/utils/chunk.c +240 -0
  153. data/ext/zsv/vendor/zsv-1.3.0/app/utils/chunk.h +63 -0
  154. data/ext/zsv/vendor/zsv-1.3.0/app/utils/clock.c +57 -0
  155. data/ext/zsv/vendor/zsv-1.3.0/app/utils/db.c +148 -0
  156. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs-no-jq.c +2 -0
  157. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs.c +427 -0
  158. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs_from_json.c +253 -0
  159. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs_to_json.c +121 -0
  160. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dl.c +20 -0
  161. data/ext/zsv/vendor/zsv-1.3.0/app/utils/emcc/fs_api.c +159 -0
  162. data/ext/zsv/vendor/zsv-1.3.0/app/utils/err.c +24 -0
  163. data/ext/zsv/vendor/zsv-1.3.0/app/utils/file-mem.c +180 -0
  164. data/ext/zsv/vendor/zsv-1.3.0/app/utils/file.c +256 -0
  165. data/ext/zsv/vendor/zsv-1.3.0/app/utils/index.c +197 -0
  166. data/ext/zsv/vendor/zsv-1.3.0/app/utils/index.h +49 -0
  167. data/ext/zsv/vendor/zsv-1.3.0/app/utils/jq.c +400 -0
  168. data/ext/zsv/vendor/zsv-1.3.0/app/utils/json.c +120 -0
  169. data/ext/zsv/vendor/zsv-1.3.0/app/utils/mem.c +18 -0
  170. data/ext/zsv/vendor/zsv-1.3.0/app/utils/memmem.c +132 -0
  171. data/ext/zsv/vendor/zsv-1.3.0/app/utils/os.c +178 -0
  172. data/ext/zsv/vendor/zsv-1.3.0/app/utils/overwrite.c +258 -0
  173. data/ext/zsv/vendor/zsv-1.3.0/app/utils/overwrite_writer.c +246 -0
  174. data/ext/zsv/vendor/zsv-1.3.0/app/utils/pcre2-8/pcre2-8-test.c +123 -0
  175. data/ext/zsv/vendor/zsv-1.3.0/app/utils/pcre2-8/pcre2-8.c +153 -0
  176. data/ext/zsv/vendor/zsv-1.3.0/app/utils/pcre2-8/pcre2-8.h +54 -0
  177. data/ext/zsv/vendor/zsv-1.3.0/app/utils/prop.c +267 -0
  178. data/ext/zsv/vendor/zsv-1.3.0/app/utils/signal.c +53 -0
  179. data/ext/zsv/vendor/zsv-1.3.0/app/utils/string.c +357 -0
  180. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/dir_exists_longpath.c +83 -0
  181. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/dl.c +33 -0
  182. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/fopen_longpath.c +184 -0
  183. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/foreach_dirent_longpath.c +292 -0
  184. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/io.c +259 -0
  185. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/io.h +13 -0
  186. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/mkdir_longpath.c +255 -0
  187. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/remove_longpath.c +96 -0
  188. data/ext/zsv/vendor/zsv-1.3.0/app/utils/writer.c +361 -0
  189. data/ext/zsv/vendor/zsv-1.3.0/app/zsv_command.h +40 -0
  190. data/ext/zsv/vendor/zsv-1.3.0/app/zsv_command_standalone.c +16 -0
  191. data/ext/zsv/vendor/zsv-1.3.0/app/zsv_main.h +44 -0
  192. data/ext/zsv/vendor/zsv-1.3.0/examples/js/zsv_parser_api_dummy.c +3 -0
  193. data/ext/zsv/vendor/zsv-1.3.0/examples/lib/parse_by_chunk.c +100 -0
  194. data/ext/zsv/vendor/zsv-1.3.0/examples/lib/print_my_column.c +143 -0
  195. data/ext/zsv/vendor/zsv-1.3.0/examples/lib/pull.c +89 -0
  196. data/ext/zsv/vendor/zsv-1.3.0/examples/lib/simple.c +123 -0
  197. data/ext/zsv/vendor/zsv-1.3.0/fuzz/fuzz.c +16 -0
  198. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/api.h +336 -0
  199. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/common.h +361 -0
  200. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext/implementation.h +62 -0
  201. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext/implementation_private.h +113 -0
  202. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext/sheet.h +73 -0
  203. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext.h +329 -0
  204. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/arg.h +90 -0
  205. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/cache.h +49 -0
  206. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/clock.h +36 -0
  207. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/compiler.h +58 -0
  208. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/db.h +19 -0
  209. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/dirs.h +147 -0
  210. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/dl.h +22 -0
  211. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/emcc/fs_api.h +28 -0
  212. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/err.h +22 -0
  213. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/file-mem.h +17 -0
  214. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/file.h +99 -0
  215. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/jq.h +65 -0
  216. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/json.h +19 -0
  217. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/mem.h +19 -0
  218. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/memmem.h +13 -0
  219. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/os.h +54 -0
  220. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/overwrite.h +71 -0
  221. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/overwrite_writer.h +53 -0
  222. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/prop.h +107 -0
  223. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/signal.h +18 -0
  224. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/sql.h +11 -0
  225. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/string.h +148 -0
  226. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/utf8.h +41 -0
  227. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/win/dl.h +25 -0
  228. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/writer.h +101 -0
  229. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/zsv_export.h +33 -0
  230. data/ext/zsv/vendor/zsv-1.3.0/include/zsv.h +20 -0
  231. data/ext/zsv/vendor/zsv-1.3.0/src/vector_delim.c +60 -0
  232. data/ext/zsv/vendor/zsv-1.3.0/src/zsv.c +484 -0
  233. data/ext/zsv/vendor/zsv-1.3.0/src/zsv_internal.c +731 -0
  234. data/ext/zsv/vendor/zsv-1.3.0/src/zsv_scan_delim.c +285 -0
  235. data/ext/zsv/vendor/zsv-1.3.0/src/zsv_scan_fixed.c +88 -0
  236. data/ext/zsv/vendor/zsv-1.3.0/src/zsv_strencode.c +51 -0
  237. data/ext/zsv/zsv_ext.c +343 -0
  238. data/lib/zsv/version.rb +5 -0
  239. data/lib/zsv.rb +81 -0
  240. metadata +340 -0
@@ -0,0 +1,381 @@
1
+ /*
2
+ * Copyright (C) 2021-2022 Liquidaty and zsv contributors. All rights reserved.
3
+ * This file is part of zsv/lib, distributed under the license defined at
4
+ * https://opensource.org/licenses/MIT
5
+ */
6
+
7
+ #include <stdio.h>
8
+ #include <string.h>
9
+ #include <stdlib.h>
10
+ #include <jsonwriter.h>
11
+ #include <sqlite3.h>
12
+
13
+ #define ZSV_COMMAND 2json
14
+ #include "zsv_command.h"
15
+
16
+ #include <zsv/utils/writer.h>
17
+ #include <zsv/utils/mem.h>
18
+ #include <zsv/utils/db.h>
19
+
20
+ struct zsv_2json_header {
21
+ struct zsv_2json_header *next;
22
+ char *name;
23
+ };
24
+
25
+ #define LQ_2JSON_MAX_INDEXES 32
26
+
27
+ struct zsv_2json_data {
28
+ zsv_parser parser;
29
+ jsonwriter_handle jsw;
30
+
31
+ size_t rows_processed; // includes header row
32
+
33
+ struct {
34
+ const char *clauses[LQ_2JSON_MAX_INDEXES];
35
+ char unique[LQ_2JSON_MAX_INDEXES];
36
+ unsigned count;
37
+ } indexes;
38
+
39
+ struct zsv_2json_header *headers, *current_header;
40
+ struct zsv_2json_header **headers_next;
41
+
42
+ char *db_tablename;
43
+
44
+ #define ZSV_JSON_SCHEMA_OBJECT 1
45
+ #define ZSV_JSON_SCHEMA_DATABASE 2
46
+ unsigned char schema : 2;
47
+ unsigned char no_header : 1;
48
+ unsigned char no_empty : 1;
49
+ unsigned char err : 1;
50
+ unsigned char from_db : 1;
51
+ unsigned char compact : 1;
52
+ unsigned char _ : 1;
53
+ };
54
+
55
+ static void zsv_2json_cleanup(struct zsv_2json_data *data) {
56
+ for (struct zsv_2json_header *next, *h = data->headers; h; h = next) {
57
+ next = h->next;
58
+ if (h->name)
59
+ free(h->name);
60
+ free(h);
61
+ }
62
+ free(data->db_tablename);
63
+ }
64
+
65
+ static void write_header_cell(struct zsv_2json_data *data, const unsigned char *utf8_value, size_t len) {
66
+ if (data->schema == ZSV_JSON_SCHEMA_OBJECT) {
67
+ struct zsv_2json_header *h;
68
+ if (!(h = calloc(1, sizeof(*h)))) {
69
+ fprintf(stderr, "Out of memory!\n");
70
+ data->err = 1;
71
+ } else {
72
+ *data->headers_next = h;
73
+ data->headers_next = &h->next;
74
+ if ((h->name = malloc(len + 1))) {
75
+ memcpy(h->name, utf8_value, len);
76
+ h->name[len] = '\0';
77
+ }
78
+ }
79
+ } else {
80
+ // to do: add options to set data type, etc
81
+ jsonwriter_start_object(data->jsw);
82
+ jsonwriter_object_key(data->jsw, "name");
83
+ jsonwriter_strn(data->jsw, utf8_value, len);
84
+ jsonwriter_end(data->jsw);
85
+ }
86
+ }
87
+
88
+ static void write_data_cell(struct zsv_2json_data *data, const unsigned char *utf8_value, size_t len) {
89
+ if (data->schema == ZSV_JSON_SCHEMA_OBJECT) {
90
+ if (!data->current_header)
91
+ return;
92
+ char *current_header_name = data->current_header->name;
93
+ data->current_header = data->current_header->next;
94
+
95
+ if (len || !data->no_empty)
96
+ jsonwriter_object_key(data->jsw, current_header_name);
97
+ else
98
+ return;
99
+ }
100
+ jsonwriter_strn(data->jsw, utf8_value, len);
101
+ }
102
+
103
+ static char *zsv_2json_db_first_tname(sqlite3 *db) {
104
+ char *tname = NULL;
105
+ sqlite3_stmt *stmt = NULL;
106
+ const char *sql = "select name from sqlite_master where type = 'table'";
107
+ if (sqlite3_prepare_v2(db, sql, -1, &stmt, NULL) != SQLITE_OK)
108
+ fprintf(stderr, "Unable to prepare %s: %s\n", sql, sqlite3_errmsg(db));
109
+ else if (sqlite3_step(stmt) == SQLITE_ROW) {
110
+ const unsigned char *text = sqlite3_column_text(stmt, 0);
111
+ if (text) {
112
+ int len = sqlite3_column_bytes(stmt, 0);
113
+ tname = zsv_memdup(text, len);
114
+ }
115
+ }
116
+ if (stmt)
117
+ sqlite3_finalize(stmt);
118
+ return tname;
119
+ }
120
+
121
+ static void zsv_2json_row(void *ctx) {
122
+ struct zsv_2json_data *data = ctx;
123
+ unsigned int cols = zsv_cell_count(data->parser);
124
+ if (cols) {
125
+ char obj = 0;
126
+ char arr = 0;
127
+ if (!data->rows_processed) { // header row
128
+ jsonwriter_start_array(data->jsw); // start array of rows
129
+ if (data->schema == ZSV_JSON_SCHEMA_DATABASE) {
130
+ jsonwriter_start_object(data->jsw); // start this row
131
+ obj = 1;
132
+
133
+ if (data->db_tablename)
134
+ jsonwriter_object_cstr(data->jsw, "name", data->db_tablename);
135
+
136
+ // to do: check index syntax (as of now, we just take argument value
137
+ // as-is and assume it will translate into a valid SQLITE3 command)
138
+ char have_index = 0;
139
+ for (unsigned i = 0; i < data->indexes.count; i++) {
140
+ const char *name_start = data->indexes.clauses[i];
141
+ const char *on = strstr(name_start, " on ");
142
+ if (on) {
143
+ on += 4;
144
+ while (*on == ' ')
145
+ on++;
146
+ }
147
+ if (!on || !*on)
148
+ continue;
149
+
150
+ const char *name_end = name_start;
151
+ while (name_end && *name_end && *name_end != ' ')
152
+ name_end++;
153
+
154
+ if (name_end > name_start) {
155
+ if (!have_index) {
156
+ have_index = 1;
157
+ jsonwriter_object_object(data->jsw, "indexes");
158
+ }
159
+ char *tmp = zsv_memdup(name_start, name_end - name_start);
160
+ jsonwriter_object_object(data->jsw, tmp); // this index
161
+ free(tmp);
162
+ jsonwriter_object_cstr(data->jsw, "on", on);
163
+ if (data->indexes.unique[i])
164
+ jsonwriter_object_bool(data->jsw, "unique", 1);
165
+ jsonwriter_end_object(data->jsw); // end this index
166
+ }
167
+ }
168
+ if (have_index)
169
+ jsonwriter_end_object(data->jsw); // indexes
170
+
171
+ jsonwriter_object_array(data->jsw, "columns");
172
+ arr = 1;
173
+ } else if (data->schema != ZSV_JSON_SCHEMA_OBJECT) {
174
+ jsonwriter_start_array(data->jsw); // start this row
175
+ arr = 1;
176
+ }
177
+ } else { // processing a data row, not header row
178
+ if (data->schema == ZSV_JSON_SCHEMA_OBJECT) {
179
+ jsonwriter_start_object(data->jsw); // start this row
180
+ obj = 1;
181
+ } else {
182
+ if (data->rows_processed == 1 && data->schema == ZSV_JSON_SCHEMA_DATABASE)
183
+ jsonwriter_start_array(data->jsw); // start the table-data element
184
+ jsonwriter_start_array(data->jsw); // start this row
185
+ arr = 1;
186
+ }
187
+ }
188
+
189
+ for (unsigned int i = 0; i < cols; i++) {
190
+ struct zsv_cell cell = zsv_get_cell(data->parser, i);
191
+ // output this cell
192
+ if (!data->rows_processed && !data->no_header) // this is header row
193
+ write_header_cell(data, cell.str, cell.len);
194
+ else
195
+ write_data_cell(data, cell.str, cell.len);
196
+ }
197
+
198
+ // end this row
199
+ if (arr)
200
+ jsonwriter_end_array(data->jsw);
201
+ if (obj)
202
+ jsonwriter_end_object(data->jsw);
203
+ data->rows_processed++;
204
+ }
205
+ data->current_header = data->headers;
206
+ }
207
+
208
+ static int zsv_db2json(const char *input_filename, char **tname, jsonwriter_handle jsw) {
209
+ sqlite3 *db;
210
+ int rc =
211
+ sqlite3_open_v2(input_filename, &db, SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_SHAREDCACHE, NULL);
212
+ int err = 0;
213
+ if (!db)
214
+ fprintf(stderr, "Unable to open db at %s\n", input_filename), err = 1;
215
+ else if (rc != SQLITE_OK)
216
+ fprintf(stderr, "Unable to open db at %s: %s\n", input_filename, sqlite3_errmsg(db)), err = 1;
217
+ else if (!*tname)
218
+ *tname = zsv_2json_db_first_tname(db);
219
+
220
+ if (!*tname)
221
+ fprintf(stderr, "No table name provided, and none found in %s\n", input_filename), err = 1;
222
+ else
223
+ err = zsv_dbtable2json(db, *tname, jsw, 0);
224
+ return err;
225
+ }
226
+
227
+ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *optsp,
228
+ struct zsv_prop_handler *custom_prop_handler) {
229
+ struct zsv_opts opts = *optsp;
230
+ struct zsv_2json_data data = {0};
231
+ data.headers_next = &data.headers;
232
+
233
+ const char *usage[] = {
234
+ APPNAME ": streaming CSV to JSON converter, or SQLite3 DB to JSON converter",
235
+ "",
236
+ "Usage: " APPNAME " [options] [file.csv]",
237
+ "",
238
+ "Options:",
239
+ " -h,--help : show usage",
240
+ " -o,--output <filename> : filename to write output to",
241
+ " --compact : output compact JSON",
242
+ " --from-db : input is sqlite3 database",
243
+ " --db-table <table_name> : name of table in input database to convert",
244
+ " --object : output as array of objects",
245
+ " --no-empty : omit empty properties (only with --object)",
246
+ " --database : output in database schema",
247
+ " --no-header : treat the header row as a data row",
248
+ " --index <name_on_expr> : add index to database schema",
249
+ " --unique-index <name_on_expr> : add unique index to database schema",
250
+ NULL,
251
+ };
252
+
253
+ FILE *out = NULL;
254
+ const char *input_path = NULL;
255
+ enum zsv_status err = zsv_status_ok;
256
+ int done = 0;
257
+
258
+ for (int i = 1; !err && !done && i < argc; i++) {
259
+ if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
260
+ for (int j = 0; usage[j]; j++)
261
+ fprintf(stdout, "%s\n", usage[j]);
262
+ done = 1;
263
+ } else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--output")) {
264
+ if (++i >= argc)
265
+ fprintf(stderr, "%s option requires a filename value\n", argv[i - 1]), err = zsv_status_error;
266
+ else if (out && out != stdout)
267
+ fprintf(stderr, "Output file specified more than once\n"), err = zsv_status_error;
268
+ else if (!(out = fopen(argv[i], "wb")))
269
+ fprintf(stderr, "Unable to open for writing: %s\n", argv[i]), err = zsv_status_error;
270
+ } else if (!strcmp(argv[i], "--index") || !strcmp(argv[i], "--unique-index")) {
271
+ if (++i >= argc)
272
+ fprintf(stderr, "%s option requires a filename value\n", argv[i - 1]), err = zsv_status_error;
273
+ else if (data.indexes.count > LQ_2JSON_MAX_INDEXES)
274
+ fprintf(stderr, "Max index count exceeded; ignoring %s\n", argv[i]), err = zsv_status_error;
275
+ else if (!strstr(argv[i], " on "))
276
+ fprintf(stderr, "Index value should be in the form of 'index_name on expr'; got %s\n", argv[i]),
277
+ err = zsv_status_error;
278
+ else {
279
+ if (!strcmp(argv[i - 1], "--unique-index"))
280
+ data.indexes.unique[data.indexes.count] = 1;
281
+ data.indexes.clauses[data.indexes.count++] = argv[i];
282
+ }
283
+ } else if (!strcmp(argv[i], "--no-empty")) {
284
+ data.no_empty = 1;
285
+ } else if (!strcmp(argv[i], "--db-table")) {
286
+ if (++i >= argc)
287
+ fprintf(stderr, "%s option requires a table name value\n", argv[i - 1]), err = zsv_status_error;
288
+ else if (data.db_tablename)
289
+ fprintf(stderr, "%s option specified more than once\n", argv[i - 1]), err = zsv_status_error;
290
+ else
291
+ data.db_tablename = strdup(argv[i]);
292
+ } else if (!strcmp(argv[i], "--from-db")) {
293
+ if (++i >= argc)
294
+ fprintf(stderr, "%s option requires a filename value\n", argv[i - 1]), err = zsv_status_error;
295
+ else if (opts.stream)
296
+ fprintf(stderr, "Input file specified more than once\n"), err = zsv_status_error;
297
+ else if (!(opts.stream = fopen(argv[i], "rb")))
298
+ fprintf(stderr, "Unable to open for reading: %s\n", argv[i]), err = zsv_status_error;
299
+ else {
300
+ input_path = argv[i];
301
+ data.from_db = 1;
302
+ }
303
+ } else if (!strcmp(argv[i], "--database") || !strcmp(argv[i], "--object")) {
304
+ if (data.schema)
305
+ fprintf(stderr, "Output schema specified more than once\n"), err = zsv_status_error;
306
+ else if (!strcmp(argv[i], "--database"))
307
+ data.schema = ZSV_JSON_SCHEMA_DATABASE;
308
+ else
309
+ data.schema = ZSV_JSON_SCHEMA_OBJECT;
310
+ } else if (!strcmp(argv[i], "--no-header"))
311
+ data.no_header = 1;
312
+ else if (!strcmp(argv[i], "--compact"))
313
+ data.compact = 1;
314
+ else {
315
+ if (opts.stream)
316
+ fprintf(stderr, "Input file specified more than once\n"), err = zsv_status_error;
317
+ else if (!(opts.stream = fopen(argv[i], "rb")))
318
+ fprintf(stderr, "Unable to open for reading: %s\n", argv[i]), err = zsv_status_error;
319
+ else
320
+ input_path = argv[i];
321
+ }
322
+ }
323
+
324
+ if (!(err || done)) {
325
+ if (data.indexes.count && data.schema != ZSV_JSON_SCHEMA_DATABASE)
326
+ fprintf(stderr, "--index/--unique-index can only be used with --database\n"), err = zsv_status_error;
327
+ else if (data.no_header && data.schema)
328
+ fprintf(stderr, "--no-header cannot be used together with --object or --database\n"), err = zsv_status_error;
329
+ else if (data.no_empty && data.schema != ZSV_JSON_SCHEMA_OBJECT)
330
+ fprintf(stderr, "--no-empty can only be used with --object\n"), err = zsv_status_error;
331
+ else if (!opts.stream) {
332
+ if (data.from_db)
333
+ fprintf(stderr, "Database input specified, but no input file provided\n"), err = zsv_status_error;
334
+ else {
335
+ #ifdef NO_STDIN
336
+ fprintf(stderr, "Please specify an input file\n"), err = zsv_status_error;
337
+ #else
338
+ opts.stream = stdin;
339
+ #endif
340
+ }
341
+ }
342
+ }
343
+
344
+ if (!(err || done)) {
345
+ if (!out)
346
+ out = stdout;
347
+ if (!(data.jsw = jsonwriter_new(out)))
348
+ err = zsv_status_error;
349
+ else {
350
+ if (data.compact)
351
+ jsonwriter_set_option(data.jsw, jsonwriter_option_compact);
352
+ if (data.from_db) {
353
+ if (opts.stream != stdin) {
354
+ fclose(opts.stream);
355
+ opts.stream = NULL;
356
+ }
357
+ err = zsv_db2json(input_path, &data.db_tablename, data.jsw);
358
+ } else {
359
+ opts.row_handler = zsv_2json_row;
360
+ opts.ctx = &data;
361
+ if (zsv_new_with_properties(&opts, custom_prop_handler, input_path, &data.parser) == zsv_status_ok) {
362
+ zsv_handle_ctrl_c_signal();
363
+ while (!data.err && !zsv_signal_interrupted && zsv_parse_more(data.parser) == zsv_status_ok)
364
+ ;
365
+ zsv_finish(data.parser);
366
+ zsv_delete(data.parser);
367
+ jsonwriter_end_all(data.jsw);
368
+ }
369
+ err = data.err;
370
+ }
371
+ }
372
+ jsonwriter_delete(data.jsw);
373
+ }
374
+
375
+ zsv_2json_cleanup(&data);
376
+ if (opts.stream && opts.stream != stdin)
377
+ fclose(opts.stream);
378
+ if (out && out != stdout)
379
+ fclose(out);
380
+ return err;
381
+ }
@@ -0,0 +1,228 @@
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 <string.h>
11
+ #include <stdlib.h>
12
+ #define ZSV_COMMAND 2tsv
13
+ #include "zsv_command.h"
14
+
15
+ #include <zsv/utils/utf8.h>
16
+
17
+ enum zsv_2tsv_status {
18
+ zsv_2tsv_status_ok = 0,
19
+ zsv_2tsv_status_out_of_memory
20
+ };
21
+
22
+ #define ZSV_2TSV_BUFF_SIZE 65536
23
+
24
+ struct static_buff {
25
+ char *buff; // will be ZSV_2TSV_BUFF_SIZE
26
+ size_t used;
27
+ FILE *stream;
28
+ };
29
+
30
+ struct zsv_2tsv_data {
31
+ zsv_parser parser;
32
+ struct static_buff out;
33
+ unsigned char convert_to_space : 1;
34
+ unsigned char _ : 7;
35
+ };
36
+
37
+ __attribute__((always_inline)) static inline void zsv_2tsv_flush(struct static_buff *b) {
38
+ fwrite(b->buff, b->used, 1, b->stream);
39
+ b->used = 0;
40
+ }
41
+
42
+ static inline void zsv_2tsv_write(struct static_buff *b, const unsigned char *s, size_t n) {
43
+ if (n) {
44
+ if (VERY_UNLIKELY(n + b->used > ZSV_2TSV_BUFF_SIZE)) {
45
+ zsv_2tsv_flush(b);
46
+ if (VERY_UNLIKELY(n > ZSV_2TSV_BUFF_SIZE)) { // n too big, so write directly
47
+ fwrite(s, n, 1, b->stream);
48
+ return;
49
+ }
50
+ }
51
+ // n + used < buff size
52
+ memcpy(b->buff + b->used, s, n);
53
+ b->used += n;
54
+ }
55
+ }
56
+
57
+ // zsv_to_tsv(): convert, if necessary, to text suitable for tab-delimited output.
58
+ // - return NULL if nothing to convert
59
+ // - else, return allocated char * of converted tsv (caller must free), and update *lenp
60
+ // - on error, set *err
61
+ __attribute__((always_inline)) static inline unsigned char *zsv_to_tsv(const unsigned char *utf8, size_t *len,
62
+ enum zsv_2tsv_status *err,
63
+ char convert_to_space) {
64
+ // replace tab, newline and lf with \t, \n or \r or backslash
65
+ size_t do_convert = 0;
66
+ for (size_t i = 0; i < *len; i++) {
67
+ if (UNLIKELY(utf8[i] == '\t' || utf8[i] == '\n' || utf8[i] == '\r' || utf8[i] == '\\'))
68
+ do_convert++;
69
+ }
70
+ if (LIKELY(do_convert == 0))
71
+ return NULL;
72
+
73
+ unsigned char *converted = malloc(*len + do_convert + 1);
74
+ if (!converted)
75
+ *err = zsv_2tsv_status_out_of_memory;
76
+ else {
77
+ size_t j = 0;
78
+ for (size_t i = 0; i < *len; i++) {
79
+ if (UNLIKELY(utf8[i] == '\t' || utf8[i] == '\n' || utf8[i] == '\r' || utf8[i] == '\\')) {
80
+ if (convert_to_space)
81
+ converted[j++] = utf8[i] == '\\' ? '\\' : ' ';
82
+ else {
83
+ converted[j++] = '\\';
84
+ converted[j++] = utf8[i] == '\t' ? 't' : utf8[i] == '\n' ? 'n' : utf8[i] == '\r' ? 'r' : '\\';
85
+ }
86
+ } else
87
+ converted[j++] = utf8[i];
88
+ }
89
+ converted[j] = '\0';
90
+ *len = j;
91
+ }
92
+ return converted;
93
+ }
94
+
95
+ __attribute__((always_inline)) static inline void zsv_2tsv_cell(struct zsv_2tsv_data *data, unsigned char *utf8_value,
96
+ size_t len, char no_newline_or_slash,
97
+ char convert_to_space) {
98
+ // output cell contents (converted if necessary)
99
+ if (len) {
100
+ enum zsv_2tsv_status err = zsv_2tsv_status_ok;
101
+ if (VERY_LIKELY(no_newline_or_slash && !memchr(utf8_value, '\t', len))) {
102
+ zsv_2tsv_write(&data->out, utf8_value, len);
103
+ return;
104
+ }
105
+
106
+ // if we're here, there either definitely an embedded tab, or maybe an embedded \n or \r
107
+ unsigned char *converted = zsv_to_tsv(utf8_value, &len, &err, convert_to_space);
108
+ if (converted != NULL) {
109
+ zsv_2tsv_write(&data->out, converted, len);
110
+ free(converted);
111
+ } else if (UNLIKELY(err))
112
+ fprintf(stderr, "Out of memory!\n");
113
+ else
114
+ zsv_2tsv_write(&data->out, utf8_value, len);
115
+ }
116
+ }
117
+
118
+ static void zsv_2tsv_row(void *ctx) {
119
+ struct zsv_2tsv_data *data = ctx;
120
+ unsigned int cols = zsv_cell_count(data->parser);
121
+ if (cols) {
122
+ struct zsv_cell cell = zsv_get_cell(data->parser, 0);
123
+ struct zsv_cell end = zsv_get_cell(data->parser, cols - 1);
124
+ unsigned char *start = cell.str;
125
+ size_t row_len = end.str + end.len - start;
126
+ char no_newline_or_slash = 0;
127
+ if (LIKELY(!(memchr(start, '\n', row_len) || memchr(start, '\r', row_len) || memchr(start, '\\', row_len))))
128
+ no_newline_or_slash = 1;
129
+
130
+ const char convert_to_space = data->convert_to_space;
131
+ zsv_2tsv_cell(ctx, cell.str, cell.len, no_newline_or_slash, convert_to_space);
132
+ for (unsigned int i = 1; i < cols; i++) {
133
+ zsv_2tsv_write(&data->out, (const unsigned char *)"\t", 1);
134
+ cell = zsv_get_cell(data->parser, i);
135
+ zsv_2tsv_cell(ctx, cell.str, cell.len, no_newline_or_slash, convert_to_space);
136
+ }
137
+ }
138
+ zsv_2tsv_write(&data->out, (const unsigned char *)"\n", 1);
139
+ }
140
+
141
+ int zsv_2tsv_usage(int rc) {
142
+ static const char *zsv_2tsv_usage_msg[] = {
143
+ APPNAME ": convert CSV to TSV (tab-delimited text) suitable for simple-delimiter",
144
+ " text processing. By default, embedded tabs or multilines will be escaped",
145
+ " to \\t, \\n or \\r, respectively",
146
+ "",
147
+ "Usage: " APPNAME " [filename] [options]",
148
+ " e.g. " APPNAME " < file.csv > file.tsv",
149
+ "",
150
+ "Options:",
151
+ " -o <file> : save output to <file>",
152
+ " --convert-to-space: convert embedded \\t, \\n or \\r to space",
153
+ NULL,
154
+ };
155
+
156
+ for (size_t i = 0; zsv_2tsv_usage_msg[i]; i++)
157
+ fprintf(stdout, "%s\n", zsv_2tsv_usage_msg[i]);
158
+
159
+ return rc;
160
+ }
161
+
162
+ int ZSV_MAIN_FUNC(ZSV_COMMAND)(int argc, const char *argv[], struct zsv_opts *optsp,
163
+ struct zsv_prop_handler *custom_prop_handler) {
164
+ struct zsv_opts opts = *optsp;
165
+ struct zsv_2tsv_data data = {0};
166
+ const char *input_path = NULL;
167
+ int err = 0;
168
+ for (int i = 1; !err && i < argc; i++) {
169
+ if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h"))
170
+ return zsv_2tsv_usage(0);
171
+ if (!strcmp(argv[i], "--convert-to-space"))
172
+ data.convert_to_space = 1;
173
+ else if (!strcmp(argv[i], "-o") || !strcmp(argv[i], "--output")) {
174
+ if (++i >= argc)
175
+ fprintf(stderr, "%s option requires a filename value\n", argv[i - 1]), err = 1;
176
+ else if (data.out.stream && data.out.stream != stdout)
177
+ fprintf(stderr, "Output file specified more than once\n"), err = 1;
178
+ else if (!(data.out.stream = fopen(argv[i], "wb")))
179
+ fprintf(stderr, "Unable to open for writing: %s\n", argv[i]), err = 1;
180
+ } else {
181
+ if (opts.stream)
182
+ fprintf(stderr, "Input file specified more than once\n"), err = 1;
183
+ else if (!(opts.stream = fopen(argv[i], "rb")))
184
+ fprintf(stderr, "Unable to open for reading: %s\n", argv[i]), err = 1;
185
+ else
186
+ input_path = argv[i];
187
+ }
188
+ }
189
+
190
+ if (err) {
191
+ goto exit_2tsv;
192
+ }
193
+
194
+ if (!opts.stream) {
195
+ #ifdef NO_STDIN
196
+ fprintf(stderr, "Please specify an input file\n");
197
+ err = 1;
198
+ goto exit_2tsv;
199
+ #else
200
+ opts.stream = stdin;
201
+ #endif
202
+ }
203
+
204
+ if (!data.out.stream)
205
+ data.out.stream = stdout;
206
+
207
+ opts.row_handler = zsv_2tsv_row;
208
+ opts.ctx = &data;
209
+ if (zsv_new_with_properties(&opts, custom_prop_handler, input_path, &data.parser) == zsv_status_ok) {
210
+ char output[ZSV_2TSV_BUFF_SIZE];
211
+ data.out.buff = output;
212
+
213
+ zsv_handle_ctrl_c_signal();
214
+ enum zsv_status status;
215
+ while (!zsv_signal_interrupted && (status = zsv_parse_more(data.parser)) == zsv_status_ok)
216
+ ;
217
+ zsv_finish(data.parser);
218
+ zsv_delete(data.parser);
219
+ zsv_2tsv_flush(&data.out);
220
+ }
221
+
222
+ exit_2tsv:
223
+ if (opts.stream && opts.stream != stdin)
224
+ fclose(opts.stream);
225
+ if (data.out.stream && data.out.stream != stdout)
226
+ fclose(data.out.stream);
227
+ return err;
228
+ }