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,123 @@
1
+ #include <stdio.h>
2
+ #include <stdlib.h>
3
+ #include <string.h>
4
+ #include "./pcre2-8.h"
5
+
6
+ /**
7
+ * @brief Reads an entire file into a new buffer.
8
+ *
9
+ * @param filename The name of the file to read.
10
+ * @param out_size Pointer to a size_t to store the file size.
11
+ * @return A new buffer containing the file contents (must be free'd) or NULL on error.
12
+ */
13
+ char *read_file_to_buffer(const char *filename, size_t *out_size) {
14
+ const char *tmp_filename = "./pcre2-8-test.temp";
15
+ if (!strcmp(filename, "-")) { // write stdin to temp file
16
+ FILE *tmp = fopen(tmp_filename, "wb");
17
+ if (!tmp) {
18
+ perror(tmp_filename);
19
+ return NULL;
20
+ }
21
+ size_t sz;
22
+ char buff[4096];
23
+ while ((sz = fread(buff, 1, sizeof(buff), stdin)) > 0)
24
+ fwrite(buff, 1, sz, tmp);
25
+ fclose(tmp);
26
+ filename = tmp_filename;
27
+ }
28
+ FILE *f = fopen(filename, "rb");
29
+ if (f == NULL) {
30
+ perror(filename);
31
+ return NULL;
32
+ }
33
+
34
+ // Seek to end to find file size
35
+ if (fseek(f, 0, SEEK_END) != 0) {
36
+ perror("Error seeking in file");
37
+ fclose(f);
38
+ return NULL;
39
+ }
40
+
41
+ long file_size = ftell(f);
42
+ if (file_size == -1) {
43
+ perror("Error getting file size");
44
+ fclose(f);
45
+ return NULL;
46
+ }
47
+ rewind(f); // Go back to the start
48
+
49
+ // Allocate buffer for file content + 1 for a null terminator
50
+ char *buffer = malloc(file_size + 1);
51
+ if (buffer == NULL) {
52
+ fprintf(stderr, "Error: Could not allocate memory for file.\n");
53
+ fclose(f);
54
+ return NULL;
55
+ }
56
+
57
+ // Read the file
58
+ size_t bytes_read = fread(buffer, 1, file_size, f);
59
+ if (bytes_read != (size_t)file_size) {
60
+ fprintf(stderr, "Error reading file (read %zu, expected %ld).\n", bytes_read, file_size);
61
+ fclose(f);
62
+ free(buffer);
63
+ return NULL;
64
+ }
65
+
66
+ fclose(f);
67
+ buffer[file_size] = '\0'; // Null-terminate the string
68
+ *out_size = (size_t)file_size;
69
+ return buffer;
70
+ }
71
+
72
+ /**
73
+ * @brief Main entry point.
74
+ *
75
+ * Takes a regex pattern and a filename as command-line arguments.
76
+ */
77
+ int main(int argc, char *argv[]) {
78
+ if (argc != 3) {
79
+ fprintf(stderr, "Usage: %s <pattern> <filename, or - for stdin>\n", argv[0]);
80
+ return 1;
81
+ }
82
+
83
+ const char *pattern_string = argv[1];
84
+ const char *filename = argv[2];
85
+
86
+ // Read file into memory
87
+ size_t file_size = 0;
88
+ char *file_content = read_file_to_buffer(filename, &file_size);
89
+ if (file_content == NULL) {
90
+ return 1; // Error already printed
91
+ }
92
+
93
+ // Compile the pattern (pass 0 for default options,
94
+ // PCRE2_UTF and PCRE2_MULTILINE are added by the library)
95
+ regex_handle_t *handle = zsv_pcre2_8_new(pattern_string, 0);
96
+ if (handle == NULL) {
97
+ fprintf(stderr, "Error compiling regex pattern.\n");
98
+ free(file_content);
99
+ return 1;
100
+ }
101
+
102
+ // Check for anchors
103
+ if (zsv_pcre2_8_has_anchors(pattern_string)) {
104
+ printf("Pattern contains ^ or $ line anchors.\n");
105
+ } else {
106
+ printf("Pattern does not contain line anchors.\n");
107
+ }
108
+
109
+ // Perform the match
110
+ int result = zsv_pcre2_8_match(handle, file_content, file_size);
111
+
112
+ if (result) {
113
+ printf("Match\n");
114
+ } else {
115
+ printf("No Match\n");
116
+ }
117
+
118
+ // Clean up
119
+ zsv_pcre2_8_delete(handle);
120
+ free(file_content);
121
+
122
+ return 0;
123
+ }
@@ -0,0 +1,153 @@
1
+ #define PCRE2_CODE_UNIT_WIDTH 8
2
+ #include <pcre2.h>
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include "pcre2-8.h"
6
+
7
+ /**
8
+ * @brief Defines the internal structure of the handle.
9
+ * We only need to store the compiled code.
10
+ */
11
+ struct zsv_pcre2_handle {
12
+ pcre2_code *re;
13
+ pcre2_match_data *cached_match_data;
14
+ };
15
+
16
+ /**
17
+ * @brief Implementation of zsv_pcre2_8_new.
18
+ */
19
+ regex_handle_t *zsv_pcre2_8_new(const char *pattern, uint32_t options) {
20
+ regex_handle_t *handle = calloc(1, sizeof(regex_handle_t));
21
+ if (handle == NULL) {
22
+ perror("zsv_pcre2_8_new");
23
+ return NULL;
24
+ }
25
+
26
+ int error_number;
27
+ PCRE2_SIZE error_offset;
28
+
29
+ // utf-8 and multiline support
30
+ uint32_t compile_options = options | PCRE2_UTF | PCRE2_MULTILINE;
31
+
32
+ pcre2_compile_context *compile_context = pcre2_compile_context_create_8(NULL);
33
+ if (compile_context == NULL) {
34
+ printf("Error: Failed to create compile context.\n");
35
+ free(handle);
36
+ return NULL;
37
+ }
38
+
39
+ // set newline convention to '\0'
40
+ pcre2_set_newline_8(compile_context, PCRE2_NEWLINE_NUL);
41
+
42
+ handle->re = pcre2_compile_8((PCRE2_SPTR)pattern, // the pattern
43
+ PCRE2_ZERO_TERMINATED, // pattern is zero-terminated
44
+ compile_options, // user options + UTF + MULTILINE
45
+ &error_number, // for error number
46
+ &error_offset, // for error offset
47
+ compile_context // use our configured compile context
48
+ );
49
+
50
+ // free the compile context (no longer needed)
51
+ pcre2_compile_context_free_8(compile_context);
52
+
53
+ if (handle->re == NULL) {
54
+ PCRE2_UCHAR buffer[256];
55
+ pcre2_get_error_message_8(error_number, buffer, sizeof(buffer));
56
+ printf("PCRE2 compilation failed for pattern \"%s\" at offset %d: %s\n", pattern, (int)error_offset, buffer);
57
+ free(handle);
58
+ return NULL;
59
+ }
60
+
61
+ handle->cached_match_data = pcre2_match_data_create_from_pattern_8(handle->re, NULL);
62
+
63
+ return handle;
64
+ }
65
+
66
+ /**
67
+ * @brief Implementation of zsv_pcre2_8_match.
68
+ */
69
+ int zsv_pcre2_8_match(regex_handle_t *handle, const unsigned char *subject, size_t len) {
70
+ int rc = pcre2_match_8(handle->re, (PCRE2_SPTR)subject, len, 0, 0, handle->cached_match_data, NULL);
71
+ if (rc >= 0) // matched
72
+ return 1;
73
+ if (rc != PCRE2_ERROR_NOMATCH)
74
+ fprintf(stderr, "zsv_pcre2_8_match: match error %i\n", rc);
75
+ return 0;
76
+ }
77
+
78
+ /**
79
+ * @brief Implementation of zsv_pcre2_8_has_anchors.
80
+ */
81
+ int zsv_pcre2_8_has_anchors(const char *pattern) {
82
+ int in_char_class = 0;
83
+
84
+ if (pattern == NULL) {
85
+ return 0;
86
+ }
87
+
88
+ for (int i = 0; pattern[i] != '\0'; i++) {
89
+ // First, check for an escape character
90
+ if (pattern[i] == '\\') {
91
+ // Check how many backslashes precede this point
92
+ int backslash_count = 0;
93
+ for (int j = i - 1; j >= 0; j--) {
94
+ if (pattern[j] == '\\') {
95
+ backslash_count++;
96
+ } else {
97
+ break;
98
+ }
99
+ }
100
+ // If we are on an *escaped* backslash (e.g., "\\"),
101
+ // it doesn't escape the *next* character.
102
+ if (backslash_count % 2 == 0) {
103
+ // This backslash is NOT itself escaped, so it *will*
104
+ // escape the next character. Skip the next char.
105
+ i++;
106
+ if (pattern[i] == '\0') {
107
+ // Pattern ended with a backslash
108
+ return 0;
109
+ }
110
+ }
111
+ // If the backslash_count is odd, this backslash *is*
112
+ // escaped (e.g., "\\\^"), so it does NOT escape the
113
+ // next character. We just continue normally.
114
+ continue;
115
+ }
116
+
117
+ // We are on a non-escaped character
118
+ if (in_char_class) {
119
+ if (pattern[i] == ']') {
120
+ in_char_class = 0;
121
+ }
122
+ // Inside a char class, all chars are treated as literals
123
+ // or class operators (like -), so we ignore ^ and $
124
+ } else {
125
+ switch (pattern[i]) {
126
+ case '[':
127
+ in_char_class = 1;
128
+ break;
129
+ case '^':
130
+ case '$':
131
+ // Found an unescaped anchor *outside* a char class
132
+ return 1;
133
+ default:
134
+ // Any other character
135
+ break;
136
+ }
137
+ }
138
+ }
139
+ return 0; // No anchors found
140
+ }
141
+
142
+ /**
143
+ * @brief Implementation of zsv_pcre2_8_delete.
144
+ */
145
+ void zsv_pcre2_8_delete(regex_handle_t *handle) {
146
+ if (handle) {
147
+ if (handle->cached_match_data)
148
+ pcre2_match_data_free_8(handle->cached_match_data);
149
+ if (handle->re)
150
+ pcre2_code_free_8(handle->re);
151
+ free(handle);
152
+ }
153
+ }
@@ -0,0 +1,54 @@
1
+ #ifndef PCRE2_8_LIB_H
2
+ #define PCRE2_8_LIB_H
3
+
4
+ #include <stddef.h> // For size_t
5
+ #include <stdint.h> // For uint32_t
6
+
7
+ /**
8
+ * @brief An opaque handle for a compiled regex pattern.
9
+ */
10
+ typedef struct zsv_pcre2_handle regex_handle_t;
11
+
12
+ /**
13
+ * @brief Compiles a regex pattern into a handle for matching.
14
+ *
15
+ * This function automatically enables PCRE2_UTF, PCRE2_MULTILINE,
16
+ * and PCRE2_NEWLINE_NUL. This configures the multiline anchors (^ and $)
17
+ * to use '\0' (NULL) as the line delimiter.
18
+ *
19
+ * @param pattern The null-terminated, UTF-8 encoded regex pattern.
20
+ * @param options Additional PCRE2_COMPILE_... options to be OR'd in.
21
+ * @return A pointer to a handle, or NULL on compilation error.
22
+ */
23
+ regex_handle_t *zsv_pcre2_8_new(const char *pattern, uint32_t options);
24
+
25
+ /**
26
+ * @brief Matches a compiled regex handle against a subject string.
27
+ *
28
+ * @param handle A valid handle returned from zsv_pcre2_8_new.
29
+ * @param subject The subject string to search.
30
+ * @param subject_length The length (in bytes) of the subject string.
31
+ * @return 1 if a match is found, 0 otherwise (no match or error).
32
+ */
33
+ int zsv_pcre2_8_match(regex_handle_t *handle, const unsigned char *subject, size_t subject_length);
34
+
35
+ /**
36
+ * @brief Checks if a pattern string contains any unescaped line anchors
37
+ * (^ or $) that are *not* inside a character class.
38
+ *
39
+ * This is a robust-enough check to see if a pattern is attempting
40
+ * line-based matching.
41
+ *
42
+ * @param pattern The null-terminated, UTF-8 encoded regex pattern.
43
+ * @return 1 if a line anchor is found, 0 otherwise.
44
+ */
45
+ int zsv_pcre2_8_has_anchors(const char *pattern);
46
+
47
+ /**
48
+ * @brief Frees the resources associated with a regex handle.
49
+ *
50
+ * @param handle The handle to free.
51
+ */
52
+ void zsv_pcre2_8_delete(regex_handle_t *handle);
53
+
54
+ #endif // PCRE2_8_LIB_H
@@ -0,0 +1,267 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+ #include <limits.h>
4
+ #include <errno.h>
5
+ #include <zsv.h>
6
+ #include <zsv/utils/prop.h>
7
+ #include <zsv/utils/cache.h>
8
+ #include <zsv/utils/file.h>
9
+ #include <zsv/utils/overwrite.h>
10
+ #include <yajl_helper/yajl_helper.h>
11
+
12
+ #ifndef ZSVTLS
13
+ #ifndef NO_THREADING
14
+ #define ZSVTLS _Thread_local
15
+ #else
16
+ #define ZSVTLS
17
+ #endif
18
+ #endif
19
+ // see arg.c
20
+
21
+ static struct zsv_prop_handler *zsv_with_default_custom_prop_handler(char mode) {
22
+ ZSVTLS static char zsv_default_custom_prop_initd = 0;
23
+ ZSVTLS static struct zsv_prop_handler zsv_default_custom_prop_handler = {0};
24
+
25
+ switch (mode) {
26
+ case 'c': // clear
27
+ memset(&zsv_default_custom_prop_handler, 0, sizeof(zsv_default_custom_prop_handler));
28
+ zsv_default_custom_prop_initd = 0;
29
+ break;
30
+ case 'g': // get
31
+ if (!zsv_default_custom_prop_initd) {
32
+ zsv_default_custom_prop_initd = 1;
33
+ zsv_default_custom_prop_handler.handler = NULL;
34
+ zsv_default_custom_prop_handler.ctx = NULL;
35
+ }
36
+ break;
37
+ }
38
+ return &zsv_default_custom_prop_handler;
39
+ }
40
+
41
+ ZSV_EXPORT
42
+ void zsv_clear_default_custom_prop_handler(void) {
43
+ zsv_with_default_custom_prop_handler('c');
44
+ }
45
+
46
+ ZSV_EXPORT
47
+ struct zsv_prop_handler zsv_get_default_custom_prop_handler(void) {
48
+ return *zsv_with_default_custom_prop_handler('g');
49
+ }
50
+
51
+ ZSV_EXPORT
52
+ void zsv_set_default_custom_prop_handler(struct zsv_prop_handler custom_prop_handler) {
53
+ *zsv_with_default_custom_prop_handler(0) = custom_prop_handler;
54
+ }
55
+
56
+ // TO DO: import these through a proper header
57
+ static int zsv_properties_parse_process_value(yajl_helper_t yh, struct json_value *value);
58
+
59
+ struct zsv_properties_parser {
60
+ yajl_helper_t yh;
61
+ yajl_status stat;
62
+
63
+ // queryable data
64
+ struct zsv_file_properties *fp;
65
+ struct zsv_opts *opts;
66
+ struct zsv_prop_handler *custom_prop_handler;
67
+ const unsigned char *filepath; // path to this properties file
68
+ };
69
+
70
+ const unsigned char *zsv_properties_parser_get_filepath(void *p_) {
71
+ struct zsv_properties_parser *p = p_;
72
+ return p ? p->filepath : NULL;
73
+ }
74
+
75
+ void *zsv_properties_parser_get_custom_ctx(void *p_) {
76
+ struct zsv_properties_parser *p = p_;
77
+ return p && p->custom_prop_handler ? p->custom_prop_handler->ctx : NULL;
78
+ }
79
+
80
+ struct zsv_opts *zsv_properties_parser_get_opts(void *p_) {
81
+ struct zsv_properties_parser *p = p_;
82
+ return p ? p->opts : NULL;
83
+ }
84
+
85
+ /**
86
+ * Create a new properties parser
87
+ */
88
+ struct zsv_properties_parser *zsv_properties_parser_new(const unsigned char *path,
89
+ struct zsv_prop_handler *custom_prop_handler,
90
+ struct zsv_file_properties *fp, struct zsv_opts *opts) {
91
+ struct zsv_properties_parser *parser = calloc(1, sizeof(*parser));
92
+ if (parser) {
93
+ parser->yh = yajl_helper_new(32,
94
+ NULL, // start_map,
95
+ NULL, // end_map,
96
+ NULL, // map_key,
97
+ NULL, // start_array,
98
+ NULL, // end_array,
99
+ zsv_properties_parse_process_value, parser);
100
+ if (!parser->yh)
101
+ free(parser);
102
+ else {
103
+ parser->custom_prop_handler = custom_prop_handler;
104
+ parser->fp = fp;
105
+ parser->filepath = path;
106
+ parser->opts = opts;
107
+ parser->stat = yajl_status_ok;
108
+ return parser;
109
+ }
110
+ }
111
+ // error
112
+ return NULL;
113
+ }
114
+
115
+ /**
116
+ * Finished parsing
117
+ */
118
+ enum zsv_status zsv_properties_parse_complete(struct zsv_properties_parser *parser) {
119
+ if (parser && parser->stat == yajl_status_ok)
120
+ parser->stat = yajl_complete_parse(yajl_helper_yajl(parser->yh));
121
+ return parser && parser->stat == yajl_status_ok ? zsv_status_ok : zsv_status_error;
122
+ }
123
+
124
+ /**
125
+ * Clean up
126
+ */
127
+ enum zsv_status zsv_properties_parser_destroy(struct zsv_properties_parser *parser) {
128
+ yajl_helper_delete(parser->yh);
129
+ yajl_status stat = parser->stat;
130
+ free(parser);
131
+ return stat == yajl_status_ok ? zsv_status_ok : zsv_status_error;
132
+ }
133
+
134
+ /**
135
+ * Load cached file properties into a zsp_opts and/or zsv_file_properties struct
136
+ *
137
+ * @param data_filepath required file path
138
+ * @param opts (optional) parser options to load. will be updated to reflect
139
+ * what is actually used
140
+ * @param custom_prop_handler (optional) handler for custom properties
141
+ * @return zsv_status_ok on success
142
+ */
143
+ struct zsv_file_properties zsv_cache_load_props(const char *data_filepath, struct zsv_opts *opts,
144
+ struct zsv_prop_handler *custom_prop_handler) {
145
+ // we need some memory to save the parsed properties
146
+ // if the caller did not provide that, use our own
147
+ struct zsv_file_properties tmp = {0};
148
+ if (!(data_filepath && *data_filepath))
149
+ return tmp; // e.g. input = stdin
150
+
151
+ struct zsv_file_properties *fp = &tmp;
152
+ struct zsv_properties_parser *p = NULL;
153
+ unsigned char *fn = zsv_cache_filepath((const unsigned char *)data_filepath, zsv_cache_type_property, 0, 0);
154
+ if (!fn)
155
+ tmp.stat = zsv_status_memory;
156
+ else {
157
+ FILE *f;
158
+ int err;
159
+ if (!zsv_file_readable((char *)fn, &err, &f)) {
160
+ if (err != ENOENT) {
161
+ perror((const char *)fn);
162
+ tmp.stat = zsv_status_error;
163
+ }
164
+ } else {
165
+ p = zsv_properties_parser_new(fn, custom_prop_handler, fp, opts);
166
+ if (!p)
167
+ tmp.stat = zsv_status_memory;
168
+ else if (p->stat != yajl_status_ok)
169
+ tmp.stat = zsv_status_error;
170
+ else {
171
+ unsigned char buff[1024];
172
+ size_t bytes_read;
173
+ while ((bytes_read = fread(buff, 1, sizeof(buff), f))) {
174
+ if ((p->stat = yajl_parse(yajl_helper_yajl(p->yh), buff, bytes_read)) != yajl_status_ok) {
175
+ tmp.stat = zsv_status_error;
176
+ break;
177
+ }
178
+ }
179
+ if (tmp.stat == zsv_status_ok)
180
+ zsv_properties_parse_complete(p);
181
+ }
182
+ fclose(f);
183
+ }
184
+ free(fn);
185
+ }
186
+
187
+ if (tmp.stat == zsv_status_ok) {
188
+ // warn if the loaded properties conflict with command-line options
189
+ if (fp->skip_specified) {
190
+ if (opts && opts->option_overrides.skip_head && opts->rows_to_ignore != fp->skip)
191
+ fprintf(stderr, "Warning: file property 'skip-head' overridden by command option\n");
192
+ else if (opts)
193
+ opts->rows_to_ignore = fp->skip;
194
+ }
195
+ if (fp->header_span_specified) {
196
+ if (opts && opts->option_overrides.header_row_span && opts->header_span != fp->header_span)
197
+ fprintf(stderr, "Warning: file property 'header-row-span' overridden by command option\n");
198
+ else if (opts)
199
+ opts->header_span = fp->header_span;
200
+ }
201
+ }
202
+ if (p && tmp.stat == zsv_status_ok && zsv_properties_parser_destroy(p) != zsv_status_ok)
203
+ tmp.stat = zsv_status_error;
204
+ return tmp;
205
+ }
206
+
207
+ static int zsv_properties_parse_process_value(yajl_helper_t yh, struct json_value *value) {
208
+ struct zsv_properties_parser *parser = yajl_helper_ctx(yh);
209
+ struct zsv_file_properties *fp = parser->fp;
210
+ if (yajl_helper_level_raw(yh) == 1) {
211
+ const char *prop_name = yajl_helper_get_map_key(yh, 0);
212
+ unsigned int *target = NULL;
213
+ if (!strcmp(prop_name, "skip-head")) {
214
+ target = &fp->skip;
215
+ fp->skip_specified = 1;
216
+ } else if (!strcmp(prop_name, "header-row-span")) {
217
+ target = &fp->header_span;
218
+ fp->header_span_specified = 1;
219
+ }
220
+
221
+ if (!target) {
222
+ int rc = 1;
223
+ struct zsv_prop_handler *custom_prop_handler = parser->custom_prop_handler;
224
+ if (custom_prop_handler && custom_prop_handler->handler)
225
+ rc = custom_prop_handler->handler(parser, prop_name, value);
226
+ if (rc) {
227
+ fprintf(stderr, "Unrecognized property: %s\n", prop_name);
228
+ fp->stat = zsv_status_error;
229
+ }
230
+ } else {
231
+ int err = 0;
232
+ long long i = json_value_long(value, &err);
233
+ if (err || i < 0 || i > UINT_MAX) {
234
+ fp->stat = zsv_status_error;
235
+ fprintf(stderr, "Invalid %s property value: should be an integer between 0 and %u", prop_name, UINT_MAX);
236
+ } else
237
+ *target = (unsigned int)i;
238
+ }
239
+ }
240
+ return 1;
241
+ }
242
+
243
+ /**
244
+ * zsv_new_with_properties(): use in lieu of zsv_new() to also merge zsv options
245
+ * with any saved properties (such as rows_to_ignore or header_span) for the
246
+ * specified input file. In the event that saved properties conflict with a
247
+ * command-line option, the command-line option "wins" (the property value is
248
+ * ignored), but a warning is printed
249
+ *
250
+ * optional `struct zsv_file_properties` supports custom file property processing
251
+ */
252
+ enum zsv_status zsv_new_with_properties(struct zsv_opts *opts, struct zsv_prop_handler *custom_prop_handler,
253
+ const char *input_path, zsv_parser *handle_out) {
254
+ *handle_out = NULL;
255
+ if (input_path) {
256
+ struct zsv_file_properties fp = zsv_cache_load_props(input_path, opts, custom_prop_handler);
257
+ if (fp.stat != zsv_status_ok)
258
+ return fp.stat;
259
+ }
260
+ #ifdef ZSV_EXTRAS
261
+ if (opts->overwrite_auto)
262
+ zsv_overwrite_auto(opts, input_path);
263
+ #endif
264
+ if ((*handle_out = zsv_new(opts)))
265
+ return zsv_status_ok;
266
+ return zsv_status_memory;
267
+ }
@@ -0,0 +1,53 @@
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 <signal.h>
10
+ #include <stdio.h>
11
+ #include <string.h>
12
+
13
+ volatile sig_atomic_t zsv_signal_interrupted = 0;
14
+
15
+ #ifdef _WIN32
16
+ #include <windows.h>
17
+
18
+ static int consoleHandler(DWORD signal) {
19
+ if (signal == CTRL_C_EVENT) {
20
+ if (!zsv_signal_interrupted) {
21
+ zsv_signal_interrupted = 1;
22
+ fclose(stdin);
23
+ return 1;
24
+ }
25
+ }
26
+ return 0;
27
+ }
28
+
29
+ void zsv_handle_ctrl_c_signal(void) {
30
+ if (!SetConsoleCtrlHandler(consoleHandler, 1))
31
+ fprintf(stderr, "Warning: unable to set signal handler\n");
32
+ }
33
+
34
+ #else
35
+
36
+ // handle signal interrupts: first Ctrl-C sets interrupt
37
+ // second reverts to default Ctrl-C behavior
38
+
39
+ static void INThandler(int sig) {
40
+ signal(sig, SIG_IGN); // ignore
41
+ if (!zsv_signal_interrupted) {
42
+ zsv_signal_interrupted = 1;
43
+ signal(SIGINT, NULL); // restore default handler
44
+ }
45
+ }
46
+
47
+ void zsv_handle_ctrl_c_signal(void) {
48
+ // sigaction only ADDs the handler instead of REPLACING it
49
+ // so we will use signal() instead
50
+ signal(SIGINT, INThandler);
51
+ }
52
+
53
+ #endif