carray 2.0.0 → 3.0.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 (339) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +5 -25
  3. data/CHANGELOG.md +16 -0
  4. data/LICENSE +1 -1
  5. data/NEWS.md +3 -0
  6. data/README.md +128 -44
  7. data/carray.gemspec +22 -24
  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 +1208 -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 +125 -0
  15. data/ext/ca_binop_dispatch.h +159 -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 +241 -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 +4321 -0
  26. data/ext/ca_kernel_iterator.h +2603 -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 +809 -0
  33. data/ext/ca_obj_binop.c +892 -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 +965 -0
  39. data/ext/ca_obj_face.c +670 -0
  40. data/ext/ca_obj_face.h +247 -0
  41. data/ext/ca_obj_fake.c +228 -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 +306 -0
  45. data/ext/ca_obj_grid.c +858 -440
  46. data/ext/ca_obj_meld.c +1034 -0
  47. data/ext/ca_obj_moncmp.c +569 -0
  48. data/ext/ca_obj_monop.c +1111 -0
  49. data/ext/ca_obj_object.c +774 -298
  50. data/ext/ca_obj_record.c +468 -0
  51. data/ext/ca_obj_reduce.c +97 -82
  52. data/ext/ca_obj_refer.c +569 -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 +616 -0
  56. data/ext/ca_obj_select.c +344 -296
  57. data/ext/ca_obj_select_axis.c +1296 -0
  58. data/ext/ca_obj_shift.c +230 -792
  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 +2501 -0
  62. data/ext/ca_obj_string.c +268 -0
  63. data/ext/ca_obj_tile.c +614 -0
  64. data/ext/ca_obj_time.c +546 -0
  65. data/ext/ca_obj_timedelta.c +435 -0
  66. data/ext/ca_obj_transpose.c +62 -516
  67. data/ext/ca_obj_triop.c +746 -0
  68. data/ext/ca_obj_unbound_repeat.c +208 -241
  69. data/ext/ca_obj_window.c +1131 -563
  70. data/ext/ca_op_byte_swap.c +175 -0
  71. data/ext/ca_op_ipower.c +319 -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 +430 -0
  75. data/ext/ca_sweep_engine.h +157 -0
  76. data/ext/ca_transform_common.c +228 -0
  77. data/ext/ca_triop_dispatch.c +55 -0
  78. data/ext/ca_triop_dispatch.h +62 -0
  79. data/ext/carray.h +795 -402
  80. data/ext/carray_access.c +831 -711
  81. data/ext/carray_attribute.c +98 -330
  82. data/ext/carray_bincount.c +255 -0
  83. data/ext/carray_broadcast.c +283 -0
  84. data/ext/carray_call_cfunc.c +1360 -828
  85. data/ext/carray_call_cfunc.h +160 -0
  86. data/ext/carray_cast.c +1212 -301
  87. data/ext/carray_cast_func.rb +81 -40
  88. data/ext/carray_class.c +53 -63
  89. data/ext/carray_config.h +28 -0
  90. data/ext/carray_conversion.c +350 -346
  91. data/ext/carray_copy.c +156 -268
  92. data/ext/carray_core.c +1342 -199
  93. data/ext/carray_count.c +312 -0
  94. data/ext/carray_data_type.c +43 -19
  95. data/ext/carray_element.c +585 -213
  96. data/ext/carray_factorize.c +2542 -0
  97. data/ext/carray_generate.c +230 -559
  98. data/ext/carray_histogram.c +490 -0
  99. data/ext/carray_hold.c +228 -0
  100. data/ext/carray_index_classifier.c +1035 -0
  101. data/ext/carray_index_classifier.h +27 -0
  102. data/ext/carray_internal.h +120 -0
  103. data/ext/carray_kernels_bincmp.c +4445 -0
  104. data/ext/carray_kernels_binop.c +10979 -0
  105. data/ext/carray_kernels_init.c +36 -0
  106. data/ext/carray_kernels_map.c +3466 -0
  107. data/ext/carray_kernels_moncmp.c +2096 -0
  108. data/ext/carray_kernels_monop.c +18312 -0
  109. data/ext/carray_kernels_reduce_aggregate.c +25836 -0
  110. data/ext/carray_kernels_reduce_boolean.c +329 -0
  111. data/ext/carray_kernels_reduce_cumulative.c +14592 -0
  112. data/ext/carray_kernels_reduce_extreme.c +16947 -0
  113. data/ext/carray_kernels_reduce_variance.c +3909 -0
  114. data/ext/carray_kernels_scan.c +3692 -0
  115. data/ext/carray_kernels_search.c +32137 -0
  116. data/ext/carray_kernels_sort.c +10625 -0
  117. data/ext/carray_kernels_triop.c +1391 -0
  118. data/ext/carray_lazy.c +567 -0
  119. data/ext/carray_loop.c +88 -200
  120. data/ext/carray_mask.c +848 -154
  121. data/ext/carray_math_kernel.h +120 -0
  122. data/ext/carray_mathfunc.c +10 -241
  123. data/ext/carray_median_percentile.c +1257 -0
  124. data/ext/carray_memory_view.c +1625 -0
  125. data/ext/carray_operator.c +1526 -318
  126. data/ext/carray_order.c +664 -1394
  127. data/ext/carray_partition.c +416 -0
  128. data/ext/carray_random.c +518 -0
  129. data/ext/carray_scatter.c +357 -0
  130. data/ext/carray_slab.c +1219 -0
  131. data/ext/carray_slab.h +84 -0
  132. data/ext/carray_sort.c +829 -0
  133. data/ext/carray_sort_kernel.c +620 -0
  134. data/ext/carray_struct.c +695 -0
  135. data/ext/carray_test.c +343 -229
  136. data/ext/carray_undef.c +34 -17
  137. data/ext/carray_utils.c +175 -74
  138. data/ext/extconf.rb +216 -55
  139. data/ext/mk_call_cfunc.rb +480 -0
  140. data/ext/mkkernel.rb +8842 -0
  141. data/ext/ruby_carray.c +202 -101
  142. data/ext/version.h +4 -14
  143. data/ext/version.rb +5 -13
  144. data/lib/carray/arrow_tensor.rb +401 -0
  145. data/lib/carray/attribute.rb +166 -0
  146. data/lib/carray/autoload_carray.rb +220 -0
  147. data/lib/carray/autoload_method_extension.rb +44 -0
  148. data/lib/carray/axis_group.rb +711 -0
  149. data/lib/carray/basics.rb +481 -0
  150. data/lib/carray/bincount_nd.rb +358 -0
  151. data/lib/carray/block_iterator.rb +604 -0
  152. data/lib/carray/boolean_reduce.rb +109 -0
  153. data/lib/carray/categorical.rb +561 -0
  154. data/lib/carray/categorical_iterator.rb +1062 -0
  155. data/lib/carray/complex.rb +150 -0
  156. data/lib/carray/conditional.rb +216 -0
  157. data/lib/carray/const_string.rb +228 -0
  158. data/lib/carray/construct.rb +139 -328
  159. data/lib/carray/core_extensions.rb +240 -0
  160. data/lib/carray/data_type_extension.rb +233 -0
  161. data/lib/carray/fixlen_string.rb +95 -0
  162. data/lib/carray/frame/concat.rb +132 -0
  163. data/lib/carray/frame/convert.rb +95 -0
  164. data/lib/carray/frame/csv_parser.rb +211 -0
  165. data/lib/carray/frame/frame.rb +649 -0
  166. data/lib/carray/frame/group.rb +186 -0
  167. data/lib/carray/frame/io.rb +164 -0
  168. data/lib/carray/frame/join.rb +248 -0
  169. data/lib/carray/frame/records.rb +99 -0
  170. data/lib/carray/frame/sort.rb +113 -0
  171. data/lib/carray/frame/verbs.rb +299 -0
  172. data/lib/carray/frame.rb +16 -0
  173. data/lib/carray/histogram.rb +512 -0
  174. data/lib/carray/inspect.rb +37 -20
  175. data/lib/carray/iterator.rb +57 -349
  176. data/lib/carray/lazy.rb +889 -0
  177. data/lib/carray/mask_gap_fill.rb +200 -0
  178. data/lib/carray/math.rb +78 -342
  179. data/lib/carray/meld_reduce.rb +289 -0
  180. data/lib/carray/methods/align_addr.rb +116 -0
  181. data/lib/carray/methods/bin.rb +128 -0
  182. data/lib/carray/methods/bincount.rb +87 -0
  183. data/lib/carray/methods/bit_string.rb +92 -0
  184. data/lib/carray/methods/broadcast.rb +63 -0
  185. data/lib/carray/methods/choose.rb +39 -0
  186. data/lib/carray/methods/composition.rb +280 -0
  187. data/lib/carray/methods/gather_nd.rb +206 -0
  188. data/lib/carray/methods/index.rb +39 -0
  189. data/lib/carray/methods/insert_block.rb +99 -0
  190. data/lib/carray/methods/is_in.rb +141 -0
  191. data/lib/carray/methods/join.rb +90 -0
  192. data/lib/carray/methods/locate_addr.rb +47 -0
  193. data/lib/carray/methods/mask_duplicates.rb +41 -0
  194. data/lib/carray/methods/meshgrid.rb +91 -0
  195. data/lib/carray/methods/mode.rb +126 -0
  196. data/lib/carray/methods/nunique.rb +46 -0
  197. data/lib/carray/methods/resize.rb +56 -0
  198. data/lib/carray/methods/snap.rb +156 -0
  199. data/lib/carray/methods/string_format.rb +57 -0
  200. data/lib/carray/methods/unique.rb +47 -0
  201. data/lib/carray/methods/value_counts.rb +71 -0
  202. data/lib/carray/mkmf.rb +124 -101
  203. data/lib/carray/runtime.rb +108 -0
  204. data/lib/carray/serialize.rb +478 -167
  205. data/lib/carray/slab_iterator.rb +292 -0
  206. data/lib/carray/stack.rb +291 -0
  207. data/lib/carray/string.rb +56 -180
  208. data/lib/carray/string_operation_extension.rb +289 -0
  209. data/lib/carray/struct.rb +335 -323
  210. data/lib/carray/struct_builder.rb +697 -0
  211. data/lib/carray/table.rb +41 -2
  212. data/lib/carray/time.rb +2255 -38
  213. data/lib/carray/window_iterator.rb +655 -0
  214. data/lib/carray.rb +55 -57
  215. metadata +163 -130
  216. data/Rakefile +0 -51
  217. data/TODO.md +0 -18
  218. data/ext/ca_iter_block.c +0 -257
  219. data/ext/ca_iter_dimension.c +0 -299
  220. data/ext/ca_iter_window.c +0 -214
  221. data/ext/ca_obj_mapping.c +0 -644
  222. data/ext/carray_iterator.c +0 -641
  223. data/ext/carray_math.rb +0 -850
  224. data/ext/carray_numeric.c +0 -259
  225. data/ext/carray_sort_addr.c +0 -254
  226. data/ext/carray_stat.c +0 -2100
  227. data/ext/carray_stat_proc.rb +0 -1999
  228. data/ext/mkmath.rb +0 -741
  229. data/ext/ruby_ccomplex.c +0 -509
  230. data/ext/ruby_float_func.c +0 -86
  231. data/lib/carray/array.rb +0 -8
  232. data/lib/carray/autoload/autoload_base.rb +0 -19
  233. data/lib/carray/autoload/autoload_gem_cairo.rb +0 -9
  234. data/lib/carray/autoload/autoload_gem_ffi.rb +0 -9
  235. data/lib/carray/autoload/autoload_gem_gnuplot.rb +0 -2
  236. data/lib/carray/autoload/autoload_gem_io_csv.rb +0 -14
  237. data/lib/carray/autoload/autoload_gem_io_pg.rb +0 -6
  238. data/lib/carray/autoload/autoload_gem_io_sqlite3.rb +0 -12
  239. data/lib/carray/autoload/autoload_gem_narray.rb +0 -10
  240. data/lib/carray/autoload/autoload_gem_numo_narray.rb +0 -15
  241. data/lib/carray/autoload/autoload_gem_opencv.rb +0 -16
  242. data/lib/carray/autoload/autoload_gem_random.rb +0 -8
  243. data/lib/carray/autoload/autoload_gem_rmagick.rb +0 -23
  244. data/lib/carray/autoload/autoload_gem_zimg.rb +0 -3
  245. data/lib/carray/autoload/autoload_io_imagemagick.rb +0 -6
  246. data/lib/carray/autoload/autoload_math_histogram.rb +0 -5
  247. data/lib/carray/autoload/autoload_math_recurrence.rb +0 -6
  248. data/lib/carray/autoload/autoload_object_iterator.rb +0 -1
  249. data/lib/carray/autoload/autoload_object_link.rb +0 -1
  250. data/lib/carray/autoload/autoload_object_pack.rb +0 -2
  251. data/lib/carray/autoload.rb +0 -141
  252. data/lib/carray/basic.rb +0 -191
  253. data/lib/carray/broadcast.rb +0 -101
  254. data/lib/carray/compose.rb +0 -315
  255. data/lib/carray/convert.rb +0 -115
  256. data/lib/carray/info.rb +0 -110
  257. data/lib/carray/io/imagemagick.rb +0 -235
  258. data/lib/carray/mask.rb +0 -102
  259. data/lib/carray/math/histogram.rb +0 -177
  260. data/lib/carray/math/recurrence.rb +0 -93
  261. data/lib/carray/object/ca_obj_iterator.rb +0 -50
  262. data/lib/carray/object/ca_obj_link.rb +0 -50
  263. data/lib/carray/object/ca_obj_pack.rb +0 -99
  264. data/lib/carray/obsolete.rb +0 -256
  265. data/lib/carray/ordering.rb +0 -181
  266. data/lib/carray/testing.rb +0 -51
  267. data/lib/carray/transform.rb +0 -109
  268. data/misc/Methods.ja.md +0 -182
  269. data/misc/NOTE +0 -51
  270. data/spec/Classes/CABitfield_spec.rb +0 -58
  271. data/spec/Classes/CABlockIterator_spec.rb +0 -114
  272. data/spec/Classes/CABlock_spec.rb +0 -205
  273. data/spec/Classes/CAField_spec.rb +0 -39
  274. data/spec/Classes/CAGrid_spec.rb +0 -75
  275. data/spec/Classes/CAMap_spec.rb +0 -0
  276. data/spec/Classes/CAMapping_spec.rb +0 -105
  277. data/spec/Classes/CAObject_attribute_spec.rb +0 -33
  278. data/spec/Classes/CAObject_spec.rb +0 -33
  279. data/spec/Classes/CARefer_spec.rb +0 -93
  280. data/spec/Classes/CARepeat_spec.rb +0 -65
  281. data/spec/Classes/CASelect_spec.rb +0 -22
  282. data/spec/Classes/CAShift_spec.rb +0 -16
  283. data/spec/Classes/CAStruct_spec.rb +0 -71
  284. data/spec/Classes/CATranspose_spec.rb +0 -60
  285. data/spec/Classes/CAUnboudRepeat_spec.rb +0 -102
  286. data/spec/Classes/CAWindow_spec.rb +0 -54
  287. data/spec/Classes/CAWrap_spec.rb +0 -8
  288. data/spec/Classes/CArray_spec.rb +0 -184
  289. data/spec/Classes/CScalar_spec.rb +0 -55
  290. data/spec/Classes/ex1.rb +0 -46
  291. data/spec/Features/feature_130_spec.rb +0 -19
  292. data/spec/Features/feature_attributes_spec.rb +0 -280
  293. data/spec/Features/feature_boolean_spec.rb +0 -98
  294. data/spec/Features/feature_broadcast.rb +0 -116
  295. data/spec/Features/feature_cast_function.rb +0 -19
  296. data/spec/Features/feature_cast_spec.rb +0 -33
  297. data/spec/Features/feature_class_spec.rb +0 -84
  298. data/spec/Features/feature_complex_spec.rb +0 -42
  299. data/spec/Features/feature_composite_spec.rb +0 -124
  300. data/spec/Features/feature_convert_spec.rb +0 -46
  301. data/spec/Features/feature_copy_spec.rb +0 -123
  302. data/spec/Features/feature_creation_spec.rb +0 -84
  303. data/spec/Features/feature_element_spec.rb +0 -144
  304. data/spec/Features/feature_extream_spec.rb +0 -54
  305. data/spec/Features/feature_generate_spec.rb +0 -74
  306. data/spec/Features/feature_index_spec.rb +0 -69
  307. data/spec/Features/feature_mask_spec.rb +0 -580
  308. data/spec/Features/feature_math_spec.rb +0 -97
  309. data/spec/Features/feature_order_spec.rb +0 -146
  310. data/spec/Features/feature_ref_store_spec.rb +0 -209
  311. data/spec/Features/feature_serialization_spec.rb +0 -125
  312. data/spec/Features/feature_stat_spec.rb +0 -397
  313. data/spec/Features/feature_virtual_spec.rb +0 -48
  314. data/spec/Features/method_eq_spec.rb +0 -81
  315. data/spec/Features/method_is_nan_spec.rb +0 -12
  316. data/spec/Features/method_map_spec.rb +0 -54
  317. data/spec/Features/method_max_with.rb +0 -20
  318. data/spec/Features/method_min_with.rb +0 -19
  319. data/spec/Features/method_ne_spec.rb +0 -18
  320. data/spec/Features/method_project_spec.rb +0 -188
  321. data/spec/Features/method_ref_spec.rb +0 -27
  322. data/spec/Features/method_round_spec.rb +0 -11
  323. data/spec/Features/method_s_linspace_spec.rb +0 -48
  324. data/spec/Features/method_s_span_spec.rb +0 -14
  325. data/spec/Features/method_seq_spec.rb +0 -47
  326. data/spec/Features/method_sort_with.rb +0 -43
  327. data/spec/Features/method_sorted_with.rb +0 -29
  328. data/spec/Features/method_span_spec.rb +0 -42
  329. data/spec/Features/method_wrap_readonly_spec.rb +0 -43
  330. data/spec/UnitTest/test_CAVirtual.rb +0 -214
  331. data/spec/spec_all.rb +0 -10
  332. data/utils/ca_ase.rb +0 -21
  333. data/utils/ca_methods.rb +0 -15
  334. data/utils/cast_checker.rb +0 -30
  335. data/utils/convert_test.rb +0 -73
  336. data/utils/extract_yard.rb +0 -22
  337. data/utils/guess_shape.rb +0 -76
  338. data/utils/monkey_patch_methods.rb +0 -62
  339. 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-2020 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. `dtype` nil returns a
30
+ # CAString (string results); an explicit dtype returns a plain typed array
31
+ # (integer / boolean results). Shape and mask are carried.
32
+ def string_map (dtype = nil) # :nodoc:
33
+ out = dtype ? template(dtype) : 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
+ dtype ? 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