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,167 @@
1
+ static zsvsheet_status zsv_sqlite3_to_csv(zsvsheet_proc_context_t pctx, struct zsv_sqlite3_db *zdb, const char *sql,
2
+ const char **err_msg, void *ctx,
3
+ void (*on_header_cell)(void *, size_t, const char *),
4
+ void (*on_data_cell)(void *, size_t, const char *, size_t len)) {
5
+ zsvsheet_status zst = zsvsheet_status_error;
6
+ sqlite3_stmt *stmt = NULL;
7
+ char have_data = 0;
8
+ if ((zdb->rc = sqlite3_prepare_v2(zdb->db, sql, -1, &stmt, NULL)) == SQLITE_OK) {
9
+ char *tmp_fn = zsv_get_temp_filename("zsv_mysheet_ext_XXXXXXXX");
10
+ struct zsv_csv_writer_options writer_opts = zsv_writer_get_default_opts();
11
+ zsv_csv_writer cw = NULL;
12
+ if (!tmp_fn)
13
+ zst = zsvsheet_status_memory;
14
+ else if (!(writer_opts.stream = fopen(tmp_fn, "wb"))) {
15
+ zst = zsvsheet_status_error;
16
+ *err_msg = strerror(errno);
17
+ } else if (!(cw = zsv_writer_new(&writer_opts)))
18
+ zst = zsvsheet_status_memory;
19
+ else {
20
+ zst = zsvsheet_status_ok;
21
+ unsigned char cw_buff[1024];
22
+ zsv_writer_set_temp_buff(cw, cw_buff, sizeof(cw_buff));
23
+
24
+ int col_count = sqlite3_column_count(stmt);
25
+ // write header row
26
+ for (int i = 0; i < col_count; i++) {
27
+ const char *colname = sqlite3_column_name(stmt, i);
28
+ zsv_writer_cell(cw, !i, (const unsigned char *)colname, colname ? strlen(colname) : 0, 1);
29
+ if (on_header_cell)
30
+ on_header_cell(ctx, i, colname);
31
+ }
32
+
33
+ // write sql results
34
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
35
+ for (int i = 0; i < col_count; i++) {
36
+ const unsigned char *text = sqlite3_column_text(stmt, i);
37
+ int len = text ? sqlite3_column_bytes(stmt, i) : 0;
38
+ zsv_writer_cell(cw, !i, text, len, 1);
39
+ have_data = 1;
40
+ if (on_data_cell)
41
+ on_data_cell(ctx, i, (const char *)text, len);
42
+ }
43
+ }
44
+ }
45
+ if (cw)
46
+ zsv_writer_delete(cw);
47
+ if (writer_opts.stream)
48
+ fclose(writer_opts.stream);
49
+
50
+ if (tmp_fn && zsv_file_exists(tmp_fn) && have_data) {
51
+ struct zsvsheet_ui_buffer_opts uibopts = {0};
52
+ uibopts.data_filename = tmp_fn;
53
+ zst = zsvsheet_open_file_opts(pctx, &uibopts);
54
+ } else {
55
+ if (zst == zsvsheet_status_ok) {
56
+ if (!have_data)
57
+ zst = zsvsheet_status_no_data;
58
+ if (!*err_msg && zdb && zdb->rc != SQLITE_OK) {
59
+ zst = zsvsheet_status_error; // to do: make this more specific
60
+ *err_msg = sqlite3_errmsg(zdb->db);
61
+ }
62
+ }
63
+ if (tmp_fn && zsv_file_exists(tmp_fn))
64
+ unlink(tmp_fn);
65
+ }
66
+ free(tmp_fn);
67
+ }
68
+ if (stmt)
69
+ sqlite3_finalize(stmt);
70
+
71
+ return zst;
72
+ }
73
+
74
+ static int is_constant_expression(sqlite3 *db, const char *expr, int *err) {
75
+ sqlite3_stmt *stmt = NULL;
76
+ // We try to prepare "SELECT [expr]". If this succeeds, the expression
77
+ // does not depend on any columns and is therefore constant.
78
+ char *sql_const_test = sqlite3_mprintf("SELECT %s", expr);
79
+ if (!sql_const_test) {
80
+ *err = errno;
81
+ return 0;
82
+ }
83
+
84
+ int rc = sqlite3_prepare_v2(db, sql_const_test, -1, &stmt, NULL);
85
+ if (stmt) {
86
+ sqlite3_finalize(stmt);
87
+ stmt = NULL;
88
+ }
89
+ sqlite3_free(sql_const_test);
90
+
91
+ int is_constant = (rc == SQLITE_OK);
92
+ return is_constant;
93
+ }
94
+
95
+ enum check_select_expression_result {
96
+ zsv_select_sql_expression_valid = 0,
97
+ zsv_select_sql_expression_invalid,
98
+ zsv_select_sql_expression_multiple_statements,
99
+ zsv_select_sql_expression_multiple_expressions,
100
+ zsv_select_sql_expression_other
101
+ };
102
+
103
+ const char *check_select_expression_result_str(enum check_select_expression_result rc) {
104
+ switch (rc) {
105
+ case zsv_select_sql_expression_valid:
106
+ return NULL;
107
+ case zsv_select_sql_expression_invalid:
108
+ return "Invalid SQL";
109
+ case zsv_select_sql_expression_multiple_statements:
110
+ return "Please enter only a single expression";
111
+ case zsv_select_sql_expression_multiple_expressions:
112
+ return "Please enter only a single expression";
113
+ case zsv_select_sql_expression_other:
114
+ return "Unknown error";
115
+ }
116
+ return NULL;
117
+ }
118
+
119
+ static int is_str_empty(const char *s) {
120
+ if (!s)
121
+ return 1;
122
+ while (*s) {
123
+ if (!isspace((unsigned char)*s)) {
124
+ return 0;
125
+ }
126
+ s++;
127
+ }
128
+ return 1;
129
+ }
130
+
131
+ static enum check_select_expression_result check_select_expression(sqlite3 *db, const char *expr, int *err) {
132
+ sqlite3_stmt *stmt = NULL;
133
+
134
+ // Prepare "SELECT [expr] FROM data" to see if it's valid in the
135
+ // context of the 'data' table.
136
+ char *sql_valid_test = sqlite3_mprintf("SELECT %s FROM data LIMIT 0", expr);
137
+ if (!sql_valid_test) {
138
+ *err = errno;
139
+ return zsv_select_sql_expression_other;
140
+ }
141
+
142
+ const char *pzTail = NULL;
143
+ int rc = sqlite3_prepare_v2(db, sql_valid_test, -1, &stmt, &pzTail);
144
+ sqlite3_free(sql_valid_test); // Free the string immediately
145
+ if (rc != SQLITE_OK) {
146
+ if (stmt)
147
+ sqlite3_finalize(stmt);
148
+ return zsv_select_sql_expression_invalid;
149
+ }
150
+
151
+ // if we are here, the expression is valid. check it is a single statement
152
+ // pzTail points to the start of the *next* statement. If it's not
153
+ // empty or just whitespace, the user tried to inject a second command.
154
+ if (!is_str_empty(pzTail)) {
155
+ sqlite3_finalize(stmt);
156
+ return zsv_select_sql_expression_multiple_statements;
157
+ }
158
+
159
+ // Check that we have a single expression (e.g., not "myvalue, 123")
160
+ int col_count = sqlite3_column_count(stmt);
161
+
162
+ sqlite3_finalize(stmt);
163
+ if (col_count != 1)
164
+ return zsv_select_sql_expression_multiple_expressions;
165
+
166
+ return zsv_select_sql_expression_valid;
167
+ }
@@ -0,0 +1,36 @@
1
+ #ifndef ZSVSHEET_INTERNAL_H
2
+ #define ZSVSHEET_INTERNAL_H
3
+
4
+ #define ZSVSHEET_ROWNUM_HEADER "Row #"
5
+ #define ZSVSHEET_ROWNUM_HEADER_LEN strlen(ZSVSHEET_ROWNUM_HEADER)
6
+
7
+ enum zsvsheet_priv_status {
8
+ zsvsheet_priv_status_ok = 0,
9
+ zsvsheet_priv_status_memory,
10
+ zsvsheet_priv_status_error, // generic error
11
+ zsvsheet_priv_status_utf8,
12
+ zsvsheet_priv_status_continue // ignore / continue
13
+ // zsvsheet_priv_status_duplicate
14
+ };
15
+
16
+ struct zsvsheet_input_dimensions {
17
+ size_t col_count;
18
+ size_t row_count;
19
+ };
20
+
21
+ struct zsvsheet_display_dimensions {
22
+ size_t rows;
23
+ size_t columns;
24
+ size_t header_span;
25
+ size_t footer_span;
26
+ };
27
+
28
+ struct zsvsheet_buffer_info_internal {
29
+ unsigned char index_started : 1;
30
+ unsigned char index_ready : 1;
31
+ unsigned char write_in_progress : 1;
32
+ unsigned char write_done : 1;
33
+ unsigned char _ : 4;
34
+ };
35
+
36
+ #endif
@@ -0,0 +1,153 @@
1
+ /*
2
+ * Copyright (C) 2021 Liquidaty and zsv contributors. All rights
3
+ * reserved. This file is part of zsv/lib, distributed under the
4
+ * license defined at https://opensource.org/licenses/MIT
5
+ */
6
+
7
+ #include <assert.h>
8
+ #include <errno.h>
9
+ #include "../external/sqlite3/sqlite3.h"
10
+ #include <zsv/ext/implementation.h>
11
+ #include <zsv/ext/sheet.h>
12
+ #include <zsv/utils/writer.h>
13
+ #include <zsv/utils/file.h>
14
+ #include <zsv/utils/prop.h>
15
+ #include "file.h"
16
+ #include "handlers_internal.h"
17
+ #include "./curses.h"
18
+ #include "../sql_internal.h"
19
+
20
+ struct sqlfilter_data {
21
+ char *value_sql; // the sql expression entered by the user e.g. City
22
+ char *data_filename;
23
+ };
24
+
25
+ static void sqlfilter_data_delete(void *h) {
26
+ struct sqlfilter_data *pd = h;
27
+ if (pd) {
28
+ free(pd->value_sql);
29
+ free(pd->data_filename);
30
+ free(pd);
31
+ }
32
+ }
33
+
34
+ static struct sqlfilter_data *sqlfilter_data_new(const char *data_filename, const char *value_sql) {
35
+ struct sqlfilter_data *pd = calloc(1, sizeof(*pd));
36
+ if (pd && (pd->value_sql = strdup(value_sql)) && (pd->data_filename = strdup(data_filename)))
37
+ return pd;
38
+ sqlfilter_data_delete(pd);
39
+ return NULL;
40
+ }
41
+
42
+ static void zsvsheet_check_buffer_worker_updates(struct zsvsheet_ui_buffer *ub,
43
+ struct zsvsheet_display_dimensions *display_dims,
44
+ struct zsvsheet_sheet_context *handler_state);
45
+
46
+ /**
47
+ * Here we define a custom command for the zsv `sheet` feature
48
+ */
49
+ static zsvsheet_status zsvsheet_sqlfilter_handler(struct zsvsheet_proc_context *ctx) {
50
+ char result_buffer[256] = {0};
51
+ const char *expr;
52
+ zsvsheet_buffer_t buff = zsvsheet_buffer_current(ctx);
53
+ struct zsvsheet_buffer_data bd = zsvsheet_buffer_info(buff);
54
+ const char add_row_num = !bd.has_row_num;
55
+ const char *data_filename = NULL;
56
+ if (buff)
57
+ data_filename = zsvsheet_buffer_data_filename(buff);
58
+
59
+ if (!data_filename) { // TO DO: check that the underlying data is a tabular file and we know how to parse
60
+ zsvsheet_ui_buffer_set_status(buff, "SQL filter only available for tabular data buffers");
61
+ return zsvsheet_status_ok;
62
+ }
63
+
64
+ char *selected_cell_str_dup = NULL;
65
+ switch (ctx->proc_id) {
66
+ case zsvsheet_builtin_proc_sqlfilter:
67
+ zsvsheet_ext_prompt(ctx, result_buffer, sizeof(result_buffer), "Enter SQL expr to filter by");
68
+ if (*result_buffer == '\0')
69
+ return zsvsheet_status_ok;
70
+ expr = result_buffer;
71
+ break;
72
+ default:
73
+ assert(0);
74
+ return zsvsheet_status_error;
75
+ }
76
+
77
+ enum zsvsheet_status zst = zsvsheet_status_ok;
78
+ struct zsv_sqlite3_dbopts dbopts = {0};
79
+ struct zsv_opts zopts = zsvsheet_buffer_get_zsv_opts(buff);
80
+ struct zsv_sqlite3_db *zdb = zsv_sqlite3_db_new(&dbopts);
81
+ sqlite3_str *sql_str = NULL;
82
+ struct sqlfilter_data *sqlfd = NULL;
83
+ if (!zdb || !(sql_str = sqlite3_str_new(zdb->db)))
84
+ zst = zsvsheet_status_memory;
85
+ else if (zdb->rc == SQLITE_OK && zsv_sqlite3_add_csv_no_dq(zdb, data_filename, &zopts, NULL) == SQLITE_OK) {
86
+ int ok = 0;
87
+ const char *err_msg = NULL;
88
+ int err = 0;
89
+ if (is_constant_expression(zdb->db, expr, &err))
90
+ err_msg = "Please enter an expression that is not a constant";
91
+ else {
92
+ enum check_select_expression_result expr_rc = check_select_expression(zdb->db, expr, &err);
93
+ if (expr_rc != zsv_select_sql_expression_valid)
94
+ err_msg = check_select_expression_result_str(expr_rc);
95
+ else if (!err)
96
+ ok = 1;
97
+ }
98
+ if (!ok) {
99
+ if (err)
100
+ zsvsheet_ui_buffer_set_status(buff, strerror(err));
101
+ else if (err_msg)
102
+ zsvsheet_ui_buffer_set_status(buff, err_msg);
103
+ else
104
+ zsvsheet_ui_buffer_set_status(buff, "Unknown error");
105
+ } else {
106
+ if (add_row_num)
107
+ sqlite3_str_appendf(sql_str, "select ROWID as %Q, * from data where %s", ZSVSHEET_ROWNUM_HEADER, expr);
108
+ else
109
+ sqlite3_str_appendf(sql_str, "select * from data where %s", expr);
110
+
111
+ if (!(sqlfd = sqlfilter_data_new(data_filename, expr)))
112
+ zst = zsvsheet_status_memory;
113
+ else {
114
+ zst = zsv_sqlite3_to_csv(ctx, zdb, sqlite3_str_value(sql_str), &err_msg, sqlfd, NULL, NULL);
115
+ if (zst != zsvsheet_status_ok) {
116
+ if (zst == zsvsheet_status_no_data)
117
+ zsvsheet_ui_buffer_set_status(buff, "No results returned");
118
+ else
119
+ zsvsheet_ui_buffer_set_status(buff, err_msg ? err_msg : "Unexpected error preparing SQL");
120
+ } else {
121
+ buff = zsvsheet_buffer_current(ctx);
122
+ zsvsheet_buffer_set_ctx(buff, sqlfd, sqlfilter_data_delete);
123
+ sqlfd = NULL; // so that it isn't cleaned up below
124
+
125
+ while (!zsvsheet_ui_buffer_index_ready(buff, 0))
126
+ napms(200); // sleep for 200ms, then check index again
127
+ // TO DO: fix this if there is no data!
128
+
129
+ if (selected_cell_str_dup) {
130
+ struct zsvsheet_sheet_context *state = (struct zsvsheet_sheet_context *)ctx->subcommand_context;
131
+ struct zsvsheet_display_info *di = &state->display_info;
132
+ zsvsheet_check_buffer_worker_updates(buff, di->dimensions, NULL);
133
+ zsvsheet_handle_find_next(di, buff, selected_cell_str_dup,
134
+ 1, // find value in first column
135
+ 1, // exact
136
+ 1, // header_span
137
+ di->dimensions, &di->update_buffer, NULL);
138
+ }
139
+ }
140
+ }
141
+ }
142
+ // TO DO: add param to ext_sheet_open_file to set filename vs data_filename, and set buffer type or proc owner
143
+ // TO DO: add way to attach custom context, and custom context destructor, to the new buffer
144
+ // TO DO: add cell highlighting
145
+ }
146
+
147
+ zsv_sqlite3_db_delete(zdb);
148
+ if (sql_str)
149
+ sqlite3_free(sqlite3_str_finish(sql_str));
150
+ sqlfilter_data_delete(sqlfd);
151
+ free(selected_cell_str_dup);
152
+ return zst;
153
+ }
@@ -0,0 +1,32 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+ #include <unistd.h>
5
+
6
+ // check_or_set_terminfo: return 1 if ok, 0 if not
7
+ static int terminfo_ok(void) {
8
+ // Check if TERMINFO environment variable is set
9
+ char *terminfo_env = getenv("TERMINFO");
10
+ if (terminfo_env != NULL)
11
+ return 1; // ok
12
+
13
+ // Check some default locations
14
+ const char *default_paths[] = {
15
+ "/usr/share/terminfo", "/lib/terminfo", "/usr/lib/terminfo", "/etc/terminfo", "/usr/local/share/terminfo", NULL};
16
+
17
+ for (int i = 0; default_paths[i] != NULL; i++) {
18
+ if (access(default_paths[i], R_OK) == 0) {
19
+ // Set the TERMINFO environment variable
20
+ if (setenv("TERMINFO", default_paths[i], 1) == 0)
21
+ return 1; // ok
22
+ else {
23
+ perror("Failed to set TERMINFO environment variable");
24
+ return 0;
25
+ }
26
+ }
27
+ }
28
+ #if defined(WIN32) || defined(_WIN32)
29
+ return 1; // ok
30
+ #endif
31
+ return 0;
32
+ }
@@ -0,0 +1,312 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+ #include <pthread.h>
4
+ #include <zsv/utils/file.h>
5
+ #include <zsv/utils/prop.h>
6
+
7
+ #include "handlers_internal.h"
8
+ #include "transformation.h"
9
+ #include "../utils/index.h"
10
+
11
+ struct zsvsheet_transformation {
12
+ zsv_parser parser;
13
+ zsv_csv_writer writer;
14
+ char *output_filename;
15
+ FILE *output_stream;
16
+ unsigned char *output_buffer;
17
+ int output_fileno;
18
+ char writer_wrote;
19
+ struct zsvsheet_transformation_opts opts;
20
+ void *user_context;
21
+
22
+ struct zsvsheet_ui_buffer *ui_buffer;
23
+ char *default_status;
24
+ void (*on_done)(zsvsheet_transformation trn);
25
+ };
26
+
27
+ static size_t transformation_write(const void *restrict ptr, size_t size, size_t nitems, void *restrict stream) {
28
+ struct zsvsheet_transformation *trn = stream;
29
+
30
+ const size_t count = fwrite(ptr, size, nitems, trn->output_stream);
31
+ trn->writer_wrote = count > 0;
32
+
33
+ return count > 0 ? count : 0;
34
+ }
35
+
36
+ struct transformation_writer_index_ctx {
37
+ void *index;
38
+ zsv_csv_writer writer;
39
+ };
40
+
41
+ static void transformation_writer_index_on_row(void *p) {
42
+ struct transformation_writer_index_ctx *ctx = p;
43
+ uint64_t written = zsv_writer_cum_bytes_written(ctx->writer);
44
+ zsv_index_add_row(ctx->index, written);
45
+ }
46
+
47
+ static void transformation_writer_index_delete(void *p) {
48
+ struct transformation_writer_index_ctx *ctx = p;
49
+ uint64_t written = zsv_writer_cum_bytes_written(ctx->writer);
50
+ if (written)
51
+ zsv_index_add_row(ctx->index, written);
52
+ free(ctx);
53
+ }
54
+
55
+ enum zsv_status zsvsheet_transformation_new(struct zsvsheet_transformation_opts opts, zsvsheet_transformation *out) {
56
+ unsigned char *temp_buff = NULL;
57
+ char *temp_filename = NULL;
58
+ FILE *temp_f = NULL;
59
+ zsv_csv_writer temp_file_writer = NULL;
60
+ struct transformation_writer_index_ctx *ctx = NULL;
61
+ enum zsv_status zst = zsv_status_memory;
62
+
63
+ struct zsvsheet_transformation *trn = calloc(1, sizeof(*trn));
64
+ if (trn == NULL)
65
+ return zst;
66
+
67
+ trn->on_done = opts.on_done;
68
+ trn->ui_buffer = opts.ui_buffer;
69
+ zst = zsv_status_error;
70
+
71
+ temp_filename = zsv_get_temp_filename("zsvsheet_filter_XXXXXXXX");
72
+ if (!temp_filename)
73
+ goto free;
74
+ trn->output_filename = temp_filename;
75
+
76
+ if (!(temp_f = fopen(temp_filename, "w+")))
77
+ goto free;
78
+ if (setvbuf(temp_f, NULL, _IONBF, 0))
79
+ goto free;
80
+ trn->output_stream = temp_f;
81
+
82
+ ctx = calloc(1, sizeof(*ctx));
83
+ if (!ctx)
84
+ goto free;
85
+ ctx->index = opts.index;
86
+
87
+ struct zsv_csv_writer_options writer_opts = {
88
+ .with_bom = 0,
89
+ .write = transformation_write,
90
+ .stream = trn,
91
+ .table_init = NULL,
92
+ .table_init_ctx = NULL,
93
+ .on_row = transformation_writer_index_on_row,
94
+ .on_row_ctx = ctx,
95
+ .on_delete = transformation_writer_index_delete,
96
+ .on_delete_ctx = ctx,
97
+ };
98
+ if (!(temp_file_writer = zsv_writer_new(&writer_opts)))
99
+ goto free;
100
+
101
+ ctx->writer = temp_file_writer;
102
+ const size_t temp_buff_size = 2 * 1024 * 1024;
103
+ temp_buff = malloc(temp_buff_size);
104
+ if (!temp_buff)
105
+ goto free;
106
+ trn->output_buffer = temp_buff;
107
+ zsv_writer_set_temp_buff(temp_file_writer, temp_buff, temp_buff_size);
108
+ trn->writer = temp_file_writer;
109
+
110
+ trn->user_context = opts.zsv_opts.ctx;
111
+ opts.zsv_opts.ctx = trn;
112
+
113
+ zst = zsv_new_with_properties(&opts.zsv_opts, opts.custom_prop_handler, opts.input_filename, &trn->parser);
114
+ if (zst != zsv_status_ok)
115
+ goto free;
116
+
117
+ *out = trn;
118
+ return zst;
119
+
120
+ free:
121
+ if (trn)
122
+ free(trn);
123
+ if (temp_filename)
124
+ free(temp_filename);
125
+ if (temp_f)
126
+ fclose(temp_f);
127
+ if (temp_file_writer)
128
+ zsv_writer_delete(temp_file_writer);
129
+ if (temp_buff)
130
+ free(temp_buff);
131
+ if (ctx)
132
+ transformation_writer_index_delete(ctx);
133
+
134
+ return zst;
135
+ }
136
+
137
+ void zsvsheet_transformation_delete(zsvsheet_transformation trn) {
138
+ zsv_writer_delete(trn->writer);
139
+ zsv_delete(trn->parser);
140
+ free(trn->output_filename);
141
+ fclose(trn->output_stream);
142
+ free(trn->output_buffer);
143
+ free(trn);
144
+ }
145
+
146
+ zsv_parser zsvsheet_transformation_parser(zsvsheet_transformation trn) {
147
+ return trn->parser;
148
+ }
149
+
150
+ zsv_csv_writer zsvsheet_transformation_writer(zsvsheet_transformation trn) {
151
+ return trn->writer;
152
+ }
153
+
154
+ const char *zsvsheet_transformation_filename(zsvsheet_transformation trn) {
155
+ return trn->output_filename;
156
+ }
157
+
158
+ void *zsvsheet_transformation_user_context(zsvsheet_transformation trn) {
159
+ return trn->user_context;
160
+ }
161
+
162
+ static void *zsvsheet_run_buffer_transformation(void *arg) {
163
+ struct zsvsheet_transformation *trn = arg;
164
+ struct zsvsheet_ui_buffer *uib = trn->ui_buffer;
165
+ zsv_parser parser = trn->parser;
166
+ pthread_mutex_t *mutex = &uib->mutex;
167
+ enum zsv_status zst;
168
+ char *default_status = trn->default_status;
169
+
170
+ char cancelled = 0;
171
+ while (!cancelled && (zst = zsv_parse_more(parser)) == zsv_status_ok) {
172
+ pthread_mutex_lock(mutex);
173
+ cancelled = uib->worker_cancelled;
174
+ if (trn->writer_wrote) {
175
+ trn->writer_wrote = 0;
176
+ zsv_index_commit_rows(uib->index);
177
+ uib->index_ready = 1;
178
+ }
179
+ pthread_mutex_unlock(mutex);
180
+ }
181
+
182
+ if (zst == zsv_status_no_more_input || zst == zsv_status_cancelled)
183
+ zsv_finish(parser);
184
+
185
+ if (trn->on_done)
186
+ trn->on_done(trn);
187
+
188
+ if (trn->user_context)
189
+ free(trn->user_context);
190
+
191
+ zsvsheet_transformation_delete(trn);
192
+
193
+ pthread_mutex_lock(mutex);
194
+ char *buff_status_old = uib->status;
195
+ uib->write_done = 1;
196
+ zsv_index_commit_rows(uib->index);
197
+ uib->index_ready = 1;
198
+ if (buff_status_old == default_status)
199
+ uib->status = NULL;
200
+ pthread_mutex_unlock(mutex);
201
+
202
+ if (buff_status_old == default_status)
203
+ free(buff_status_old);
204
+
205
+ return NULL;
206
+ }
207
+
208
+ enum zsvsheet_status zsvsheet_push_transformation(zsvsheet_proc_context_t ctx,
209
+ struct zsvsheet_buffer_transformation_opts opts) {
210
+ zsvsheet_buffer_t buff = zsvsheet_buffer_current(ctx);
211
+ const char *filename = zsvsheet_buffer_data_filename(buff);
212
+ enum zsvsheet_status stat = zsvsheet_status_error;
213
+ struct zsvsheet_buffer_info_internal info = zsvsheet_buffer_info_internal(buff);
214
+ struct zsv_index *index = NULL;
215
+
216
+ // TODO: Starting a second transformation before the first ends works, but if the second is faster
217
+ // than the first then it can end prematurely and read a partially written row.
218
+ // We could override the input stream reader to wait for more data when it sees EOF
219
+ if (info.write_in_progress && !info.write_done)
220
+ return zsvsheet_status_busy;
221
+
222
+ if (!(index = zsv_index_new()))
223
+ return zsvsheet_status_memory;
224
+
225
+ // TODO: custom_prop_handler is not passed to extensions?
226
+ struct zsvsheet_transformation_opts trn_opts = {
227
+ .custom_prop_handler = NULL,
228
+ .input_filename = filename,
229
+ .on_done = opts.on_done,
230
+ .ui_buffer = NULL,
231
+ .index = index,
232
+ };
233
+ zsvsheet_transformation trn = NULL;
234
+ struct zsv_opts zopts = zsvsheet_buffer_get_zsv_opts(buff);
235
+
236
+ zopts.ctx = opts.user_context;
237
+ zopts.row_handler = (void (*)(void *))opts.row_handler;
238
+ zopts.stream = fopen(filename, "rb");
239
+ zopts.buffsize = 2 * 1024 * 1024;
240
+
241
+ if (!zopts.stream)
242
+ goto error;
243
+
244
+ trn_opts.zsv_opts = zopts;
245
+
246
+ enum zsv_status zst = zsvsheet_transformation_new(trn_opts, &trn);
247
+ if (zst != zsv_status_ok)
248
+ goto error;
249
+
250
+ // Transform part of the file to initially populate the UI buffer
251
+ // TODO: If the transformation is a reduction that doesn't output for some time this will caus a pause
252
+ zsv_parser parser = zsvsheet_transformation_parser(trn);
253
+ while ((zst = zsv_parse_more(parser)) == zsv_status_ok) {
254
+ if (trn->writer_wrote)
255
+ break;
256
+ }
257
+ trn->writer_wrote = 0;
258
+
259
+ switch (zst) {
260
+ case zsv_status_no_more_input:
261
+ case zsv_status_cancelled:
262
+ if (zsv_finish(parser) != zsv_status_ok)
263
+ goto error;
264
+ zsv_writer_flush(trn->writer);
265
+ break;
266
+ case zsv_status_ok:
267
+ break;
268
+ default:
269
+ goto error;
270
+ }
271
+
272
+ struct zsvsheet_ui_buffer_opts uibopts = {0};
273
+
274
+ uibopts.data_filename = zsvsheet_transformation_filename(trn);
275
+ uibopts.write_after_open = 1;
276
+
277
+ stat = zsvsheet_open_file_opts(ctx, &uibopts);
278
+ if (stat != zsvsheet_status_ok)
279
+ goto error;
280
+
281
+ struct zsvsheet_ui_buffer *nbuff = zsvsheet_buffer_current(ctx);
282
+ trn->ui_buffer = nbuff;
283
+ zsv_index_commit_rows(index);
284
+ nbuff->index_started = 1;
285
+ nbuff->index = index;
286
+
287
+ if (zst != zsv_status_ok) {
288
+ nbuff->write_done = 1;
289
+ nbuff->index_ready = 1;
290
+ if (trn->on_done)
291
+ opts.on_done(trn);
292
+ zsvsheet_transformation_delete(trn);
293
+ zsv_index_commit_rows(index);
294
+ return stat;
295
+ }
296
+
297
+ asprintf(&trn->default_status, "(working) Press ESC to cancel ");
298
+ nbuff->status = trn->default_status;
299
+
300
+ zsvsheet_ui_buffer_create_worker(nbuff, zsvsheet_run_buffer_transformation, trn);
301
+ return stat;
302
+
303
+ error:
304
+ zsv_index_delete(index);
305
+
306
+ if (trn && trn->on_done)
307
+ opts.on_done(trn);
308
+ if (trn)
309
+ zsvsheet_transformation_delete(trn);
310
+
311
+ return stat;
312
+ }