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,366 @@
1
+ /*
2
+ * Copyright (C) 2021 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 <stdlib.h>
9
+ #include <string.h>
10
+ #include <assert.h>
11
+ #include <zsv/ext/implementation.h>
12
+ #include <zsv/ext/sheet.h>
13
+ #include <zsv/utils/writer.h>
14
+ #include <zsv/utils/file.h>
15
+
16
+ /**
17
+ * `zsv` can easily be extended by simply creating a shared library
18
+ * that implements the interface specified in zsv/ext/implementation.h
19
+ * for any extension id of up to 8 bytes
20
+ *
21
+ * Once the library file is created, you can run any commands it implements
22
+ * by naming the library file zsvext<id>, placing it in any folder that is
23
+ * in the system lib search path, or in the same folder as zsv, and running:
24
+ * `zsv xx-command`
25
+ *
26
+ * It's as simple as that!
27
+ *
28
+ * In this example, we will implement two simple commands:
29
+ * * `count` will count lines
30
+ * * `echo` will regurgitate its input to stdout
31
+ *
32
+ * We will name our extension "my", so our shared library will be named
33
+ * zsvextmy.so (non-win) or zsvextmy.dll (win). After the shared lib is built,
34
+ * place it anywhere in the PATH or in the same folder as the zsv binary.
35
+ * Our extension commands can then be invoked by running:
36
+ * `zsv my-count`
37
+ * `zsv my-echo`
38
+ *
39
+ * in addition, a description of our extension is available via:
40
+ * `zsv help`
41
+ *
42
+ * and command-specific help displayed via:
43
+ * `zsv help my-<command>`
44
+ *
45
+ */
46
+
47
+ /**
48
+ * *Required*: define our extension id, of up to 8 bytes in length
49
+ */
50
+ const char *zsv_ext_id(void) {
51
+ return "my";
52
+ }
53
+
54
+ /**
55
+ * When our library is initialized, zsv will pass it the address of the zsvlib
56
+ * functions we will be using. We can keep track of this any way we want;
57
+ * in this example, we use a global variable to store the function pointers
58
+ */
59
+ static struct zsv_ext_callbacks zsv_cb;
60
+
61
+ /**
62
+ * Each command must be implemented as a function with a signature
63
+ * as defined by `zsv_ext_main`. This is basically the same as a main() function,
64
+ * but with an additional preceding zsv_execution_context parameter.
65
+ * Here, we just declare the functions; we fully define them further below
66
+ */
67
+ enum zsv_ext_status count_main(zsv_execution_context ctx, int argc, const char *argv[], struct zsv_opts *opts);
68
+ static enum zsv_ext_status echo_main(zsv_execution_context ctx, int argc, const char *argv[], struct zsv_opts *opts);
69
+
70
+ #ifdef ZSVSHEET_BUILD
71
+
72
+ /**
73
+ * Here we define a custom command for the zsv `sheet` feature
74
+ */
75
+ zsvsheet_status my_test_command_handler(zsvsheet_proc_context_t ctx) {
76
+ char result_buffer[256] = {0};
77
+ int ch = zsv_cb.ext_sheet_keypress(ctx);
78
+ if (ch < 0)
79
+ return zsvsheet_status_error;
80
+ zsv_cb.ext_sheet_prompt(ctx, result_buffer, sizeof(result_buffer), "You pressed %c. Now enter something here",
81
+ (char)ch);
82
+ if (*result_buffer == '\0')
83
+ return zsvsheet_status_ok;
84
+
85
+ char *temp_filename = zsv_get_temp_filename("zsvsheet_extension_example.csv");
86
+ if (!temp_filename) {
87
+ fprintf(stderr, "Out of memory!\n");
88
+ return zsvsheet_status_error;
89
+ }
90
+
91
+ FILE *f = fopen(temp_filename, "wb");
92
+ if (!f)
93
+ zsv_cb.ext_sheet_set_status(ctx, "Unable to open for write: %s", temp_filename);
94
+ else {
95
+ fprintf(f, "buffer #,file name\n");
96
+ // get a count of open buffers
97
+ int i = 0;
98
+ for (zsvsheet_buffer_t buff = zsv_cb.ext_sheet_buffer_current(ctx); buff;
99
+ buff = zsv_cb.ext_sheet_buffer_prior(buff), i++)
100
+ ;
101
+
102
+ // print a list of open buffers and filenames
103
+ for (zsvsheet_buffer_t buff = zsv_cb.ext_sheet_buffer_current(ctx); buff;
104
+ buff = zsv_cb.ext_sheet_buffer_prior(buff), i--) {
105
+ const char *buff_filename = zsv_cb.ext_sheet_buffer_data_filename(buff);
106
+ if (buff_filename)
107
+ fprintf(f, "%i,%s\n", i, buff_filename); // assumes no need for quoting or escaping buff_filename...
108
+ }
109
+ fclose(f);
110
+ return zsv_cb.ext_sheet_open_file(ctx, temp_filename, NULL);
111
+ }
112
+ free(temp_filename);
113
+ return zsvsheet_status_ok;
114
+ }
115
+
116
+ struct transformation_context {
117
+ zsvsheet_proc_context_t proc_ctx;
118
+ size_t col_count;
119
+ size_t row_count;
120
+ };
121
+
122
+ // Similar to a regular ZSV row handler used in ext_parse_all
123
+ void my_transformation_row_handler(zsvsheet_transformation trn) {
124
+ struct transformation_context *priv = zsv_cb.ext_sheet_transformation_user_context(trn);
125
+ zsv_parser parser = zsv_cb.ext_sheet_transformation_parser(trn);
126
+ zsv_csv_writer writer = zsv_cb.ext_sheet_transformation_writer(trn);
127
+
128
+ size_t j = zsv_cb.cell_count(parser);
129
+ for (size_t i = 0; i < j; i++) {
130
+ struct zsv_cell c = zsv_cb.get_cell(parser, i);
131
+ zsv_writer_cell(writer, i == 0, c.str, c.len, c.quoted);
132
+ }
133
+
134
+ priv->col_count += j;
135
+
136
+ if (!priv->row_count)
137
+ zsv_writer_cell_s(writer, 0, (const unsigned char *)"Column count", 0);
138
+ else
139
+ zsv_writer_cell_zu(writer, 0, priv->col_count);
140
+
141
+ priv->row_count++;
142
+ }
143
+
144
+ zsvsheet_status my_transformation_command_handler(zsvsheet_proc_context_t ctx) {
145
+ struct zsvsheet_buffer_transformation_opts opts = {
146
+ // Gets freed automatically
147
+ .user_context = calloc(1, sizeof(struct transformation_context)),
148
+ .row_handler = my_transformation_row_handler,
149
+ .on_done = NULL,
150
+ };
151
+
152
+ return zsv_cb.ext_sheet_push_transformation(ctx, opts);
153
+ }
154
+ #endif
155
+
156
+ /**
157
+ * *Required*. Initialization is called when our extension is loaded. Our
158
+ * initialization routine uses `ext_add_command` to register our commands and
159
+ * `ext_set_help` to set the help text. When we register a command, we provide a
160
+ * callback-- in our cases, those will be `count_main()` and `echo_main()`-- for
161
+ * zsv to invoke when our command is run
162
+ *
163
+ * @param callbacks pointers to zsvlib functions that we must save for later use
164
+ * @param ctx context to be passed whenever we execute a zsvlib function from our init
165
+ * @return status code e.g. zsv_ext_status_ok
166
+ */
167
+
168
+ enum zsv_ext_status zsv_ext_init(struct zsv_ext_callbacks *cb, zsv_execution_context ctx) {
169
+ zsv_cb = *cb;
170
+ zsv_cb.ext_set_help(ctx, "Sample zsv extension");
171
+ zsv_cb.ext_set_license(ctx,
172
+ "Unlicense. See https://github.com/spdx/license-list-data/blob/master/text/Unlicense.txt");
173
+ /**
174
+ * In the common case where your extension uses third-party software, you can add
175
+ * the related licenses and acknowledgements here, which `zsv` will display whenever
176
+ * `zsv thirdparty` is invoked
177
+ */
178
+ const char *third_party_licenses[] = {"If we used any third-party software, we would list each license here", NULL};
179
+ zsv_cb.ext_set_thirdparty(ctx, third_party_licenses);
180
+ zsv_cb.ext_add_command(ctx, "count", "print the number of rows", count_main);
181
+ zsv_cb.ext_add_command(ctx, "echo", "print the input data back to stdout", echo_main);
182
+
183
+ #ifdef ZSVSHEET_BUILD
184
+ int proc_id = zsv_cb.ext_sheet_register_proc("my-test-command", "my test command", my_test_command_handler);
185
+ if (proc_id < 0)
186
+ return zsv_ext_status_error;
187
+ zsv_cb.ext_sheet_register_proc_key_binding('t', proc_id);
188
+
189
+ proc_id = zsv_cb.ext_sheet_register_proc("my-transformation", "my transformation", my_transformation_command_handler);
190
+ if (proc_id < 0)
191
+ return zsv_ext_status_error;
192
+ zsv_cb.ext_sheet_register_proc_key_binding('T', proc_id);
193
+ #endif
194
+ return zsv_ext_status_ok;
195
+ }
196
+
197
+ /**
198
+ * exit: called once by zsv before the library is unloaded, if `zsv_ext_init()` was
199
+ * previously called
200
+ */
201
+ enum zsv_ext_status zsv_ext_exit(void) {
202
+ fprintf(stderr, "Exiting extension example!\n");
203
+ return zsv_ext_status_ok;
204
+ }
205
+ /**
206
+ * Now we are getting to the "meat" of our program. Each command will be defined by two
207
+ * functions:
208
+ * - a main routine, which initializes private data, calls the parser, then performs any final
209
+ * steps and/or cleanup
210
+ * - a row handler, which is called by the parser for each parsed row
211
+ */
212
+
213
+ /**
214
+ * structure that our functions will use to store private state data
215
+ * which our functions can retrieve using the zsvlib callback `ext_get_context()`
216
+ */
217
+ struct my_data {
218
+ zsv_csv_writer csv_writer;
219
+ size_t rows;
220
+ };
221
+
222
+ /**
223
+ * Our row handlers retrieve our state data and update and/or operate on it
224
+ * We can choose, in our main routine, for the ctx pointer it receives to be
225
+ * anything we want, but in most cases there is no reason to set it to anything
226
+ * other than the zsv_execution_context passed to main
227
+ *
228
+ * @param ctx a context pointer of our choice, typically set in the main() function
229
+ */
230
+
231
+ static void count_rowhandler(void *ctx) {
232
+ /* get our private data */
233
+ struct my_data *data = zsv_cb.ext_get_context(ctx);
234
+
235
+ /* increment row counter */
236
+ data->rows++;
237
+ }
238
+
239
+ static void echo_rowhandler(void *ctx) {
240
+ /* get our private data */
241
+ struct my_data *data = zsv_cb.ext_get_context(ctx);
242
+
243
+ /**
244
+ * In most cases, we will want to do something with the row that was just parsed,
245
+ * in which case we can use ext_get_parser(), cell_count() and get_cell()
246
+ * to get a parser handle, the number of cells in our current row, and each
247
+ * cell's length and string (and other info)
248
+ */
249
+ zsv_parser parser = zsv_cb.ext_get_parser(ctx);
250
+ unsigned j = zsv_cb.cell_count(parser);
251
+ for (unsigned i = 0; i < j; i++) {
252
+ struct zsv_cell c = zsv_cb.get_cell(parser, i);
253
+
254
+ /**
255
+ * get_cell() returns a zsv_cell structure that holds a pointer to the text,
256
+ * the length (in bytes) of the data,
257
+ * and other parser-generated info (e.g. QUOTED flags)
258
+ */
259
+ /* write the cell contents to csv output */
260
+ zsv_writer_cell(data->csv_writer, i == 0, c.str, c.len, c.quoted);
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Our main routines are similar to normal main() functions, except that the first
266
+ * param is a zsvlib-generated zsv_execution_context pointer for use with other
267
+ * `ext_xxx` functions. All we do here is initialize our data, call the parser, and
268
+ * perform any final steps after all data has been processed
269
+ */
270
+ static enum zsv_ext_status echo_main(zsv_execution_context ctx, int argc, const char *argv[], struct zsv_opts *optsp) {
271
+ (void)(argc);
272
+ (void)(argv);
273
+ (void)(optsp);
274
+ /* initialize private data */
275
+ struct my_data data;
276
+ memset(&data, 0, sizeof(data));
277
+
278
+ /* initialize a csv writer, which we add to our private data structure */
279
+ unsigned char writer_buff[128];
280
+ /**
281
+ * the the zsv_writer utility has two special optimizations: first, it
282
+ * uses its own buffer to short-circuit costly stdio operations, and second,
283
+ * it accepts a 'quoted' flag that, if zero, tells it to not bother
284
+ * checking for quote requirements and to just output the contents 'raw'
285
+ */
286
+ if (!(data.csv_writer = zsv_writer_new(NULL)))
287
+ return zsv_ext_status_memory;
288
+ zsv_writer_set_temp_buff(data.csv_writer, writer_buff, sizeof(writer_buff));
289
+
290
+ /**
291
+ * The following common parser options that are already handled by zsv (so long as we use
292
+ * either of the provided callbacks `ext_parse_all()` or `new_with_context()`), including:
293
+ * ```
294
+ * -B,--buff-size <N>
295
+ * -c,--max-column-count <N>
296
+ * -r,--max-row-size <N>
297
+ * -t,--tab-delim
298
+ * -O,--other-delim <C>
299
+ * -q,--no-quote
300
+ * -R,--skip-head <n>: skip specified number of initial rows
301
+ * -d,--header-row-span <n>: apply header depth (rowspan) of n
302
+ * -S,--keep-blank-headers: disable default behavior of ignoring leading blank rows
303
+ * -v,--verbose: verbose output
304
+ * ```
305
+ *
306
+ * If we wanted our command to support parameters for modifying other
307
+ * `zsv_opts`, we could do so here by processing argc and argv[] and taking
308
+ * the appropriate actions to change our private data and/or modify our opts
309
+ * structure
310
+ *
311
+ * For this example, we will not implement any additional options, so the only
312
+ * `zsv_opts` value we need to update is the row handler
313
+ */
314
+
315
+ /**
316
+ * use the `ext_parse_all()` convenience function
317
+ */
318
+ struct zsv_opts opts = zsv_cb.ext_parser_opts(ctx);
319
+ enum zsv_ext_status stat = zsv_cb.ext_parse_all(ctx, &data, echo_rowhandler, &opts);
320
+
321
+ /**
322
+ * clean up after we finish parsing
323
+ */
324
+ zsv_writer_delete(data.csv_writer);
325
+
326
+ /**
327
+ * the return value of the main function will be passed on as the return value
328
+ * of this process invocation
329
+ */
330
+ return stat;
331
+ }
332
+
333
+ /**
334
+ * Our main routine for counting is just like the one for echo, but even simpler
335
+ * since we need not bother with a csv writer
336
+ */
337
+ static const char *count_help = "count: print the number of rows in a CSV data file\n"
338
+ "\n"
339
+ "usage: count [-h,--help] [filename]\n";
340
+
341
+ enum zsv_ext_status count_main(zsv_execution_context ctx, int argc, const char *argv[], struct zsv_opts *optsp) {
342
+ (void)(optsp);
343
+ /* help */
344
+ if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))) {
345
+ printf("%s", count_help);
346
+ return zsv_ext_status_ok;
347
+ }
348
+
349
+ /* initialize private data. see above for details */
350
+ struct my_data data = {0};
351
+ struct zsv_opts opts = zsv_cb.ext_parser_opts(ctx);
352
+
353
+ if (argc > 1 && !(opts.stream = fopen(argv[1], "rb"))) {
354
+ fprintf(stderr, "Unable to open for reading: %s\n", argv[1]);
355
+ return 1;
356
+ }
357
+
358
+ /* parse the input data. see above for details */
359
+ enum zsv_ext_status stat = zsv_cb.ext_parse_all(ctx, &data, count_rowhandler, &opts);
360
+
361
+ /* finish up */
362
+ if (stat == zsv_ext_status_ok)
363
+ printf("Rows: %zu\n", data.rows > 0 ? data.rows - 1 : 0);
364
+
365
+ return stat;
366
+ }
@@ -0,0 +1,341 @@
1
+ /*
2
+ * Copyright (C) 2021 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 <stdlib.h>
9
+ #include <string.h>
10
+ #include <errno.h>
11
+ #include <assert.h>
12
+ #include "../external/sqlite3/sqlite3.h"
13
+ #include <zsv/ext/implementation.h>
14
+ #include <zsv/ext/sheet.h>
15
+ #include <zsv/utils/writer.h>
16
+ #include <zsv/utils/file.h>
17
+ #include <zsv/utils/prop.h>
18
+ // #include "../curses.h"
19
+
20
+ /**
21
+ * This is an example to demonstrate various extension capabilities
22
+ * specific to the `sheet` subcommand. For examples of extending the
23
+ * CLI outside of `sheet`, see my_extension.c
24
+ *
25
+ * In this example, we will re-implement the built-in pivot table command
26
+ *
27
+ * We will name our extension "mysheet", so our shared library will be named
28
+ * zsvextmysheet.so (non-win) or zsvextmysheet.dll (win). After the shared lib is
29
+ * built, place it anywhere in the PATH or in the same folder as the zsv binary.
30
+ * Our extension can then be invoked by first running `sheet`, and then pressing
31
+ * 'z'
32
+ *
33
+ * in addition, a description of our extension is displayed in the built-in help
34
+ * command (?)
35
+ *
36
+ */
37
+
38
+ /**
39
+ * *Required*: define our extension id, of up to 8 bytes in length
40
+ */
41
+ const char *zsv_ext_id(void) {
42
+ return "mysheet";
43
+ }
44
+
45
+ /**
46
+ * When our library is initialized, zsv will pass it the address of the zsvlib
47
+ * functions we will be using. We can keep track of this any way we want;
48
+ * in this example, we use a global variable to store the function pointers
49
+ */
50
+ static struct zsv_ext_callbacks zsv_cb;
51
+
52
+ #include "../sql_internal.h"
53
+
54
+ struct pivot_row {
55
+ char *value; // to do: this will be the drill-down criteria
56
+ };
57
+
58
+ struct pivot_data {
59
+ char *value_sql; // the sql expression entered by the user e.g. City
60
+ char *data_filename;
61
+ struct {
62
+ struct pivot_row *data; // for each row, the value of the sql expression e.g. New York
63
+ size_t capacity;
64
+ size_t used;
65
+ } rows;
66
+ };
67
+
68
+ static void pivot_data_delete(void *h) {
69
+ struct pivot_data *pd = h;
70
+ if (pd) {
71
+ for (size_t i = 0; i < pd->rows.used; i++)
72
+ free(pd->rows.data[i].value);
73
+ free(pd->rows.data);
74
+ free(pd->value_sql);
75
+ free(pd->data_filename);
76
+ free(pd);
77
+ }
78
+ }
79
+
80
+ static struct pivot_data *pivot_data_new(const char *data_filename, const char *value_sql) {
81
+ struct pivot_data *pd = calloc(1, sizeof(*pd));
82
+ if (pd && (pd->value_sql = strdup(value_sql)) && (pd->data_filename = strdup(data_filename)))
83
+ return pd;
84
+ pivot_data_delete(pd);
85
+ return NULL;
86
+ }
87
+
88
+ #define ZSV_MYSHEET_EXTENSION_PIVOT_DATA_ROWS_INITIAL 32
89
+ static int pivot_data_grow(struct pivot_data *pd) {
90
+ if (pd->rows.used == pd->rows.capacity) {
91
+ size_t new_capacity =
92
+ pd->rows.capacity == 0 ? ZSV_MYSHEET_EXTENSION_PIVOT_DATA_ROWS_INITIAL : pd->rows.capacity * 2;
93
+ struct pivot_row *new_data = realloc(pd->rows.data, new_capacity * sizeof(*pd->rows.data));
94
+ if (!new_data)
95
+ return ENOMEM;
96
+ pd->rows.data = new_data;
97
+ pd->rows.capacity = new_capacity;
98
+ }
99
+ return 0;
100
+ }
101
+
102
+ static int add_pivot_row(struct pivot_data *pd, const char *value, size_t len) {
103
+ int err = pivot_data_grow(pd);
104
+ char *value_dup = NULL;
105
+ if (!err && value && len) {
106
+ value_dup = malloc(len + 1);
107
+ if (value_dup) {
108
+ memcpy(value_dup, value, len);
109
+ value_dup[len] = '\0';
110
+ }
111
+ }
112
+ pd->rows.data[pd->rows.used++].value = value_dup;
113
+ return err;
114
+ }
115
+
116
+ static struct pivot_row *get_pivot_row_data(struct pivot_data *pd, size_t row_ix) {
117
+ if (pd && row_ix < pd->rows.used)
118
+ return &pd->rows.data[row_ix];
119
+ return NULL;
120
+ }
121
+
122
+ // TO DO: return zsvsheet_status
123
+ static enum zsv_ext_status get_cell_attrs(void *pdh, zsvsheet_cell_attr_t *attrs, size_t start_row, size_t row_count,
124
+ size_t cols) {
125
+ struct pivot_data *pd = pdh;
126
+ size_t end_row = start_row + row_count;
127
+ if (end_row > pd->rows.used)
128
+ end_row = pd->rows.used;
129
+ for (size_t i = start_row; i < end_row; i++)
130
+ attrs[i * cols] = zsv_cb.ext_sheet_cell_profile_attrs(zsvsheet_cell_attr_profile_link);
131
+ return zsv_ext_status_ok;
132
+ }
133
+
134
+ static void pivot_on_header_cell(void *ctx, size_t col_ix, const char *colname) {
135
+ if (col_ix == 0) {
136
+ add_pivot_row(ctx, NULL, 0);
137
+ }
138
+ }
139
+
140
+ static void pivot_on_data_cell(void *ctx, size_t col_ix, const char *text, size_t len) {
141
+ if (col_ix == 0)
142
+ add_pivot_row(ctx, text, len);
143
+ }
144
+
145
+ static zsvsheet_status zsv_sqlite3_to_csv(zsvsheet_proc_context_t pctx, struct zsv_sqlite3_db *zdb, const char *sql,
146
+ void *ctx, void (*on_header_cell)(void *, size_t, const char *),
147
+ void (*on_data_cell)(void *, size_t, const char *, size_t len)) {
148
+ const char *err_msg = NULL;
149
+ zsvsheet_status zst = zsvsheet_status_error;
150
+ sqlite3_stmt *stmt = NULL;
151
+ if ((zdb->rc = sqlite3_prepare_v2(zdb->db, sql, -1, &stmt, NULL)) == SQLITE_OK) {
152
+ char *tmp_fn = zsv_get_temp_filename("zsv_mysheet_ext_XXXXXXXX");
153
+ struct zsv_csv_writer_options writer_opts = zsv_writer_get_default_opts();
154
+ zsv_csv_writer cw = NULL;
155
+ if (!tmp_fn)
156
+ zst = zsvsheet_status_memory;
157
+ else if (!(writer_opts.stream = fopen(tmp_fn, "wb"))) {
158
+ zst = zsvsheet_status_error;
159
+ err_msg = strerror(errno);
160
+ } else if (!(cw = zsv_writer_new(&writer_opts)))
161
+ zst = zsvsheet_status_memory;
162
+ else {
163
+ zst = zsvsheet_status_ok;
164
+ unsigned char cw_buff[1024];
165
+ zsv_writer_set_temp_buff(cw, cw_buff, sizeof(cw_buff));
166
+
167
+ int col_count = sqlite3_column_count(stmt);
168
+ // write header row
169
+ for (int i = 0; i < col_count; i++) {
170
+ const char *colname = sqlite3_column_name(stmt, i);
171
+ zsv_writer_cell(cw, !i, (const unsigned char *)colname, colname ? strlen(colname) : 0, 1);
172
+ if (on_header_cell)
173
+ on_header_cell(ctx, i, colname);
174
+ }
175
+
176
+ // write sql results
177
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
178
+ for (int i = 0; i < col_count; i++) {
179
+ const unsigned char *text = sqlite3_column_text(stmt, i);
180
+ int len = text ? sqlite3_column_bytes(stmt, i) : 0;
181
+ zsv_writer_cell(cw, !i, text, len, 1);
182
+ if (on_data_cell)
183
+ on_data_cell(ctx, i, text, len);
184
+ }
185
+ }
186
+ }
187
+ if (cw)
188
+ zsv_writer_delete(cw);
189
+ if (writer_opts.stream)
190
+ fclose(writer_opts.stream);
191
+
192
+ if (tmp_fn && zsv_file_exists(tmp_fn))
193
+ zst = zsv_cb.ext_sheet_open_file(pctx, tmp_fn, NULL);
194
+ else {
195
+ if (zst == zsvsheet_status_ok) {
196
+ zst = zsvsheet_status_error; // to do: make this more specific
197
+ if (!err_msg && zdb && zdb->rc != SQLITE_OK)
198
+ err_msg = sqlite3_errmsg(zdb->db);
199
+ }
200
+ }
201
+ free(tmp_fn);
202
+ }
203
+ if (stmt)
204
+ sqlite3_finalize(stmt);
205
+ if (err_msg)
206
+ zsv_cb.ext_sheet_set_status(ctx, "Error: %s", err_msg);
207
+ return zst;
208
+ }
209
+
210
+ //
211
+ zsvsheet_status pivot_drill_down(zsvsheet_proc_context_t ctx) {
212
+ enum zsvsheet_status zst = zsvsheet_status_ok;
213
+ char result_buffer[256] = {0};
214
+ zsvsheet_buffer_t buff = zsv_cb.ext_sheet_buffer_current(ctx);
215
+ struct pivot_data *pd;
216
+ struct zsvsheet_rowcol rc;
217
+ if (zsv_cb.ext_sheet_buffer_get_ctx(buff, (void **)&pd) != zsv_ext_status_ok ||
218
+ zsv_cb.ext_sheet_buffer_get_selected_cell(buff, &rc) != zsvsheet_status_ok) {
219
+ return zsvsheet_status_error;
220
+ }
221
+ struct pivot_row *pr = get_pivot_row_data(pd, rc.row);
222
+ if (pd && pd->data_filename && pd->value_sql && pr) {
223
+ // zsv_cb.ext_sheet_prompt(ctx, result_buffer, sizeof(result_buffer), "You are in pivot_drill_down! row = %zu, value
224
+ // = %s\n", rc.row, pr->value ? pr->value : "(null)");
225
+
226
+ struct zsv_sqlite3_dbopts dbopts = {0};
227
+ sqlite3_str *sql_str = NULL;
228
+ struct zsv_sqlite3_db *zdb = zsv_cb.ext_sqlite3_db_new(&dbopts);
229
+ if (!zdb || !(sql_str = sqlite3_str_new(zdb->db)))
230
+ zst = zsvsheet_status_memory;
231
+ else if (zdb->rc == SQLITE_OK && zsv_cb.ext_sqlite3_add_csv(zdb, pd->data_filename, NULL, NULL) == SQLITE_OK) {
232
+ if (zsv_cb.ext_sheet_buffer_info(buff).has_row_num)
233
+ sqlite3_str_appendf(sql_str, "select *");
234
+ else
235
+ sqlite3_str_appendf(sql_str, "select rowid as [Row #], *");
236
+ sqlite3_str_appendf(sql_str, " from data where %s = %Q", pd->value_sql, pr->value);
237
+ fprintf(stderr, "SQL: %s\n", sqlite3_str_value(sql_str));
238
+ zst = zsv_sqlite3_to_csv(ctx, zdb, sqlite3_str_value(sql_str), NULL, NULL, NULL);
239
+ }
240
+ if (sql_str)
241
+ sqlite3_free(sqlite3_str_finish(sql_str));
242
+ if (zdb) {
243
+ if (zst != zsvsheet_status_ok) {
244
+ // to do: consolidate this with same code in sql.c
245
+ if (zdb->err_msg)
246
+ fprintf(stderr, "Error: %s\n", zdb->err_msg);
247
+ else if (!zdb->db)
248
+ fprintf(stderr, "Error (unable to open db, code %i): %s\n", zdb->rc, sqlite3_errstr(zdb->rc));
249
+ else if (zdb->rc != SQLITE_OK)
250
+ fprintf(stderr, "Error (code %i): %s\n", zdb->rc, sqlite3_errstr(zdb->rc));
251
+ }
252
+ zsv_cb.ext_sqlite3_db_delete(zdb);
253
+ }
254
+ }
255
+ return zst;
256
+ }
257
+
258
+ /**
259
+ * Here we define a custom command for the zsv `sheet` feature
260
+ */
261
+ zsvsheet_status my_pivot_table_command_handler(zsvsheet_proc_context_t ctx) {
262
+ char result_buffer[256] = {0};
263
+ int ch = zsv_cb.ext_sheet_keypress(ctx);
264
+ if (ch < 0)
265
+ return zsvsheet_status_error;
266
+ zsvsheet_buffer_t buff = zsv_cb.ext_sheet_buffer_current(ctx);
267
+ const char *data_filename = NULL;
268
+ if (buff)
269
+ data_filename = zsv_cb.ext_sheet_buffer_data_filename(buff);
270
+ if (!data_filename) { // TO DO: check that the underlying data is a tabular file and we know how to parse
271
+ zsv_cb.ext_sheet_set_status(ctx, "Pivot table only available for tabular data buffers");
272
+ return zsvsheet_status_ok;
273
+ }
274
+ struct zsv_opts opts = zsv_cb.ext_sheet_buffer_get_zsv_opts(buff);
275
+ zsv_cb.ext_sheet_prompt(ctx, result_buffer, sizeof(result_buffer), "Pivot table: Enter group-by SQL expr");
276
+ if (*result_buffer == '\0')
277
+ return zsvsheet_status_ok;
278
+
279
+ enum zsvsheet_status zst = zsvsheet_status_ok;
280
+ struct zsv_sqlite3_dbopts dbopts = {0};
281
+ struct zsv_sqlite3_db *zdb = zsv_cb.ext_sqlite3_db_new(&dbopts);
282
+ sqlite3_str *sql_str = NULL;
283
+ struct pivot_data *pd = NULL;
284
+ if (!zdb || !(sql_str = sqlite3_str_new(zdb->db)))
285
+ zst = zsvsheet_status_memory;
286
+ else if (zdb->rc == SQLITE_OK && zsv_cb.ext_sqlite3_add_csv(zdb, data_filename, NULL, NULL) == SQLITE_OK) {
287
+ sqlite3_str_appendf(sql_str, "select %s as value, count(1) as Count from data group by %s", result_buffer,
288
+ result_buffer);
289
+ if (!(pd = pivot_data_new(data_filename, result_buffer)))
290
+ zst = zsvsheet_status_memory;
291
+ else {
292
+ zst = zsv_sqlite3_to_csv(ctx, zdb, sqlite3_str_value(sql_str), pd, pivot_on_header_cell, pivot_on_data_cell);
293
+ if (zst == zsvsheet_status_ok) {
294
+ zsvsheet_buffer_t buff = zsv_cb.ext_sheet_buffer_current(ctx);
295
+ zsv_cb.ext_sheet_buffer_set_ctx(buff, pd, pivot_data_delete);
296
+ zsv_cb.ext_sheet_buffer_set_cell_attrs(buff, get_cell_attrs);
297
+ zsv_cb.ext_sheet_buffer_on_newline(buff, pivot_drill_down);
298
+ pd = NULL; // so that it isn't cleaned up below
299
+ }
300
+ }
301
+ // TO DO: add param to ext_sheet_open_file to set filename vs data_filename, and set buffer type or proc owner
302
+ // TO DO: add way to attach custom context, and custom context destructor, to the new buffer
303
+ // TO DO: add cell highlighting
304
+ // TO DO: add drill-down
305
+ }
306
+
307
+ out:
308
+ zsv_cb.ext_sqlite3_db_delete(zdb);
309
+ if (sql_str)
310
+ sqlite3_free(sqlite3_str_finish(sql_str));
311
+ pivot_data_delete(pd);
312
+ return zst;
313
+ }
314
+
315
+ /**
316
+ * *Required*. Initialization is called when our extension is loaded
317
+ * See my_extension.c for details
318
+ */
319
+
320
+ enum zsv_ext_status zsv_ext_init(struct zsv_ext_callbacks *cb, zsv_execution_context ctx) {
321
+ zsv_cb = *cb;
322
+ zsv_cb.ext_set_help(ctx, "Sample zsv sheet extension");
323
+ zsv_cb.ext_set_license(ctx,
324
+ "Unlicense. See https://github.com/spdx/license-list-data/blob/master/text/Unlicense.txt");
325
+ const char *third_party_licenses[] = {"If we used any third-party software, we would list each license here", NULL};
326
+ zsv_cb.ext_set_thirdparty(ctx, third_party_licenses);
327
+ int proc_id = zsv_cb.ext_sheet_register_proc("my-sheet-pivot", "my sheet pivot", my_pivot_table_command_handler);
328
+ if (proc_id < 0)
329
+ return zsv_ext_status_error;
330
+ zsv_cb.ext_sheet_register_proc_key_binding('v', proc_id);
331
+ return zsv_ext_status_ok;
332
+ }
333
+
334
+ /**
335
+ * exit: called once by zsv before the library is unloaded, if `zsv_ext_init()` was
336
+ * previously called
337
+ */
338
+ enum zsv_ext_status zsv_ext_exit(void) {
339
+ fprintf(stderr, "Exiting mysheet extension example!\n");
340
+ return zsv_ext_status_ok;
341
+ }