carray 2.0.1 → 3.0.1

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 (386) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +6 -25
  3. data/CHANGELOG.md +338 -0
  4. data/{NEWS.md → CHANGELOG.v1.md} +3 -0
  5. data/LICENSE +1 -1
  6. data/README.md +120 -36
  7. data/carray.gemspec +32 -30
  8. data/ext/ca_array_pool.c +91 -0
  9. data/ext/ca_axis_descriptor.h +186 -0
  10. data/ext/ca_axis_dispatch.c +924 -0
  11. data/ext/ca_axis_group.c +1244 -0
  12. data/ext/ca_bincmp_dispatch.c +76 -0
  13. data/ext/ca_bincmp_dispatch.h +85 -0
  14. data/ext/ca_binop_dispatch.c +124 -0
  15. data/ext/ca_binop_dispatch.h +152 -0
  16. data/ext/ca_categorical_iterator.c +1375 -0
  17. data/ext/ca_compare.c +94 -0
  18. data/ext/ca_compare.h +26 -0
  19. data/ext/ca_composite_dispatch.c +414 -0
  20. data/ext/ca_composite_dispatch.h +116 -0
  21. data/ext/ca_for_buffer.h +96 -0
  22. data/ext/ca_for_each_element.h +239 -0
  23. data/ext/ca_group_iter.c +304 -0
  24. data/ext/ca_iter_substrate.h +325 -0
  25. data/ext/ca_kernel_iterator.c +4367 -0
  26. data/ext/ca_kernel_iterator.h +2596 -0
  27. data/ext/ca_moncmp_dispatch.c +37 -0
  28. data/ext/ca_moncmp_dispatch.h +62 -0
  29. data/ext/ca_monop_dispatch.c +200 -0
  30. data/ext/ca_monop_dispatch.h +235 -0
  31. data/ext/ca_obj_array.c +355 -359
  32. data/ext/ca_obj_bincmp.c +839 -0
  33. data/ext/ca_obj_binop.c +948 -0
  34. data/ext/ca_obj_bitarray.c +369 -164
  35. data/ext/ca_obj_bitfield.c +294 -234
  36. data/ext/ca_obj_block.c +189 -711
  37. data/ext/ca_obj_byte_swap.c +766 -0
  38. data/ext/ca_obj_const_string.c +967 -0
  39. data/ext/ca_obj_face.c +750 -0
  40. data/ext/ca_obj_face.h +279 -0
  41. data/ext/ca_obj_fake.c +239 -100
  42. data/ext/ca_obj_farray.c +54 -441
  43. data/ext/ca_obj_field.c +82 -529
  44. data/ext/ca_obj_fixlen_string.c +308 -0
  45. data/ext/ca_obj_grid.c +866 -440
  46. data/ext/ca_obj_meld.c +1039 -0
  47. data/ext/ca_obj_moncmp.c +588 -0
  48. data/ext/ca_obj_monop.c +1123 -0
  49. data/ext/ca_obj_object.c +866 -296
  50. data/ext/ca_obj_record.c +470 -0
  51. data/ext/ca_obj_reduce.c +97 -82
  52. data/ext/ca_obj_refer.c +593 -459
  53. data/ext/ca_obj_remap.c +475 -0
  54. data/ext/ca_obj_repeat.c +92 -477
  55. data/ext/ca_obj_roll.c +624 -0
  56. data/ext/ca_obj_select.c +344 -296
  57. data/ext/ca_obj_select_axis.c +1306 -0
  58. data/ext/ca_obj_shift.c +231 -793
  59. data/ext/ca_obj_source.c +78 -0
  60. data/ext/ca_obj_stack.c +1173 -0
  61. data/ext/ca_obj_stride.c +2584 -0
  62. data/ext/ca_obj_string.c +270 -0
  63. data/ext/ca_obj_tile.c +622 -0
  64. data/ext/ca_obj_time.c +548 -0
  65. data/ext/ca_obj_timedelta.c +437 -0
  66. data/ext/ca_obj_transpose.c +62 -516
  67. data/ext/ca_obj_triop.c +785 -0
  68. data/ext/ca_obj_window.c +1202 -565
  69. data/ext/ca_op_byte_swap.c +175 -0
  70. data/ext/ca_op_cmplx64.h +123 -0
  71. data/ext/ca_op_ipower.c +316 -0
  72. data/ext/ca_op_powi.h +88 -0
  73. data/ext/ca_sort_kernels.h +132 -0
  74. data/ext/ca_sweep_engine.c +473 -0
  75. data/ext/ca_sweep_engine.h +166 -0
  76. data/ext/ca_transform_common.c +235 -0
  77. data/ext/ca_triop_dispatch.c +55 -0
  78. data/ext/ca_triop_dispatch.h +62 -0
  79. data/ext/carray.h +810 -420
  80. data/ext/carray_access.c +873 -731
  81. data/ext/carray_attribute.c +98 -329
  82. data/ext/carray_bincount.c +255 -0
  83. data/ext/carray_broadcast.c +376 -0
  84. data/ext/carray_build_flags.h +3 -0
  85. data/ext/carray_call_cfunc.c +2897 -874
  86. data/ext/carray_call_cfunc.h +313 -0
  87. data/ext/carray_cast.c +1264 -315
  88. data/ext/carray_cast_func.rb +81 -40
  89. data/ext/carray_class.c +53 -63
  90. data/ext/carray_config.h +28 -0
  91. data/ext/carray_conversion.c +350 -346
  92. data/ext/carray_copy.c +168 -270
  93. data/ext/carray_core.c +1396 -206
  94. data/ext/carray_count.c +312 -0
  95. data/ext/carray_data_type.c +43 -19
  96. data/ext/carray_element.c +585 -213
  97. data/ext/carray_factorize.c +2542 -0
  98. data/ext/carray_generate.c +230 -559
  99. data/ext/carray_histogram.c +490 -0
  100. data/ext/carray_hold.c +228 -0
  101. data/ext/carray_index_classifier.c +1021 -0
  102. data/ext/carray_index_classifier.h +27 -0
  103. data/ext/carray_internal.h +136 -0
  104. data/ext/carray_kernels_bincmp.c +4446 -0
  105. data/ext/carray_kernels_binop.c +11001 -0
  106. data/ext/carray_kernels_init.c +1131 -0
  107. data/ext/carray_kernels_map.c +3467 -0
  108. data/ext/carray_kernels_moncmp.c +2097 -0
  109. data/ext/carray_kernels_monop.c +18313 -0
  110. data/ext/carray_kernels_reduce_aggregate.c +25837 -0
  111. data/ext/carray_kernels_reduce_boolean.c +330 -0
  112. data/ext/carray_kernels_reduce_cumulative.c +14593 -0
  113. data/ext/carray_kernels_reduce_extreme.c +16948 -0
  114. data/ext/carray_kernels_reduce_variance.c +3910 -0
  115. data/ext/carray_kernels_scan.c +3693 -0
  116. data/ext/carray_kernels_search.c +32138 -0
  117. data/ext/carray_kernels_sort.c +10626 -0
  118. data/ext/carray_kernels_triop.c +1392 -0
  119. data/ext/carray_lazy.c +737 -0
  120. data/ext/carray_loop.c +88 -200
  121. data/ext/carray_mask.c +853 -158
  122. data/ext/carray_math_kernel.h +120 -0
  123. data/ext/carray_mathfunc.c +10 -241
  124. data/ext/carray_median_percentile.c +1257 -0
  125. data/ext/carray_memory_view.c +1650 -0
  126. data/ext/carray_operator.c +1525 -320
  127. data/ext/carray_order.c +664 -1394
  128. data/ext/carray_partition.c +416 -0
  129. data/ext/carray_random.c +518 -0
  130. data/ext/carray_scatter.c +357 -0
  131. data/ext/carray_slab.c +1219 -0
  132. data/ext/carray_slab.h +84 -0
  133. data/ext/carray_sort.c +829 -0
  134. data/ext/carray_sort_kernel.c +620 -0
  135. data/ext/carray_struct.c +695 -0
  136. data/ext/carray_test.c +343 -229
  137. data/ext/carray_undef.c +34 -17
  138. data/ext/carray_utils.c +175 -74
  139. data/ext/extconf.rb +234 -55
  140. data/ext/mk_call_cfunc.rb +671 -0
  141. data/ext/mkkernel.rb +9096 -0
  142. data/ext/ruby_carray.c +211 -108
  143. data/ext/version.h +4 -14
  144. data/ext/version.rb +5 -13
  145. data/lib/carray/arrow_tensor.rb +401 -0
  146. data/lib/carray/attribute.rb +166 -0
  147. data/lib/carray/autoload_carray.rb +239 -0
  148. data/lib/carray/autoload_method_extension.rb +45 -0
  149. data/lib/carray/axis_group.rb +711 -0
  150. data/lib/carray/basics.rb +481 -0
  151. data/lib/carray/bincount_nd.rb +358 -0
  152. data/lib/carray/block_iterator.rb +614 -0
  153. data/lib/carray/boolean_reduce.rb +109 -0
  154. data/lib/carray/categorical.rb +561 -0
  155. data/lib/carray/categorical_iterator.rb +1084 -0
  156. data/lib/carray/complex.rb +150 -0
  157. data/lib/carray/conditional.rb +216 -0
  158. data/lib/carray/const_string.rb +228 -0
  159. data/lib/carray/construct.rb +160 -328
  160. data/lib/carray/core_extensions.rb +297 -0
  161. data/lib/carray/data_type_extension.rb +250 -0
  162. data/lib/carray/fixlen_string.rb +95 -0
  163. data/lib/carray/frame/concat.rb +132 -0
  164. data/lib/carray/frame/convert.rb +95 -0
  165. data/lib/carray/frame/csv_parser.rb +211 -0
  166. data/lib/carray/frame/frame.rb +642 -0
  167. data/lib/carray/frame/group.rb +186 -0
  168. data/lib/carray/frame/io.rb +321 -0
  169. data/lib/carray/frame/join.rb +248 -0
  170. data/lib/carray/frame/records.rb +99 -0
  171. data/lib/carray/frame/sort.rb +113 -0
  172. data/lib/carray/frame/verbs.rb +316 -0
  173. data/lib/carray/frame.rb +16 -0
  174. data/lib/carray/fuse_source.rb +123 -0
  175. data/lib/carray/fusion.rb +218 -0
  176. data/lib/carray/histogram.rb +512 -0
  177. data/lib/carray/inspect.rb +37 -26
  178. data/lib/carray/iterator.rb +58 -349
  179. data/lib/carray/lazy.rb +941 -0
  180. data/lib/carray/mask_gap_fill.rb +200 -0
  181. data/lib/carray/math.rb +78 -342
  182. data/lib/carray/meld_reduce.rb +289 -0
  183. data/lib/carray/methods/align_addr.rb +116 -0
  184. data/lib/carray/methods/bin.rb +128 -0
  185. data/lib/carray/methods/bincount.rb +87 -0
  186. data/lib/carray/methods/bit_string.rb +92 -0
  187. data/lib/carray/methods/broadcast.rb +63 -0
  188. data/lib/carray/methods/choose.rb +39 -0
  189. data/lib/carray/methods/composition.rb +280 -0
  190. data/lib/carray/methods/gather_nd.rb +206 -0
  191. data/lib/carray/methods/index.rb +39 -0
  192. data/lib/carray/methods/insert_block.rb +99 -0
  193. data/lib/carray/methods/is_in.rb +141 -0
  194. data/lib/carray/methods/join.rb +90 -0
  195. data/lib/carray/methods/locate_addr.rb +52 -0
  196. data/lib/carray/methods/mask_duplicates.rb +41 -0
  197. data/lib/carray/methods/meshgrid.rb +90 -0
  198. data/lib/carray/methods/mode.rb +126 -0
  199. data/lib/carray/methods/nunique.rb +46 -0
  200. data/lib/carray/methods/resize.rb +56 -0
  201. data/lib/carray/methods/snap.rb +161 -0
  202. data/lib/carray/methods/string_format.rb +57 -0
  203. data/lib/carray/methods/unique.rb +47 -0
  204. data/lib/carray/methods/value_counts.rb +71 -0
  205. data/lib/carray/mkmf.rb +124 -101
  206. data/lib/carray/runtime.rb +89 -0
  207. data/lib/carray/serialize.rb +478 -167
  208. data/lib/carray/slab_iterator.rb +305 -0
  209. data/lib/carray/stack.rb +291 -0
  210. data/lib/carray/string.rb +56 -180
  211. data/lib/carray/string_operation_extension.rb +289 -0
  212. data/lib/carray/struct.rb +335 -323
  213. data/lib/carray/struct_builder.rb +697 -0
  214. data/lib/carray/table.rb +41 -2
  215. data/lib/carray/time.rb +2654 -38
  216. data/lib/carray/window_iterator.rb +927 -0
  217. data/lib/carray.rb +55 -57
  218. data/yard-stubs/ca_obj_array.rb +385 -0
  219. data/yard-stubs/ca_obj_bitarray.rb +38 -0
  220. data/yard-stubs/ca_obj_bitfield.rb +43 -0
  221. data/yard-stubs/ca_obj_block.rb +73 -0
  222. data/yard-stubs/ca_obj_byte_swap.rb +56 -0
  223. data/yard-stubs/ca_obj_fake.rb +31 -0
  224. data/yard-stubs/ca_obj_farray.rb +32 -0
  225. data/yard-stubs/ca_obj_field.rb +45 -0
  226. data/yard-stubs/ca_obj_grid.rb +35 -0
  227. data/yard-stubs/ca_obj_refer.rb +72 -0
  228. data/yard-stubs/ca_obj_roll.rb +45 -0
  229. data/yard-stubs/ca_obj_shift.rb +43 -0
  230. data/yard-stubs/ca_obj_stride.rb +181 -0
  231. data/yard-stubs/ca_obj_tile.rb +29 -0
  232. data/yard-stubs/ca_obj_transpose.rb +40 -0
  233. data/yard-stubs/ca_obj_window.rb +49 -0
  234. data/yard-stubs/carray_access.rb +131 -0
  235. data/yard-stubs/carray_attribute.rb +246 -0
  236. data/yard-stubs/carray_broadcast.rb +37 -0
  237. data/yard-stubs/carray_cast.rb +489 -0
  238. data/yard-stubs/carray_class.rb +65 -0
  239. data/yard-stubs/carray_conversion.rb +76 -0
  240. data/yard-stubs/carray_copy.rb +79 -0
  241. data/yard-stubs/carray_core.rb +114 -0
  242. data/yard-stubs/carray_count.rb +79 -0
  243. data/yard-stubs/carray_element.rb +108 -0
  244. data/yard-stubs/carray_generate.rb +66 -0
  245. data/yard-stubs/carray_lazy.rb +23 -0
  246. data/yard-stubs/carray_loop.rb +140 -0
  247. data/yard-stubs/carray_mask.rb +259 -0
  248. data/yard-stubs/carray_math.rb +132 -0
  249. data/yard-stubs/carray_mathfunc.rb +45 -0
  250. data/yard-stubs/carray_median_percentile.rb +89 -0
  251. data/yard-stubs/carray_memory_view.rb +163 -0
  252. data/yard-stubs/carray_order.rb +312 -0
  253. data/yard-stubs/carray_random.rb +89 -0
  254. data/yard-stubs/carray_scatter.rb +106 -0
  255. data/yard-stubs/carray_slab.rb +57 -0
  256. data/yard-stubs/carray_sort.rb +163 -0
  257. data/yard-stubs/carray_test.rb +85 -0
  258. data/yard-stubs/carray_undef.rb +64 -0
  259. data/yard-stubs/carray_utils.rb +97 -0
  260. data/yard-stubs/ruby_carray.rb +193 -0
  261. metadata +220 -138
  262. data/Rakefile +0 -51
  263. data/TODO.md +0 -18
  264. data/ext/ca_iter_block.c +0 -257
  265. data/ext/ca_iter_dimension.c +0 -299
  266. data/ext/ca_iter_window.c +0 -214
  267. data/ext/ca_obj_mapping.c +0 -644
  268. data/ext/ca_obj_unbound_repeat.c +0 -529
  269. data/ext/carray_iterator.c +0 -641
  270. data/ext/carray_math.rb +0 -850
  271. data/ext/carray_numeric.c +0 -259
  272. data/ext/carray_sort_addr.c +0 -254
  273. data/ext/carray_stat.c +0 -2100
  274. data/ext/carray_stat_proc.rb +0 -1999
  275. data/ext/mkmath.rb +0 -741
  276. data/ext/ruby_ccomplex.c +0 -509
  277. data/ext/ruby_float_func.c +0 -86
  278. data/lib/carray/array.rb +0 -8
  279. data/lib/carray/autoload/autoload_base.rb +0 -19
  280. data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
  281. data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
  282. data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
  283. data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
  284. data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
  285. data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
  286. data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
  287. data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
  288. data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
  289. data/lib/carray/autoload/autoload_gem_random.rb +0 -8
  290. data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
  291. data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
  292. data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
  293. data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
  294. data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
  295. data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
  296. data/lib/carray/autoload/autoload_object_link.rb +0 -1
  297. data/lib/carray/autoload/autoload_object_pack.rb +0 -2
  298. data/lib/carray/autoload.rb +0 -141
  299. data/lib/carray/basic.rb +0 -191
  300. data/lib/carray/broadcast.rb +0 -101
  301. data/lib/carray/compose.rb +0 -315
  302. data/lib/carray/convert.rb +0 -115
  303. data/lib/carray/info.rb +0 -110
  304. data/lib/carray/io/imagemagick.rb +0 -235
  305. data/lib/carray/mask.rb +0 -102
  306. data/lib/carray/math/histogram.rb +0 -177
  307. data/lib/carray/math/recurrence.rb +0 -93
  308. data/lib/carray/object/ca_obj_iterator.rb +0 -50
  309. data/lib/carray/object/ca_obj_link.rb +0 -50
  310. data/lib/carray/object/ca_obj_pack.rb +0 -99
  311. data/lib/carray/obsolete.rb +0 -256
  312. data/lib/carray/ordering.rb +0 -181
  313. data/lib/carray/testing.rb +0 -51
  314. data/lib/carray/transform.rb +0 -109
  315. data/mailmap +0 -1
  316. data/misc/Methods.ja.md +0 -182
  317. data/misc/NOTE +0 -51
  318. data/spec/Classes/CABitfield_spec.rb +0 -58
  319. data/spec/Classes/CABlockIterator_spec.rb +0 -114
  320. data/spec/Classes/CABlock_spec.rb +0 -205
  321. data/spec/Classes/CAField_spec.rb +0 -39
  322. data/spec/Classes/CAGrid_spec.rb +0 -75
  323. data/spec/Classes/CAMap_spec.rb +0 -0
  324. data/spec/Classes/CAMapping_spec.rb +0 -105
  325. data/spec/Classes/CAObject_attribute_spec.rb +0 -33
  326. data/spec/Classes/CAObject_spec.rb +0 -33
  327. data/spec/Classes/CARefer_spec.rb +0 -93
  328. data/spec/Classes/CARepeat_spec.rb +0 -65
  329. data/spec/Classes/CASelect_spec.rb +0 -22
  330. data/spec/Classes/CAShift_spec.rb +0 -16
  331. data/spec/Classes/CAStruct_spec.rb +0 -71
  332. data/spec/Classes/CATranspose_spec.rb +0 -60
  333. data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
  334. data/spec/Classes/CAWindow_spec.rb +0 -54
  335. data/spec/Classes/CAWrap_spec.rb +0 -8
  336. data/spec/Classes/CArray_spec.rb +0 -184
  337. data/spec/Classes/CScalar_spec.rb +0 -55
  338. data/spec/Features/feature_130_spec.rb +0 -19
  339. data/spec/Features/feature_attributes_spec.rb +0 -280
  340. data/spec/Features/feature_boolean_spec.rb +0 -98
  341. data/spec/Features/feature_broadcast.rb +0 -116
  342. data/spec/Features/feature_cast_function.rb +0 -19
  343. data/spec/Features/feature_cast_spec.rb +0 -33
  344. data/spec/Features/feature_class_spec.rb +0 -84
  345. data/spec/Features/feature_complex_spec.rb +0 -42
  346. data/spec/Features/feature_composite_spec.rb +0 -124
  347. data/spec/Features/feature_convert_spec.rb +0 -46
  348. data/spec/Features/feature_copy_spec.rb +0 -123
  349. data/spec/Features/feature_creation_spec.rb +0 -84
  350. data/spec/Features/feature_element_spec.rb +0 -144
  351. data/spec/Features/feature_extream_spec.rb +0 -54
  352. data/spec/Features/feature_generate_spec.rb +0 -74
  353. data/spec/Features/feature_index_spec.rb +0 -69
  354. data/spec/Features/feature_mask_spec.rb +0 -580
  355. data/spec/Features/feature_math_spec.rb +0 -97
  356. data/spec/Features/feature_order_spec.rb +0 -146
  357. data/spec/Features/feature_ref_store_spec.rb +0 -209
  358. data/spec/Features/feature_serialization_spec.rb +0 -125
  359. data/spec/Features/feature_stat_spec.rb +0 -397
  360. data/spec/Features/feature_virtual_spec.rb +0 -48
  361. data/spec/Features/method_eq_spec.rb +0 -81
  362. data/spec/Features/method_is_nan_spec.rb +0 -12
  363. data/spec/Features/method_map_spec.rb +0 -54
  364. data/spec/Features/method_max_with.rb +0 -20
  365. data/spec/Features/method_min_with.rb +0 -19
  366. data/spec/Features/method_ne_spec.rb +0 -18
  367. data/spec/Features/method_project_spec.rb +0 -188
  368. data/spec/Features/method_ref_spec.rb +0 -27
  369. data/spec/Features/method_round_spec.rb +0 -11
  370. data/spec/Features/method_s_linspace_spec.rb +0 -48
  371. data/spec/Features/method_s_span_spec.rb +0 -14
  372. data/spec/Features/method_seq_spec.rb +0 -47
  373. data/spec/Features/method_sort_with.rb +0 -43
  374. data/spec/Features/method_sorted_with.rb +0 -29
  375. data/spec/Features/method_span_spec.rb +0 -42
  376. data/spec/Features/method_wrap_readonly_spec.rb +0 -43
  377. data/spec/UnitTest/test_CAVirtual.rb +0 -214
  378. data/spec/spec_all.rb +0 -10
  379. data/utils/ca_ase.rb +0 -21
  380. data/utils/ca_methods.rb +0 -15
  381. data/utils/cast_checker.rb +0 -30
  382. data/utils/convert_test.rb +0 -73
  383. data/utils/extract_yard.rb +0 -22
  384. data/utils/guess_shape.rb +0 -76
  385. data/utils/monkey_patch_methods.rb +0 -62
  386. data/utils/remove_resource_fork.sh +0 -5
data/lib/carray/string.rb CHANGED
@@ -1,193 +1,69 @@
1
1
  # ----------------------------------------------------------------------------
2
2
  #
3
- # carray/string.rb
3
+ # CAString high-level construction surface.
4
4
  #
5
- # This file is part of Ruby/CArray extension library.
6
- #
7
- # Copyright (C) 2005-2025 Hiroki Motoyoshi
5
+ # CAString itself (the identity Face over CA_OBJECT storage) lives in
6
+ # ext/ca_obj_string.c. This file provides the ergonomic builder that packs
7
+ # Ruby Strings into a CA_OBJECT entity and wraps it via CAString.wrap.
8
8
  #
9
9
  # ----------------------------------------------------------------------------
10
10
 
11
- require "date"
12
-
13
11
  class CArray
14
12
 
15
- def self.format (fmt, *argv)
16
- raise "no parameters given" if argv.empty?
17
- return argv.shift.zip(*argv).map { |params| Kernel::format(fmt, *params) }.to_ca
18
- end
19
-
20
- def str_len ()
21
- return convert(:int, &:length)
22
- end
23
-
24
- def str_size ()
25
- return convert(:int, &:size)
26
- end
27
-
28
- def str_bytesize ()
29
- return convert(:int, &:bytesize)
30
- end
31
-
32
- def str_gsub (*args, &block)
33
- return convert() {|s| s.gsub(*args, &block) }
34
- end
35
-
36
- def str_sub (*args, &block)
37
- return convert() {|s| s.sub(*args, &block) }
38
- end
39
-
40
- def str_encode (*args)
41
- return convert() {|s| s.encode(*args) }
42
- end
43
-
44
- def str_force_encoding (encoding)
45
- return convert() {|s| s.force_encoding(encoding) }
46
- end
47
-
48
- def str_encoding ()
49
- return convert(&:encoding)
50
- end
51
-
52
- def str_is_end_with (*args)
53
- return test {|s| s.end_with?(*args) }
54
- end
55
-
56
- def str_is_start_with (*args)
57
- return test {|s| s.start_with?(*args) }
58
- end
59
-
60
- def str_includes (substr)
61
- return test {|s| s.include?(substr) }
62
- end
63
-
64
- alias str_contains str_includes
65
-
66
- def str_index (*args)
67
- return convert(:int) {|s| s.index(*args) }
68
- end
69
-
70
- def str_rindex (*args)
71
- return convert(:int) {|s| s.rindex(*args) }
72
- end
73
-
74
- def str_intern ()
75
- return convert(&:intern)
76
- end
77
-
78
- def str_scrub ()
79
- return convert(&:scrub)
80
- end
81
-
82
- def str_downcase ()
83
- return convert(&:downcase)
84
- end
85
-
86
- def str_upcase ()
87
- return convert(&:upcase)
88
- end
89
-
90
- def str_capitalize ()
91
- return convert(&:capitalize)
92
- end
93
-
94
- def str_swapcase ()
95
- return convert(&:swapcase)
96
- end
97
-
98
- def str_chomp (*args)
99
- return convert() {|s| s.chomp(*args) }
100
- end
101
-
102
- def str_chop ()
103
- return convert(&:chop)
104
- end
105
-
106
- def str_chr ()
107
- return convert(&:chr)
108
- end
109
-
110
- def str_clear ()
111
- return convert(&:clear)
112
- end
113
-
114
- def str_count (*args)
115
- return convert(:int) {|s| s.count(*args) }
116
- end
117
-
118
- def str_delete (*args)
119
- return convert() {|s| s.delete(*args) }
120
- end
121
-
122
- def str_delete_prefix (prefix)
123
- return convert() {|s| s.delete_prefix(prefix) }
124
- end
125
-
126
- def str_delete_suffix (suffix)
127
- return convert() {|s| s.delete_suffix(suffix) }
128
- end
129
-
130
- def str_dump ()
131
- return convert(&:dump)
132
- end
133
-
134
- def str_center (*args)
135
- return convert() {|s| s.center(*args) }
136
- end
137
-
138
- def str_ljust (*args)
139
- return convert() {|s| s.ljust(*args) }
140
- end
141
-
142
- def str_rjust (*args)
143
- return convert() {|s| s.rjust(*args) }
144
- end
145
-
146
- def str_to_i ()
147
- return convert(&:to_i)
148
- end
149
-
150
- def str_to_f ()
151
- return convert(&:to_f)
152
- end
153
-
154
- def str_to_r ()
155
- return convert(&:to_r)
156
- end
157
-
158
- def str_strip ()
159
- return convert(&:strip)
160
- end
161
-
162
- def str_rstrip ()
163
- return convert(&:rstrip)
164
- end
165
-
166
- def str_lstrip ()
167
- return convert(&:lstrip)
168
- end
169
-
170
- def str_is_empty ()
171
- return test(&:empty?)
172
- end
173
-
174
- def str_matches (*args)
175
- if args.size == 1 && args.first.is_a?(Regexp)
176
- regexp = args.first
177
- return test {|v| v =~ regexp }
178
- else
179
- mask = template(:boolean) { false }
180
- args.each do |str|
181
- addr = search(str)
182
- mask[addr] = true if addr
13
+ # Build a CAString (mutable String array over object storage) from Ruby data.
14
+ #
15
+ # CArray.string(["alpha", "", "gamma"]) # 1-D from Array
16
+ # CArray.string(3) { |i| "item#{i}" } # block form
17
+ # CArray.string([a, nil, b]) # nil → masked element
18
+ # CArray.string(other_ca) # from a String Face / object / raw fixlen
19
+ #
20
+ # `nil` entries become masked cells; "" (empty) is a valid distinct value.
21
+ # A CArray source is normalised through a String Face ({CArray.string_face_of}):
22
+ # a String Face converts, CA_OBJECT storage wraps, a raw CA_FIXLEN reads as
23
+ # NUL-stripped strings; a numeric / boolean array is rejected (stringify with
24
+ # {#format} / {CArray.format}).
25
+ # @overload string(values)
26
+ # Returns a {CAString} wrapping a CA_OBJECT entity of the given values.
27
+ # @param values [Array<String, nil>] source values.
28
+ # @return [CAString]
29
+ # @overload string(ca)
30
+ # Returns a {CAString} of the string-bearing CArray `ca`.
31
+ # @param ca [CArray] a String Face, CA_OBJECT, or raw CA_FIXLEN array.
32
+ # @return [CAString]
33
+ # @raise [CArray::DataTypeError] if `ca` is numeric / boolean.
34
+ # @overload string(n) { |i| ... }
35
+ # Returns an `n`-element {CAString} filled by the block, following the
36
+ # arity-0 broadcast convention.
37
+ # @param n [Integer] element count.
38
+ # @yieldparam i [Integer] cell index.
39
+ # @yieldreturn [String, nil] value for cell `i`.
40
+ # @return [CAString]
41
+ def self.string (arg, &block)
42
+ return string_face_of(arg).to_string if arg.is_a?(CArray)
43
+
44
+ if block
45
+ n = Integer(arg)
46
+ if block.arity == 0
47
+ v = block.call
48
+ values = Array.new(n) { v }
49
+ else
50
+ values = Array.new(n) { |i| block.call(i) }
183
51
  end
184
- return mask
52
+ else
53
+ values = arg.to_a
185
54
  end
55
+
56
+ entity = CArray.object(values.size)
57
+ values.each_with_index do |s, i|
58
+ entity[i] = s.nil? ? UNDEF : s
59
+ end
60
+ CAString.wrap(entity)
186
61
  end
187
-
188
- def str_extract (regexp, replace = '\0')
189
- return convert {|s| regexp.match(s) {|m| m[0].sub(regexp, replace) } || "" }
190
- end
191
-
62
+
192
63
  end
193
64
 
65
+ # Mutable object-backed String Face: L1 ops + in-place variants.
66
+ class CAString
67
+ include CArray::StringOperationMixin
68
+ include CArray::StringOperationMixin::Mutable
69
+ end
@@ -0,0 +1,289 @@
1
+ # Shared String-operation surface for the String Faces: the
2
+ # CArray::StringOperationMixin (included by CAString / CAFixlenString /
3
+ # CAConstString).
4
+
5
+ class CArray
6
+
7
+ # String-array operations, mixed into the String Faces (CAConstString /
8
+ # CAFixlenString / CAString) — not into CArray itself, so numeric arrays
9
+ # carry no string methods.
10
+ #
11
+ # Dispatch tiers:
12
+ # L1 (here) generic per-cell implementation. Reads each cell through the
13
+ # Face's scalar fetch (so CAConstString / CAFixlenString / CAString
14
+ # all yield a proper Ruby String), applies the operation, and
15
+ # builds a shape+mask-preserving output.
16
+ # L3 a Face may override any method with a byte-level C-native
17
+ # version (CAConstString already does for the byte predicates /
18
+ # search / comparison). Ruby method resolution puts the Face's
19
+ # own method ahead of this module, so an override simply wins;
20
+ # anything not overridden falls back to L1.
21
+ #
22
+ # Output by return category (Option alpha):
23
+ # String result -> CAString (mutable object-backed String array). Chain
24
+ # #to_const_string / #to_fixlen_string to re-compact.
25
+ # Integer result -> :int CArray
26
+ # Boolean result -> :boolean CArray
27
+ module StringOperationMixin
28
+
29
+ # Per-cell map through the Face's scalar fetch. A nil `data_type` returns a
30
+ # CAString (string results); an explicit one returns a plain typed array
31
+ # (integer / boolean results). Shape and mask are carried.
32
+ def string_map (data_type = nil) # :nodoc:
33
+ out = data_type ? template(data_type) : CArray.object(*shape)
34
+ if has_mask?
35
+ m = is_masked
36
+ elements.times { |i| out[i] = (m[i] ? UNDEF : yield(self[i])) }
37
+ else
38
+ elements.times { |i| out[i] = yield(self[i]) }
39
+ end
40
+ data_type ? out : CAString.wrap(out)
41
+ end
42
+ private :string_map
43
+
44
+ # ---- transforms (String result -> CAString) --------------------------
45
+
46
+ # Per-cell `String#upcase`.
47
+ # @return [CAString] shape and mask of `self` preserved.
48
+ def upcase () ; string_map { |s| s.upcase } ; end
49
+ # Per-cell `String#downcase`.
50
+ # @return [CAString] shape and mask of `self` preserved.
51
+ def downcase () ; string_map { |s| s.downcase } ; end
52
+ # Per-cell `String#capitalize`.
53
+ # @return [CAString] shape and mask of `self` preserved.
54
+ def capitalize () ; string_map { |s| s.capitalize } ; end
55
+ # Per-cell `String#swapcase`.
56
+ # @return [CAString] shape and mask of `self` preserved.
57
+ def swapcase () ; string_map { |s| s.swapcase } ; end
58
+ # Per-cell `String#strip`.
59
+ # @return [CAString] shape and mask of `self` preserved.
60
+ def strip () ; string_map { |s| s.strip } ; end
61
+ # Per-cell `String#lstrip`.
62
+ # @return [CAString] shape and mask of `self` preserved.
63
+ def lstrip () ; string_map { |s| s.lstrip } ; end
64
+ # Per-cell `String#rstrip`.
65
+ # @return [CAString] shape and mask of `self` preserved.
66
+ def rstrip () ; string_map { |s| s.rstrip } ; end
67
+ # Per-cell `String#chomp`.
68
+ # @return [CAString] shape and mask of `self` preserved.
69
+ def chomp (*a) ; string_map { |s| s.chomp(*a) } ; end
70
+ # Per-cell `String#gsub`.
71
+ # @return [CAString] shape and mask of `self` preserved.
72
+ def gsub (*a, &b) ; string_map { |s| s.gsub(*a, &b) } ; end
73
+ # Per-cell `String#delete_prefix`.
74
+ # @return [CAString] shape and mask of `self` preserved.
75
+ def delete_prefix (p) ; string_map { |s| s.delete_prefix(p) } ; end
76
+ # Per-cell `String#delete_suffix`.
77
+ # @return [CAString] shape and mask of `self` preserved.
78
+ def delete_suffix (p) ; string_map { |s| s.delete_suffix(p) } ; end
79
+ # Per-cell `String#center`.
80
+ # @return [CAString] shape and mask of `self` preserved.
81
+ def center (*a) ; string_map { |s| s.center(*a) } ; end
82
+ # Per-cell `String#ljust`.
83
+ # @return [CAString] shape and mask of `self` preserved.
84
+ def ljust (*a) ; string_map { |s| s.ljust(*a) } ; end
85
+ # Per-cell `String#rjust`.
86
+ # @return [CAString] shape and mask of `self` preserved.
87
+ def rjust (*a) ; string_map { |s| s.rjust(*a) } ; end
88
+ # Per-cell `String#encode`.
89
+ # @return [CAString] shape and mask of `self` preserved.
90
+ def encode (*a) ; string_map { |s| s.encode(*a) } ; end
91
+ # Per-cell `String#force_encoding`.
92
+ # @return [CAString] shape and mask of `self` preserved.
93
+ def force_encoding (e) ; string_map { |s| s.force_encoding(e) } ; end
94
+ # Per-cell `String#scrub`.
95
+ # @return [CAString] shape and mask of `self` preserved.
96
+ def scrub () ; string_map { |s| s.scrub } ; end
97
+
98
+ # ---- predicates (Boolean result -> :boolean) -------------------------
99
+ # start_with? / end_with? / include? are byte-level and free of collisions
100
+ # with CArray; CAConstString overrides them with C-native versions (L3).
101
+
102
+ # Per-cell `String#start_with?`.
103
+ # @return [CArray] boolean, shape and mask of `self` preserved.
104
+ def start_with? (*a) ; string_map(:boolean) { |s| s.start_with?(*a) } ; end
105
+ # Per-cell `String#end_with?`.
106
+ # @return [CArray] boolean, shape and mask of `self` preserved.
107
+ def end_with? (*a) ; string_map(:boolean) { |s| s.end_with?(*a) } ; end
108
+ # Per-cell `String#include?`.
109
+ # @return [CArray] boolean, shape and mask of `self` preserved.
110
+ def include? (sub) ; string_map(:boolean) { |s| s.include?(sub) } ; end
111
+ # Per-cell `String#match?`.
112
+ # @return [CArray] boolean, shape and mask of `self` preserved.
113
+ def match? (re) ; string_map(:boolean) { |s| s.match?(re) } ; end
114
+
115
+ # ---- length / position (Integer result -> :int) ----------------------
116
+ # `str_len` keeps the prefix because bare #length / #size mean element
117
+ # count on a CArray; `str_index` because bare #index is an array method.
118
+ # `bytesize` / `rindex` have no array-level collision, so they stay bare.
119
+
120
+ # Per-cell `String#length`.
121
+ # @return [CArray] `:int`, shape and mask of `self` preserved.
122
+ def str_len () ; string_map(:int) { |s| s.length } ; end
123
+ # Per-cell `String#bytesize`.
124
+ # @return [CArray] `:int`, shape and mask of `self` preserved.
125
+ def bytesize () ; string_map(:int) { |s| s.bytesize } ; end
126
+ # Per-cell `String#index`.
127
+ # @return [CArray] `:int`, shape and mask of `self` preserved.
128
+ def str_index (*a) ; string_map(:int) { |s| s.index(*a) } ; end
129
+ # Per-cell `String#rindex`.
130
+ # @return [CArray] `:int`, shape and mask of `self` preserved.
131
+ def rindex (*a) ; string_map(:int) { |s| s.rindex(*a) } ; end
132
+
133
+ # ---- numeric parse (Integer / Float result) --------------------------
134
+
135
+ # Per-cell `String#to_i`.
136
+ # @return [CArray] `:int`, shape and mask of `self` preserved.
137
+ def to_i () ; string_map(:int) { |s| s.to_i } ; end
138
+ # Per-cell `String#to_f`.
139
+ # @return [CArray] `float64`, shape and mask of `self` preserved.
140
+ def to_f () ; string_map(:float64) { |s| s.to_f } ; end
141
+
142
+ # ---- membership ------------------------------------------------------
143
+
144
+ # @overload in?(*strings)
145
+ # Returns a boolean CArray marking every cell whose value equals one of
146
+ # `strings` (set membership). The string counterpart of `#match?` for
147
+ # regexps: both mark all matching cells.
148
+ # @param strings [Array<String>]
149
+ # @return [CArray]
150
+ def in? (*strings)
151
+ string_map(:boolean) { |s| strings.include?(s) }
152
+ end
153
+
154
+ # @overload extract(regexp, replace = '\0')
155
+ # Returns a CArray whose cells are each cell's first match of `regexp`
156
+ # transformed by `String#sub(regexp, replace)`; non-matching cells
157
+ # become `""`.
158
+ # @param regexp [Regexp]
159
+ # @param replace [String]
160
+ # @return [CAString]
161
+ def extract (regexp, replace = '\0')
162
+ string_map { |s| regexp.match(s) { |m| m[0].sub(regexp, replace) } || "" }
163
+ end
164
+
165
+ # --- inter-Face conversions (String Faces only) ----------------------
166
+ # These live on the mixin, not on CArray, so numeric arrays carry no
167
+ # string conversion (the same reason the string operations above are
168
+ # Face-only). Non-Face sources reach a Face through the CArray.string /
169
+ # fixlen_string / const_string builders. Each follows the to_ca
170
+ # principle: self (zero-copy) when self is already the target Face
171
+ # (compatibly), else materialise the string surface (shape + mask carried).
172
+
173
+ # @return [CAString]
174
+ def to_string
175
+ return self if is_a?(CAString)
176
+ entity = CArray.object(*shape)
177
+ if has_mask?
178
+ m = is_masked
179
+ elements.times { |i| entity[i] = (m[i] ? UNDEF : self[i]) }
180
+ else
181
+ elements.times { |i| entity[i] = self[i] }
182
+ end
183
+ CAString.wrap(entity)
184
+ end
185
+
186
+ # @param bytes [Integer, nil] slot width; defaults to the max bytesize.
187
+ # @param truncate [Symbol] :error or :silent (see {CArray.fixlen_string}).
188
+ # @return [CAFixlenString]
189
+ def to_fixlen_string (bytes: nil, truncate: :error)
190
+ unless [:error, :silent].include?(truncate)
191
+ raise ArgumentError, "truncate: must be :error or :silent (got #{truncate.inspect})"
192
+ end
193
+ return self if is_a?(CAFixlenString) && (bytes.nil? || bytes == self.bytes)
194
+
195
+ if has_mask?
196
+ m = is_masked
197
+ values = Array.new(elements) { |i| m[i] ? nil : self[i].to_s }
198
+ else
199
+ values = Array.new(elements) { |i| self[i].to_s }
200
+ end
201
+ width = bytes || values.compact.map(&:bytesize).max || 1
202
+ width = 1 if width < 1
203
+ if truncate == :error
204
+ values.each_with_index do |s, i|
205
+ next if s.nil?
206
+ if s.bytesize > width
207
+ raise ArgumentError,
208
+ "to_fixlen_string: value at #{i} is #{s.bytesize} bytes, exceeds slot width #{width} " \
209
+ "(use truncate: :silent to keep the leading bytes)"
210
+ end
211
+ end
212
+ end
213
+ entity = CArray.new(CA_FIXLEN, shape, :bytes => width)
214
+ values.each_with_index { |s, i| entity[i] = s.nil? ? UNDEF : s }
215
+ CAFixlenString.wrap(entity)
216
+ end
217
+
218
+ # Self (zero-copy) when already a {CAConstString} of the same encoding;
219
+ # otherwise materialises a compact column.
220
+ # @param encoding [Encoding] column encoding.
221
+ # @return [CAConstString]
222
+ def to_const_string (encoding: Encoding::UTF_8)
223
+ if is_a?(CAConstString) && encoding == self.encoding
224
+ return self
225
+ end
226
+ if has_mask?
227
+ m = is_masked
228
+ values = Array.new(elements) { |i| m[i] ? nil : self[i] }
229
+ else
230
+ values = Array.new(elements) { |i| self[i] }
231
+ end
232
+ CArray.const_string(values, encoding: encoding)
233
+ end
234
+
235
+ # In-place transforms, mixed into the mutable Faces only (CAString /
236
+ # CAFixlenString); CAConstString is read-only and does not include it.
237
+ module Mutable
238
+ # Writes per-cell `String#upcase` back into `self`.
239
+ # @return [CAString] the computed values that were written.
240
+ def upcase! () ; self[] = upcase ; end
241
+ # Writes per-cell `String#downcase` back into `self`.
242
+ # @return [CAString] the computed values that were written.
243
+ def downcase! () ; self[] = downcase ; end
244
+ # Writes per-cell `String#capitalize` back into `self`.
245
+ # @return [CAString] the computed values that were written.
246
+ def capitalize! () ; self[] = capitalize ; end
247
+ # Writes per-cell `String#swapcase` back into `self`.
248
+ # @return [CAString] the computed values that were written.
249
+ def swapcase! () ; self[] = swapcase ; end
250
+ # Writes per-cell `String#strip` back into `self`.
251
+ # @return [CAString] the computed values that were written.
252
+ def strip! () ; self[] = strip ; end
253
+ # Writes per-cell `String#lstrip` back into `self`.
254
+ # @return [CAString] the computed values that were written.
255
+ def lstrip! () ; self[] = lstrip ; end
256
+ # Writes per-cell `String#rstrip` back into `self`.
257
+ # @return [CAString] the computed values that were written.
258
+ def rstrip! () ; self[] = rstrip ; end
259
+ # Writes per-cell `String#chomp` back into `self`.
260
+ # @return [CAString] the computed values that were written.
261
+ def chomp! (*a) ; self[] = chomp(*a) ; end
262
+ # Writes per-cell `String#gsub` back into `self`.
263
+ # @return [CAString] the computed values that were written.
264
+ def gsub! (*a, &b) ; self[] = gsub(*a, &b) ; end
265
+ end
266
+
267
+ end
268
+
269
+ # Normalise a string-bearing CArray to a String Face, for the string
270
+ # builders. A String Face passes through; CA_OBJECT storage wraps as a
271
+ # CAString (its cells are the Ruby Strings); a raw CA_FIXLEN array wraps as a
272
+ # CAFixlenString, so its cells read as NUL-stripped strings. A numeric /
273
+ # boolean array has no string reading and is rejected -- stringify explicitly
274
+ # with #format / CArray.format. (This mirrors the numeric gate that rejects
275
+ # numeric reductions on a String Face.)
276
+ def self.string_face_of (ca)
277
+ return ca if ca.is_a?(CArray::StringOperationMixin)
278
+ case ca.data_type
279
+ when :object then CAString.wrap(ca)
280
+ when :fixlen then CAFixlenString.wrap(ca)
281
+ else
282
+ raise CArray::DataTypeError,
283
+ "cannot build a string column from a #{ca.data_type} array " \
284
+ "(use #format or CArray.format to stringify numbers)"
285
+ end
286
+ end
287
+ private_class_method :string_face_of
288
+
289
+ end