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,255 @@
1
+ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
2
+ #include <windows.h> // For CreateDirectoryW, MultiByteToWideChar, GetLastError etc.
3
+ #include <stdio.h> // For printf, perror
4
+ #include <stdlib.h> // For malloc, free, exit
5
+ #include <string.h> // For strlen, strcpy, strncpy
6
+ #include <wchar.h> // For wide character types and functions like wcslen, wcscpy
7
+
8
+ #include "io.h"
9
+
10
+ /**
11
+ * @brief Creates a directory, supporting paths longer than MAX_PATH.
12
+ *
13
+ * This function uses the Windows API CreateDirectoryW with the \\?\ prefix
14
+ * to reliably create directories even if their absolute path exceeds the
15
+ * traditional MAX_PATH limit.
16
+ *
17
+ * @param path A UTF-8 encoded string representing the absolute path of the
18
+ * directory to create. Relative paths are NOT reliably handled.
19
+ * Forward slashes '/' will be converted to backslashes '\'.
20
+ * @return 0 on success (directory created or already exists).
21
+ * Returns a non-zero Win32 error code on failure (see GetLastError()).
22
+ */
23
+
24
+ DWORD zsv_mkdir_winlp(const char *path_utf8) {
25
+ if (path_utf8 == NULL || path_utf8[0] == '\0') {
26
+ fprintf(stderr, "Error: Input path is NULL or empty.\n");
27
+ return ERROR_INVALID_PARAMETER; // Or another suitable error code
28
+ }
29
+
30
+ if (strlen(path_utf8) < 260) { // try the easy way first
31
+ int rc = mkdir(path_utf8);
32
+ if (!rc || rc == EEXIST)
33
+ return 0;
34
+ }
35
+
36
+ wchar_t *finalPath;
37
+ DWORD rc = zsv_pathToPrefixedWidePath(path_utf8, &finalPath);
38
+ if (rc)
39
+ return rc;
40
+
41
+ // 4. Call CreateDirectoryW
42
+ BOOL success = CreateDirectoryW(finalPath, NULL); // NULL for default security attributes
43
+
44
+ DWORD lastError = 0;
45
+ if (!success) {
46
+ lastError = GetLastError();
47
+ // It's okay if the directory already exists
48
+ if (lastError == ERROR_ALREADY_EXISTS) {
49
+ // printf("Debug: Directory already exists (considered success).\n");
50
+ lastError = 0; // Treat as success
51
+ } else {
52
+ fprintf(stderr, "Error: CreateDirectoryW failed (%lu) for path: %ls\n", lastError, finalPath);
53
+ }
54
+ } else {
55
+ // printf("Debug: CreateDirectoryW succeeded for path: %ls\n", finalPath);
56
+ lastError = 0; // Success
57
+ }
58
+
59
+ free(finalPath);
60
+
61
+ return lastError; // Return 0 on success (or already exists), else the error code
62
+ }
63
+
64
+ #ifdef DIRS_MKDIR_TEST
65
+ #define FILESLASH '\\'
66
+
67
+ #include "win/io.c"
68
+ #include "dirs_exists_longpath.c"
69
+ /**
70
+ * Check if a directory exists
71
+ * return true (non-zero) or false (zero)
72
+ */
73
+ int zsv_dir_exists(const char *path) {
74
+ #ifdef WIN32
75
+ if (strlen(path) >= MAX_PATH)
76
+ return zsv_dir_exists_winlp(path);
77
+
78
+ // TO DO: support win long filepath prefix
79
+ // TO DO: work properly if dir exists but we don't have permission
80
+ wchar_t wpath[MAX_PATH];
81
+ mbstowcs(wpath, path, MAX_PATH);
82
+
83
+ DWORD attrs = GetFileAttributesW(wpath);
84
+ if (attrs == INVALID_FILE_ATTRIBUTES)
85
+ // Could check GetLastError() to see if it's a permission issue vs. not-found
86
+ return 0;
87
+
88
+ // If it has the directory attribute, it's presumably a directory
89
+ return (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0;
90
+
91
+ #else
92
+ struct stat path_stat;
93
+ if (!stat(path, &path_stat))
94
+ return S_ISDIR(path_stat.st_mode);
95
+ return 0;
96
+ #endif
97
+ }
98
+
99
+ /**
100
+ * Make a directory, as well as any intermediate dirs
101
+ * return zero on success
102
+ */
103
+ #ifdef WIN32
104
+ #define zsv_mkdir zsv_mkdir_winlp
105
+ #else
106
+ #define zsv_mkdir mkdir
107
+ #endif
108
+ int zsv_mkdirs(const char *path, char path_is_filename) {
109
+ // int rc = 0;
110
+ if (!path || !*path)
111
+ return -1;
112
+ size_t len = strlen(path);
113
+
114
+ /*
115
+ #ifdef WIN32
116
+ // TO DO: handle windows long-file prefix "\\?\"
117
+ // for now, explicitly do not handle
118
+ if (len > 2 && path[2] == '?')
119
+ fprintf(stderr, "Invalid path (long file prefix not supported): %s\n", path);
120
+ #endif
121
+ */
122
+ if (len < 1) // || len > FILENAME_MAX)
123
+ return -1;
124
+
125
+ char *tmp = strdup(path);
126
+ if (!tmp) {
127
+ perror(path);
128
+ return -1;
129
+ }
130
+
131
+ if (len && strchr("/\\", tmp[len - 1]))
132
+ tmp[--len] = 0;
133
+
134
+ int offset = 0;
135
+ #ifdef WIN32
136
+ if (len > 1) {
137
+ // starts with two slashes
138
+ if (strchr("/\\", tmp[0]) && strchr("/\\", tmp[1])) {
139
+ offset = 2;
140
+ // find the next slash
141
+ char *path_end = tmp + 3;
142
+ while (*path_end && !strchr("/\\", *path_end))
143
+ path_end++;
144
+ if (*path_end)
145
+ path_end++;
146
+ if (*path_end)
147
+ offset = path_end - tmp;
148
+ else {
149
+ fprintf(stderr, "Invalid path: %s\n", path);
150
+ free(tmp);
151
+ return -1;
152
+ }
153
+ }
154
+ // starts with *:
155
+ else if (tmp[1] == ':')
156
+ offset = 2;
157
+ }
158
+ #else
159
+ offset = 1;
160
+ #endif
161
+
162
+ // TO DO: first find the longest subdir that exists, in *reverse* order so as
163
+ // to properly handle case where no access to intermediate dir,
164
+ // and then only start mkdir from there
165
+ int last_dir_exists_rc = 0;
166
+ int last_errno = -1;
167
+ for (char *p = tmp + offset; /* !rc && */ *p; p++) {
168
+ if (strchr("/\\", *p)) {
169
+ char tmp_c = p[1];
170
+ p[0] = FILESLASH;
171
+ p[1] = '\0';
172
+ if (*tmp && !(last_dir_exists_rc = zsv_dir_exists(tmp))) {
173
+ if (zsv_mkdir(tmp
174
+ #ifndef WIN32
175
+ ,
176
+ S_IRWXU
177
+ #endif
178
+ )) {
179
+ if (errno == EEXIST)
180
+ last_dir_exists_rc = 1;
181
+ else { // errno could be EEXIST if we have no permissions to an intermediate directory
182
+ last_errno = errno;
183
+ perror(tmp);
184
+ // rc = -1;
185
+ }
186
+ } else
187
+ last_dir_exists_rc = 1;
188
+ }
189
+ p[1] = tmp_c;
190
+ }
191
+ }
192
+
193
+ if (/* !rc && */ path_is_filename == 0 && *tmp && !(last_dir_exists_rc = zsv_dir_exists(tmp))) {
194
+ if (zsv_mkdir(tmp
195
+ #ifndef WIN32
196
+ ,
197
+ S_IRWXU
198
+ #endif
199
+ )) {
200
+ if (errno == EEXIST)
201
+ last_dir_exists_rc = 1;
202
+ else {
203
+ last_errno = errno;
204
+ perror(tmp);
205
+ // rc = -1;
206
+ }
207
+ } else
208
+ last_dir_exists_rc = 1;
209
+ }
210
+
211
+ free(tmp);
212
+ return last_dir_exists_rc ? 0 : last_errno ? last_errno : -1;
213
+ }
214
+
215
+ int main(int argc, char *argv[]) {
216
+ if (argc != 2) {
217
+ fprintf(stderr, "Usage: %s <absolute_directory_path>\n", argv[0]);
218
+ fprintf(stderr, "Example: %s \"C:\\Temp\\My Very Long Directory Name That Exceeds 260 Characters\\Subfolder\"\n",
219
+ argv[0]);
220
+ fprintf(stderr, " %s \"\\\\?\\C:\\Temp\\Another Long Path\\Subfolder\"\n", argv[0]);
221
+ fprintf(stderr, "Note: Provide an ABSOLUTE path.\n");
222
+ return 1;
223
+ }
224
+
225
+ const char *targetPath = argv[1];
226
+
227
+ printf("Attempting to create directory: %s\n", targetPath);
228
+
229
+ DWORD result = zsv_mkdirs(targetPath, 0);
230
+
231
+ if (result == 0) {
232
+ printf("Success: Directory created or already exists.\n");
233
+ return 0;
234
+ } else {
235
+ // You can provide more detailed error messages by checking specific Win32 error codes
236
+ // For example: if (result == ERROR_PATH_NOT_FOUND) { ... }
237
+ fprintf(stderr, "Error: Failed to create directory %s. Win32 Error Code: %lu\n", targetPath, result);
238
+
239
+ // Optionally print the system error message for the code
240
+ LPSTR messageBuffer = NULL;
241
+ size_t size =
242
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
243
+ result, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
244
+ if (messageBuffer) {
245
+ fprintf(stderr, "System Message: %s\n", messageBuffer);
246
+ LocalFree(messageBuffer); // Free buffer allocated by FormatMessage
247
+ } else {
248
+ fprintf(stderr, "Could not format error message for code %lu.\n", result);
249
+ }
250
+
251
+ return 1; // Indicate failure
252
+ }
253
+ }
254
+
255
+ #endif // DIRS_MKDIR_TEST
@@ -0,0 +1,96 @@
1
+ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
2
+ #include <windows.h>
3
+ #include <stdio.h>
4
+ #include <stdlib.h> // Required for malloc, free
5
+ #include <string.h>
6
+ #include <wchar.h> // Required for wide character functions
7
+
8
+ #include "io.h"
9
+ #include <errno.h>
10
+
11
+ // Function to map common Windows error codes to POSIX errno values
12
+ // return 0 if could not map
13
+ int windows_error_to_errno(DWORD windows_error_code) {
14
+ switch (windows_error_code) {
15
+ case ERROR_FILE_NOT_FOUND:
16
+ return ENOENT;
17
+ case ERROR_PATH_NOT_FOUND:
18
+ return ENOENT;
19
+ case ERROR_INVALID_DRIVE:
20
+ return ENODEV; // Or ENOENT
21
+
22
+ case ERROR_ACCESS_DENIED:
23
+ return EACCES;
24
+ case ERROR_INVALID_ACCESS:
25
+ return EACCES; // Or EPERM depending on context
26
+ case ERROR_SHARING_VIOLATION:
27
+ return EACCES; // File is locked/in use
28
+ case ERROR_INVALID_HANDLE:
29
+ return EBADF;
30
+ case ERROR_INVALID_DATA:
31
+ return EILSEQ; // Or EINVAL
32
+ case ERROR_INVALID_PARAMETER:
33
+ return EINVAL;
34
+ case ERROR_NEGATIVE_SEEK:
35
+ return EINVAL;
36
+ case ERROR_WRITE_PROTECT:
37
+ return EROFS; // Read-only filesystem or media
38
+ case ERROR_DISK_FULL:
39
+ return ENOSPC; // No space left on device
40
+ case ERROR_ALREADY_EXISTS:
41
+ return EEXIST;
42
+ case ERROR_FILE_EXISTS:
43
+ return EEXIST;
44
+ case ERROR_TOO_MANY_OPEN_FILES:
45
+ return EMFILE;
46
+ case ERROR_DIRECTORY:
47
+ return ENOTDIR; // Attempted file op on directory (approx)
48
+ case ERROR_BROKEN_PIPE:
49
+ return EPIPE;
50
+ case ERROR_PIPE_NOT_CONNECTED:
51
+ return EPIPE;
52
+ case ERROR_WAIT_NO_CHILDREN:
53
+ return ECHILD; // Wait functions
54
+ case ERROR_CHILD_NOT_COMPLETE:
55
+ return ECHILD; // Wait functions
56
+ case ERROR_SUCCESS:
57
+ return 0; // Not really an error
58
+ default:
59
+ return 0;
60
+ }
61
+ }
62
+
63
+ int zsv_remove_winlp(const char *path_utf8) {
64
+ if (path_utf8 == NULL || path_utf8[0] == '\0') {
65
+ return 0; // Invalid or empty path
66
+ }
67
+
68
+ wchar_t *path_to_use = NULL;
69
+ DWORD rc = zsv_pathToPrefixedWidePath(path_utf8, &path_to_use);
70
+ if (!rc) {
71
+ if (!DeleteFileW(path_to_use)) {
72
+ DWORD lastError = GetLastError();
73
+ #ifndef NDEBUG
74
+ fprintf(stderr, "Error deleting file '%ls': %lu\n", path_to_use, lastError);
75
+ #endif
76
+ if (windows_error_to_errno(lastError)) {
77
+ rc = windows_error_to_errno(lastError);
78
+ errno = rc;
79
+ } else {
80
+ fprintf(stderr, "Unable to delete file '%ls': %lu\n", path_to_use, GetLastError());
81
+ LPSTR messageBuffer = NULL;
82
+ FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
83
+ NULL, lastError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
84
+ if (messageBuffer) {
85
+ fprintf(stderr, "Error message: %s\n", messageBuffer);
86
+ LocalFree(messageBuffer);
87
+ } else
88
+ fprintf(stderr, "Could not format error message for code %lu.\n", lastError);
89
+ errno = rc = -1;
90
+ }
91
+ }
92
+ }
93
+
94
+ free(path_to_use);
95
+ return rc;
96
+ }
@@ -0,0 +1,361 @@
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 <zsv/utils/writer.h>
10
+ #include <zsv/utils/compiler.h>
11
+ #include <zsv/utils/os.h>
12
+ #include <stdio.h>
13
+ #include <ctype.h>
14
+ #include <string.h>
15
+ #include <stdlib.h>
16
+ #include <errno.h>
17
+
18
+ // clang-format off
19
+
20
+ // return 0 on eof, +1 on error, > 0 if valid utf8 first byte read
21
+ static inline char UTF8_charLenC_noerr(int c) {
22
+ char len;
23
+ if (c == EOF) len = 0;
24
+ else if (!(c & 128)) len = 1;
25
+ else if ((c & 224) == 192) len = 2; // 110xxxxx
26
+ else if ((c & 240) == 224) len = 3; // 1110xxxx
27
+ else if ((c & 248) == 240) len = 4; // 11110xxx
28
+ else if ((c & 252) == 248) len = 5; // 111110xx
29
+ else if ((c & 254) == 252) len = 6; // 1111110x
30
+ else len = 1; // error, but we are going to ignore and just call it a 1-byte char
31
+ return len;
32
+ }
33
+
34
+ // clang-format on
35
+
36
+ static struct zsv_csv_writer_options zsv_csv_writer_default_opts = {0};
37
+ static char zsv_writer_default_opts_initd = 0;
38
+ void zsv_writer_set_default_opts(struct zsv_csv_writer_options opts) {
39
+ zsv_writer_default_opts_initd = 1;
40
+ zsv_csv_writer_default_opts = opts;
41
+ }
42
+
43
+ struct zsv_csv_writer_options zsv_writer_get_default_opts(void) {
44
+ if (!zsv_writer_default_opts_initd) {
45
+ zsv_writer_default_opts_initd = 1;
46
+ zsv_csv_writer_default_opts.write = (size_t(*)(const void *restrict, size_t, size_t, void *restrict))fwrite;
47
+ zsv_csv_writer_default_opts.stream = stdout;
48
+ }
49
+ return zsv_csv_writer_default_opts;
50
+ }
51
+
52
+ // zsv_csv_quote() returns:
53
+ // - NULL if no quoting needed
54
+ // - buff if buff size was large enough to hold result
55
+ // - newly-allocated char * if buff not large enough, and was able to get from heap
56
+ // in last case, caller must free
57
+ unsigned char *zsv_csv_quote(const unsigned char *utf8_value, size_t len, unsigned char *buff, size_t buffsize) {
58
+ char need = 0;
59
+ unsigned quotes = 0;
60
+ for (unsigned int i = 0; i < len; i++) {
61
+ switch (utf8_value[i]) {
62
+ case ',':
63
+ case '\n':
64
+ case '\r':
65
+ need = 1;
66
+ break;
67
+ case '"':
68
+ need = 1;
69
+ quotes++;
70
+ break;
71
+ }
72
+ }
73
+ if (!need)
74
+ return NULL;
75
+
76
+ unsigned char *target;
77
+ unsigned mem_length = len + quotes + 3; // str + 2 quotes + terminating null
78
+ if (mem_length < buffsize)
79
+ target = buff;
80
+ else
81
+ target = malloc(mem_length * sizeof(*target));
82
+
83
+ if (target) {
84
+ *target = '"';
85
+ if (!quotes)
86
+ memcpy(target + 1, utf8_value, len);
87
+ else {
88
+ for (unsigned int i = 0, j = 1; i < len; i++) {
89
+ if ((target[j++] = utf8_value[i]) == '"')
90
+ target[j++] = '"';
91
+ }
92
+ }
93
+ target[mem_length - 2] = '"';
94
+ target[mem_length - 1] = '\0';
95
+ }
96
+ return target;
97
+ }
98
+
99
+ // to do: test #define ZSV_OUTPUT_BUFF_SIZE 65536 * 4 * 8
100
+ #define ZSV_OUTPUT_BUFF_SIZE 65536 * 4
101
+
102
+ struct zsv_output_buff {
103
+ char *buff; // will be ZSV_OUTPUT_BUFF_SIZE. to do: option to modify buff size
104
+ size_t (*write)(const void *restrict, size_t size, size_t nitems, void *restrict stream);
105
+ void *stream;
106
+ size_t used;
107
+ uint64_t written;
108
+ unsigned char close_on_delete : 1;
109
+ unsigned char _ : 7;
110
+ };
111
+
112
+ struct zsv_writer_data {
113
+ size_t buffsize; // corresponds to buf
114
+ unsigned char *buff; // option
115
+
116
+ struct zsv_output_buff out;
117
+
118
+ void (*table_init)(void *);
119
+ void *table_init_ctx;
120
+
121
+ const char *cell_prepend;
122
+
123
+ void (*on_row)(void *);
124
+ void *on_row_ctx;
125
+
126
+ void (*on_delete)(void *);
127
+ void *on_delete_ctx;
128
+
129
+ unsigned char with_bom : 1;
130
+ unsigned char started : 1;
131
+ unsigned char _ : 6;
132
+ };
133
+
134
+ #include <unistd.h> // write
135
+
136
+ static inline void zsv_output_buff_flush(struct zsv_output_buff *b) {
137
+ b->write(b->buff, b->used, 1, b->stream);
138
+ b->written += b->used;
139
+ b->used = 0;
140
+ }
141
+
142
+ static inline void zsv_output_buff_write(struct zsv_output_buff *b, const unsigned char *s, size_t n) {
143
+ if (n) {
144
+ if (n + b->used > ZSV_OUTPUT_BUFF_SIZE) {
145
+ zsv_output_buff_flush(b);
146
+ if (n > ZSV_OUTPUT_BUFF_SIZE) { // n too big, so write directly
147
+ b->write(s, n, 1, b->stream);
148
+ b->written += n;
149
+ return;
150
+ }
151
+ }
152
+ // n + used < buff size
153
+ memcpy(b->buff + b->used, s, n);
154
+ b->used += n;
155
+ }
156
+ }
157
+
158
+ void zsv_writer_set_temp_buff(zsv_csv_writer w, unsigned char *buff, size_t buffsize) {
159
+ w->buff = buff;
160
+ w->buffsize = buffsize;
161
+ }
162
+
163
+ static int writer_opts_ok(struct zsv_csv_writer_options *opts) {
164
+ if (opts) {
165
+ if (opts->output_path) {
166
+ if ((opts->write && opts->write != (size_t(*)(const void *restrict, size_t, size_t, void *restrict))fwrite) ||
167
+ (opts->stream && opts->stream != stdout)) {
168
+ fprintf(stderr, "Invalid zsv writer options: non-NULL 'output_path' with invalid 'write' and/or 'stream'\n");
169
+ errno = EINVAL;
170
+ return 0;
171
+ }
172
+ }
173
+ }
174
+ return 1;
175
+ }
176
+
177
+ zsv_csv_writer zsv_writer_new(struct zsv_csv_writer_options *opts) {
178
+ if (!(writer_opts_ok(opts)))
179
+ return NULL;
180
+ struct zsv_writer_data *w = calloc(1, sizeof(*w));
181
+ if (w) {
182
+ if (!(w->out.buff = malloc(ZSV_OUTPUT_BUFF_SIZE)))
183
+ goto zsv_writer_new_err;
184
+
185
+ if (!opts) {
186
+ w->out.write = (size_t(*)(const void *restrict, size_t, size_t, void *restrict))fwrite;
187
+ w->out.stream = stdout;
188
+ } else {
189
+ if (opts->output_path) {
190
+ if (!(w->out.stream = zsv_fopen(opts->output_path, "wb"))) {
191
+ perror(opts->output_path);
192
+ goto zsv_writer_new_err;
193
+ }
194
+ w->out.close_on_delete = 1;
195
+ w->out.write = (size_t(*)(const void *restrict, size_t, size_t, void *restrict))fwrite;
196
+ } else if (opts->write) {
197
+ w->out.write = opts->write;
198
+ w->out.stream = opts->stream;
199
+ } else {
200
+ w->out.write = (size_t(*)(const void *restrict, size_t, size_t, void *restrict))fwrite;
201
+ w->out.stream = opts->stream ? opts->stream : stdout;
202
+ }
203
+
204
+ w->with_bom = opts->with_bom;
205
+ w->table_init = opts->table_init;
206
+ w->table_init_ctx = opts->table_init_ctx;
207
+ w->on_row = opts->on_row;
208
+ w->on_row_ctx = opts->on_row_ctx;
209
+ w->on_delete = opts->on_delete;
210
+ w->on_delete_ctx = opts->on_delete_ctx;
211
+ }
212
+ }
213
+ return w;
214
+
215
+ int e;
216
+ zsv_writer_new_err:
217
+ e = errno;
218
+ zsv_writer_delete(w);
219
+ errno = e;
220
+ return NULL;
221
+ }
222
+
223
+ enum zsv_writer_status zsv_writer_flush(zsv_csv_writer w) {
224
+ if (!w)
225
+ return zsv_writer_status_missing_handle;
226
+
227
+ zsv_output_buff_flush(&w->out);
228
+ return zsv_writer_status_ok;
229
+ }
230
+
231
+ enum zsv_writer_status zsv_writer_delete(zsv_csv_writer w) {
232
+ if (!w)
233
+ return zsv_writer_status_missing_handle;
234
+
235
+ if (w->started)
236
+ zsv_output_buff_write(&w->out, (const unsigned char *)"\n", 1);
237
+
238
+ if (w->out.stream && w->out.write && w->out.buff)
239
+ zsv_output_buff_flush(&w->out);
240
+
241
+ if (w->on_delete)
242
+ w->on_delete(w->on_delete_ctx);
243
+
244
+ if (w->out.buff)
245
+ free(w->out.buff);
246
+
247
+ if (w->out.close_on_delete && w->out.stream)
248
+ fclose(w->out.stream);
249
+
250
+ free(w);
251
+ return zsv_writer_status_ok;
252
+ }
253
+
254
+ static inline enum zsv_writer_status zsv_writer_cell_aux(zsv_csv_writer w, const unsigned char *s, size_t len,
255
+ char check_if_needs_quoting) {
256
+ if (len) {
257
+ if (check_if_needs_quoting) {
258
+ unsigned char *quoted_s = zsv_csv_quote(s, len, w->buff, w->buffsize);
259
+ if (!quoted_s)
260
+ zsv_output_buff_write(&w->out, s, len);
261
+ else {
262
+ zsv_output_buff_write(&w->out, quoted_s, strlen((char *)quoted_s));
263
+ if (!(w->buff && quoted_s == w->buff))
264
+ free(quoted_s);
265
+ }
266
+ } else
267
+ zsv_output_buff_write(&w->out, s, len);
268
+ }
269
+ return zsv_writer_status_ok;
270
+ }
271
+
272
+ uint64_t zsv_writer_cum_bytes_written(zsv_csv_writer w) {
273
+ return (uint64_t)(w->out.used + w->out.written);
274
+ }
275
+
276
+ enum zsv_writer_status zsv_writer_cell(zsv_csv_writer w, char new_row, const unsigned char *s, size_t len,
277
+ char check_if_needs_quoting) {
278
+ if (!w)
279
+ return zsv_writer_status_missing_handle;
280
+ if (!w->started) {
281
+ if (w->table_init)
282
+ w->table_init(w->table_init_ctx);
283
+ if (w->with_bom)
284
+ zsv_output_buff_write(&w->out, (const unsigned char *)"\xef\xbb\xbf", 3);
285
+ w->started = 1;
286
+ } else if (new_row) {
287
+ if (VERY_UNLIKELY(w->on_row != NULL))
288
+ w->on_row(w->on_row_ctx);
289
+ zsv_output_buff_write(&w->out, (const unsigned char *)"\n", 1);
290
+ } else
291
+ zsv_output_buff_write(&w->out, (const unsigned char *)",", 1);
292
+
293
+ if (VERY_UNLIKELY(w->cell_prepend && *w->cell_prepend)) {
294
+ char *tmp = NULL;
295
+ asprintf(&tmp, "%s%.*s", w->cell_prepend, (int)len, s ? s : (const unsigned char *)"");
296
+ if (!tmp) {
297
+ perror(NULL);
298
+ return zsv_writer_status_error;
299
+ }
300
+ s = (const unsigned char *)tmp;
301
+ len = len + strlen(w->cell_prepend);
302
+ enum zsv_writer_status stat = zsv_writer_cell_aux(w, s, len, 1);
303
+ free(tmp);
304
+ return stat;
305
+ }
306
+ return zsv_writer_cell_aux(w, s, len, check_if_needs_quoting);
307
+ }
308
+
309
+ void zsv_writer_cell_prepend(zsv_csv_writer w, const unsigned char *s) {
310
+ w->cell_prepend = (const char *)s;
311
+ }
312
+
313
+ enum zsv_writer_status zsv_writer_cell_Lf(zsv_csv_writer w, char new_row, const char *fmt_spec, long double ldbl) {
314
+ char s[128];
315
+ char fmt[64];
316
+ int n = snprintf(fmt, sizeof(fmt), "%%%sLf", fmt_spec ? fmt_spec : "");
317
+ if (!(n > 0 && n < (int)sizeof(fmt)))
318
+ fprintf(stderr, "Invalid format specifier, should be X for format %%XLf e.g. '.2'\n");
319
+ else {
320
+ n = snprintf(s, sizeof(s), fmt, ldbl);
321
+ if (!(n > 0 && n < (int)sizeof(fmt)))
322
+ fprintf(stderr, "Unable to format value with fmt %s: %Lf\n", fmt, ldbl);
323
+ else
324
+ return zsv_writer_cell(w, new_row, (unsigned char *)s, n, 0);
325
+ }
326
+ zsv_writer_cell(w, new_row, NULL, 0, 0);
327
+ return zsv_writer_status_error;
328
+ }
329
+
330
+ enum zsv_writer_status zsv_writer_cell_blank(zsv_csv_writer w, char new_row) {
331
+ return zsv_writer_cell(w, new_row, (const unsigned char *)"", 0, 0);
332
+ }
333
+
334
+ enum zsv_writer_status zsv_writer_cell_zu(zsv_csv_writer w, char new_row, size_t zu) {
335
+ char s[64];
336
+ int n = snprintf(s, sizeof(s), "%zu", zu);
337
+ if (n < 1 || n >= (int)sizeof(s))
338
+ n = 0; // unexpected overflow
339
+ return zsv_writer_cell(w, new_row, (unsigned char *)s, n, 0);
340
+ }
341
+
342
+ enum zsv_writer_status zsv_writer_cell_s(zsv_csv_writer w, char new_row, const unsigned char *s,
343
+ char check_if_needs_quoting) {
344
+ return zsv_writer_cell(w, new_row, s, s ? strlen((const char *)s) : 0, check_if_needs_quoting);
345
+ }
346
+
347
+ /*
348
+ * returns: newly allocated value (caller must free) or NULL
349
+ */
350
+ unsigned char *zsv_writer_str_to_csv(const unsigned char *s, size_t len) {
351
+ if (len) {
352
+ unsigned char *csv_s = zsv_csv_quote(s, len, NULL, 0);
353
+ if (csv_s)
354
+ return csv_s;
355
+ csv_s = malloc(len + 1);
356
+ memcpy(csv_s, s, len);
357
+ csv_s[len] = '\0';
358
+ return csv_s;
359
+ }
360
+ return NULL;
361
+ }