zsv 1.3.0 → 1.4.3

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 (232) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/README.md +41 -3
  4. data/ext/zsv/extconf.rb +66 -49
  5. data/ext/zsv/options.c +1 -2
  6. data/ext/zsv/parser.c +14 -0
  7. data/ext/zsv/zsv_ext.c +3 -0
  8. data/lib/zsv/version.rb +1 -1
  9. metadata +6 -226
  10. data/ext/zsv/vendor/zsv-1.3.0/app/2db.c +0 -756
  11. data/ext/zsv/vendor/zsv-1.3.0/app/2json.c +0 -381
  12. data/ext/zsv/vendor/zsv-1.3.0/app/2tsv.c +0 -228
  13. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/help.c +0 -123
  14. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/license.c +0 -39
  15. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/register.c +0 -104
  16. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/thirdparty.c +0 -41
  17. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/unregister.c +0 -1
  18. data/ext/zsv/vendor/zsv-1.3.0/app/builtin/version.c +0 -14
  19. data/ext/zsv/vendor/zsv-1.3.0/app/check/simdutf_wrapper.h +0 -19
  20. data/ext/zsv/vendor/zsv-1.3.0/app/check/utf8.c +0 -116
  21. data/ext/zsv/vendor/zsv-1.3.0/app/check.c +0 -194
  22. data/ext/zsv/vendor/zsv-1.3.0/app/cli.c +0 -796
  23. data/ext/zsv/vendor/zsv-1.3.0/app/cli_const.h +0 -41
  24. data/ext/zsv/vendor/zsv-1.3.0/app/cli_export.h +0 -16
  25. data/ext/zsv/vendor/zsv-1.3.0/app/cli_ini.c +0 -280
  26. data/ext/zsv/vendor/zsv-1.3.0/app/cli_internal.h +0 -36
  27. data/ext/zsv/vendor/zsv-1.3.0/app/compare.c +0 -913
  28. data/ext/zsv/vendor/zsv-1.3.0/app/compare.h +0 -23
  29. data/ext/zsv/vendor/zsv-1.3.0/app/compare_added_column.c +0 -20
  30. data/ext/zsv/vendor/zsv-1.3.0/app/compare_internal.h +0 -140
  31. data/ext/zsv/vendor/zsv-1.3.0/app/compare_sort.c +0 -91
  32. data/ext/zsv/vendor/zsv-1.3.0/app/compare_unique_colname.c +0 -81
  33. data/ext/zsv/vendor/zsv-1.3.0/app/count-pull.c +0 -82
  34. data/ext/zsv/vendor/zsv-1.3.0/app/count.c +0 -404
  35. data/ext/zsv/vendor/zsv-1.3.0/app/desc.c +0 -569
  36. data/ext/zsv/vendor/zsv-1.3.0/app/echo.c +0 -365
  37. data/ext/zsv/vendor/zsv-1.3.0/app/ext_example/my_extension.c +0 -366
  38. data/ext/zsv/vendor/zsv-1.3.0/app/ext_example/mysheet_extension.c +0 -341
  39. data/ext/zsv/vendor/zsv-1.3.0/app/ext_template/YOUR_EXTENSION_zsvext.c +0 -263
  40. data/ext/zsv/vendor/zsv-1.3.0/app/external/inih/ini.c +0 -298
  41. data/ext/zsv/vendor/zsv-1.3.0/app/external/inih/ini.h +0 -157
  42. data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/json_numeric.c +0 -177
  43. data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/jsonwriter.c +0 -444
  44. data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/jsonwriter.h +0 -145
  45. data/ext/zsv/vendor/zsv-1.3.0/app/external/json_writer-1.01/utils.c +0 -110
  46. data/ext/zsv/vendor/zsv-1.3.0/app/external/memfile-1.0/include/memfile.h +0 -15
  47. data/ext/zsv/vendor/zsv-1.3.0/app/external/memfile-1.0/src/memfile.c +0 -64
  48. data/ext/zsv/vendor/zsv-1.3.0/app/external/sglib/sglib.h +0 -1955
  49. data/ext/zsv/vendor/zsv-1.3.0/app/external/simdutf/simdutf.h +0 -6802
  50. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3.c +0 -230517
  51. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3.h +0 -12174
  52. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_and_csv_vtab.c +0 -2
  53. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab-mem.c +0 -142
  54. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab-mem.h +0 -49
  55. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab-zsv.c +0 -485
  56. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3_csv_vtab.c +0 -1015
  57. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/sqlite3ext.h +0 -663
  58. data/ext/zsv/vendor/zsv-1.3.0/app/external/sqlite3/vtab_helper.c +0 -85
  59. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_common.h +0 -75
  60. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_gen.h +0 -167
  61. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_parse.h +0 -228
  62. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_tree.h +0 -186
  63. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/build/yajl-2.1.1/include/yajl/yajl_version.h +0 -23
  64. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_common.h +0 -76
  65. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_gen.h +0 -167
  66. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_parse.h +0 -238
  67. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/api/yajl_tree.h +0 -186
  68. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl.c +0 -184
  69. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_alloc.c +0 -52
  70. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_alloc.h +0 -34
  71. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_buf.c +0 -103
  72. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_buf.h +0 -57
  73. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_bytestack.h +0 -69
  74. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_encode.c +0 -220
  75. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_encode.h +0 -34
  76. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_gen.c +0 -362
  77. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_lex.c +0 -764
  78. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_lex.h +0 -117
  79. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_parser.c +0 -508
  80. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_parser.h +0 -78
  81. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_tree.c +0 -505
  82. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl/src/yajl_version.c +0 -7
  83. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper/json_value.h +0 -59
  84. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper/yajl_helper.h +0 -208
  85. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper.c +0 -795
  86. data/ext/zsv/vendor/zsv-1.3.0/app/external/yajl_helper/yajl_helper_internal.h +0 -28
  87. data/ext/zsv/vendor/zsv-1.3.0/app/flatten.c +0 -851
  88. data/ext/zsv/vendor/zsv-1.3.0/app/jq.c +0 -106
  89. data/ext/zsv/vendor/zsv-1.3.0/app/jq.h +0 -6
  90. data/ext/zsv/vendor/zsv-1.3.0/app/mv.c +0 -113
  91. data/ext/zsv/vendor/zsv-1.3.0/app/noop.c +0 -90
  92. data/ext/zsv/vendor/zsv-1.3.0/app/overwrite.c +0 -295
  93. data/ext/zsv/vendor/zsv-1.3.0/app/paste.c +0 -175
  94. data/ext/zsv/vendor/zsv-1.3.0/app/pretty.c +0 -693
  95. data/ext/zsv/vendor/zsv-1.3.0/app/prop.c +0 -980
  96. data/ext/zsv/vendor/zsv-1.3.0/app/rm.c +0 -131
  97. data/ext/zsv/vendor/zsv-1.3.0/app/select/fixed.c +0 -130
  98. data/ext/zsv/vendor/zsv-1.3.0/app/select/internal.h +0 -118
  99. data/ext/zsv/vendor/zsv-1.3.0/app/select/parallel.c +0 -45
  100. data/ext/zsv/vendor/zsv-1.3.0/app/select/parallel.h +0 -41
  101. data/ext/zsv/vendor/zsv-1.3.0/app/select/processing.c +0 -107
  102. data/ext/zsv/vendor/zsv-1.3.0/app/select/rand.c +0 -20
  103. data/ext/zsv/vendor/zsv-1.3.0/app/select/regex.c +0 -61
  104. data/ext/zsv/vendor/zsv-1.3.0/app/select/search.c +0 -14
  105. data/ext/zsv/vendor/zsv-1.3.0/app/select/selection.c +0 -192
  106. data/ext/zsv/vendor/zsv-1.3.0/app/select/usage.c +0 -72
  107. data/ext/zsv/vendor/zsv-1.3.0/app/select-pull.c +0 -812
  108. data/ext/zsv/vendor/zsv-1.3.0/app/select.c +0 -753
  109. data/ext/zsv/vendor/zsv-1.3.0/app/serialize.c +0 -372
  110. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/curses.h +0 -15
  111. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/cursor.c +0 -119
  112. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/errors.c +0 -45
  113. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/file.c +0 -63
  114. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/file.h +0 -12
  115. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/filter.c +0 -166
  116. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/handlers.c +0 -214
  117. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/handlers_internal.h +0 -128
  118. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/help.c +0 -43
  119. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/index.c +0 -81
  120. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/index.h +0 -25
  121. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/key-bindings.c +0 -325
  122. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/key-bindings.h +0 -73
  123. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/lexer.c +0 -203
  124. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/newline_handler.c +0 -7
  125. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/pivot.c +0 -318
  126. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/procedure.c +0 -134
  127. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/procedure.h +0 -119
  128. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/read-data.c +0 -322
  129. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/screen_buffer.c +0 -203
  130. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/screen_buffer.h +0 -36
  131. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/sheet-sql.c +0 -167
  132. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/sheet_internal.h +0 -36
  133. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/sqlfilter.c +0 -153
  134. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/terminfo.c +0 -32
  135. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/transformation.c +0 -312
  136. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/transformation.h +0 -29
  137. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/ui_buffer.c +0 -266
  138. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/usage.c +0 -9
  139. data/ext/zsv/vendor/zsv-1.3.0/app/sheet/utf8-width.c +0 -60
  140. data/ext/zsv/vendor/zsv-1.3.0/app/sheet.c +0 -1007
  141. data/ext/zsv/vendor/zsv-1.3.0/app/sql.c +0 -453
  142. data/ext/zsv/vendor/zsv-1.3.0/app/sql_internal.c +0 -101
  143. data/ext/zsv/vendor/zsv-1.3.0/app/sql_internal.h +0 -49
  144. data/ext/zsv/vendor/zsv-1.3.0/app/stack.c +0 -393
  145. data/ext/zsv/vendor/zsv-1.3.0/app/utils/arg.c +0 -322
  146. data/ext/zsv/vendor/zsv-1.3.0/app/utils/cache.c +0 -228
  147. data/ext/zsv/vendor/zsv-1.3.0/app/utils/cat.c +0 -91
  148. data/ext/zsv/vendor/zsv-1.3.0/app/utils/chunk.c +0 -240
  149. data/ext/zsv/vendor/zsv-1.3.0/app/utils/chunk.h +0 -63
  150. data/ext/zsv/vendor/zsv-1.3.0/app/utils/clock.c +0 -57
  151. data/ext/zsv/vendor/zsv-1.3.0/app/utils/db.c +0 -148
  152. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs-no-jq.c +0 -2
  153. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs.c +0 -427
  154. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs_from_json.c +0 -253
  155. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dirs_to_json.c +0 -121
  156. data/ext/zsv/vendor/zsv-1.3.0/app/utils/dl.c +0 -20
  157. data/ext/zsv/vendor/zsv-1.3.0/app/utils/emcc/fs_api.c +0 -159
  158. data/ext/zsv/vendor/zsv-1.3.0/app/utils/err.c +0 -24
  159. data/ext/zsv/vendor/zsv-1.3.0/app/utils/file-mem.c +0 -180
  160. data/ext/zsv/vendor/zsv-1.3.0/app/utils/file.c +0 -256
  161. data/ext/zsv/vendor/zsv-1.3.0/app/utils/index.c +0 -197
  162. data/ext/zsv/vendor/zsv-1.3.0/app/utils/index.h +0 -49
  163. data/ext/zsv/vendor/zsv-1.3.0/app/utils/jq.c +0 -400
  164. data/ext/zsv/vendor/zsv-1.3.0/app/utils/json.c +0 -120
  165. data/ext/zsv/vendor/zsv-1.3.0/app/utils/mem.c +0 -18
  166. data/ext/zsv/vendor/zsv-1.3.0/app/utils/memmem.c +0 -132
  167. data/ext/zsv/vendor/zsv-1.3.0/app/utils/os.c +0 -178
  168. data/ext/zsv/vendor/zsv-1.3.0/app/utils/overwrite.c +0 -258
  169. data/ext/zsv/vendor/zsv-1.3.0/app/utils/overwrite_writer.c +0 -246
  170. data/ext/zsv/vendor/zsv-1.3.0/app/utils/pcre2-8/pcre2-8-test.c +0 -123
  171. data/ext/zsv/vendor/zsv-1.3.0/app/utils/pcre2-8/pcre2-8.c +0 -153
  172. data/ext/zsv/vendor/zsv-1.3.0/app/utils/pcre2-8/pcre2-8.h +0 -54
  173. data/ext/zsv/vendor/zsv-1.3.0/app/utils/prop.c +0 -267
  174. data/ext/zsv/vendor/zsv-1.3.0/app/utils/signal.c +0 -53
  175. data/ext/zsv/vendor/zsv-1.3.0/app/utils/string.c +0 -357
  176. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/dir_exists_longpath.c +0 -83
  177. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/dl.c +0 -33
  178. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/fopen_longpath.c +0 -184
  179. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/foreach_dirent_longpath.c +0 -292
  180. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/io.c +0 -259
  181. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/io.h +0 -13
  182. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/mkdir_longpath.c +0 -255
  183. data/ext/zsv/vendor/zsv-1.3.0/app/utils/win/remove_longpath.c +0 -96
  184. data/ext/zsv/vendor/zsv-1.3.0/app/utils/writer.c +0 -361
  185. data/ext/zsv/vendor/zsv-1.3.0/app/zsv_command.h +0 -40
  186. data/ext/zsv/vendor/zsv-1.3.0/app/zsv_command_standalone.c +0 -16
  187. data/ext/zsv/vendor/zsv-1.3.0/app/zsv_main.h +0 -44
  188. data/ext/zsv/vendor/zsv-1.3.0/examples/js/zsv_parser_api_dummy.c +0 -3
  189. data/ext/zsv/vendor/zsv-1.3.0/examples/lib/parse_by_chunk.c +0 -100
  190. data/ext/zsv/vendor/zsv-1.3.0/examples/lib/print_my_column.c +0 -143
  191. data/ext/zsv/vendor/zsv-1.3.0/examples/lib/pull.c +0 -89
  192. data/ext/zsv/vendor/zsv-1.3.0/examples/lib/simple.c +0 -123
  193. data/ext/zsv/vendor/zsv-1.3.0/fuzz/fuzz.c +0 -16
  194. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/api.h +0 -336
  195. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/common.h +0 -361
  196. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext/implementation.h +0 -62
  197. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext/implementation_private.h +0 -113
  198. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext/sheet.h +0 -73
  199. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/ext.h +0 -329
  200. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/arg.h +0 -90
  201. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/cache.h +0 -49
  202. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/clock.h +0 -36
  203. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/compiler.h +0 -58
  204. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/db.h +0 -19
  205. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/dirs.h +0 -147
  206. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/dl.h +0 -22
  207. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/emcc/fs_api.h +0 -28
  208. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/err.h +0 -22
  209. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/file-mem.h +0 -17
  210. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/file.h +0 -99
  211. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/jq.h +0 -65
  212. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/json.h +0 -19
  213. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/mem.h +0 -19
  214. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/memmem.h +0 -13
  215. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/os.h +0 -54
  216. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/overwrite.h +0 -71
  217. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/overwrite_writer.h +0 -53
  218. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/prop.h +0 -107
  219. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/signal.h +0 -18
  220. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/sql.h +0 -11
  221. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/string.h +0 -148
  222. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/utf8.h +0 -41
  223. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/win/dl.h +0 -25
  224. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/utils/writer.h +0 -101
  225. data/ext/zsv/vendor/zsv-1.3.0/include/zsv/zsv_export.h +0 -33
  226. data/ext/zsv/vendor/zsv-1.3.0/include/zsv.h +0 -20
  227. data/ext/zsv/vendor/zsv-1.3.0/src/vector_delim.c +0 -60
  228. data/ext/zsv/vendor/zsv-1.3.0/src/zsv.c +0 -484
  229. data/ext/zsv/vendor/zsv-1.3.0/src/zsv_internal.c +0 -731
  230. data/ext/zsv/vendor/zsv-1.3.0/src/zsv_scan_delim.c +0 -285
  231. data/ext/zsv/vendor/zsv-1.3.0/src/zsv_scan_fixed.c +0 -88
  232. data/ext/zsv/vendor/zsv-1.3.0/src/zsv_strencode.c +0 -51
@@ -1,123 +0,0 @@
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
- }
@@ -1,153 +0,0 @@
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
- }
@@ -1,54 +0,0 @@
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
@@ -1,267 +0,0 @@
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
- }
@@ -1,53 +0,0 @@
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