enclave 0.1.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 (739) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +182 -0
  3. data/Rakefile +30 -0
  4. data/ext/enclave/enclave.c +390 -0
  5. data/ext/enclave/extconf.rb +33 -0
  6. data/ext/enclave/mruby/Makefile +63 -0
  7. data/ext/enclave/mruby/Rakefile +102 -0
  8. data/ext/enclave/mruby/benchmark/bm_ao_render.rb +309 -0
  9. data/ext/enclave/mruby/benchmark/bm_app_lc_fizzbuzz.rb +51 -0
  10. data/ext/enclave/mruby/benchmark/bm_fib.rb +6 -0
  11. data/ext/enclave/mruby/benchmark/bm_mandel_term.rb +34 -0
  12. data/ext/enclave/mruby/benchmark/bm_so_lists.rb +49 -0
  13. data/ext/enclave/mruby/benchmark/bm_so_mandelbrot.rb +65 -0
  14. data/ext/enclave/mruby/benchmark/vm_dispatch_bench.c +197 -0
  15. data/ext/enclave/mruby/benchmark/vm_optimization_bench.rb +513 -0
  16. data/ext/enclave/mruby/build/host/include/mrbconf.h +230 -0
  17. data/ext/enclave/mruby/build/host/include/mruby/array.h +303 -0
  18. data/ext/enclave/mruby/build/host/include/mruby/boxing_nan.h +169 -0
  19. data/ext/enclave/mruby/build/host/include/mruby/boxing_no.h +59 -0
  20. data/ext/enclave/mruby/build/host/include/mruby/boxing_word.h +248 -0
  21. data/ext/enclave/mruby/build/host/include/mruby/class.h +157 -0
  22. data/ext/enclave/mruby/build/host/include/mruby/common.h +127 -0
  23. data/ext/enclave/mruby/build/host/include/mruby/compile.h +187 -0
  24. data/ext/enclave/mruby/build/host/include/mruby/data.h +76 -0
  25. data/ext/enclave/mruby/build/host/include/mruby/debug.h +75 -0
  26. data/ext/enclave/mruby/build/host/include/mruby/dump.h +159 -0
  27. data/ext/enclave/mruby/build/host/include/mruby/endian.h +44 -0
  28. data/ext/enclave/mruby/build/host/include/mruby/error.h +168 -0
  29. data/ext/enclave/mruby/build/host/include/mruby/gc.h +77 -0
  30. data/ext/enclave/mruby/build/host/include/mruby/hash.h +234 -0
  31. data/ext/enclave/mruby/build/host/include/mruby/internal.h +278 -0
  32. data/ext/enclave/mruby/build/host/include/mruby/irep.h +142 -0
  33. data/ext/enclave/mruby/build/host/include/mruby/istruct.h +50 -0
  34. data/ext/enclave/mruby/build/host/include/mruby/khash.h +455 -0
  35. data/ext/enclave/mruby/build/host/include/mruby/mempool.h +19 -0
  36. data/ext/enclave/mruby/build/host/include/mruby/numeric.h +174 -0
  37. data/ext/enclave/mruby/build/host/include/mruby/object.h +44 -0
  38. data/ext/enclave/mruby/build/host/include/mruby/opcode.h +73 -0
  39. data/ext/enclave/mruby/build/host/include/mruby/ops.h +133 -0
  40. data/ext/enclave/mruby/build/host/include/mruby/presym/id.h +895 -0
  41. data/ext/enclave/mruby/build/host/include/mruby/presym/scanning.h +82 -0
  42. data/ext/enclave/mruby/build/host/include/mruby/presym/table.h +1787 -0
  43. data/ext/enclave/mruby/build/host/include/mruby/presym.h +65 -0
  44. data/ext/enclave/mruby/build/host/include/mruby/proc.h +184 -0
  45. data/ext/enclave/mruby/build/host/include/mruby/range.h +77 -0
  46. data/ext/enclave/mruby/build/host/include/mruby/re.h +16 -0
  47. data/ext/enclave/mruby/build/host/include/mruby/string.h +428 -0
  48. data/ext/enclave/mruby/build/host/include/mruby/throw.h +81 -0
  49. data/ext/enclave/mruby/build/host/include/mruby/value.h +471 -0
  50. data/ext/enclave/mruby/build/host/include/mruby/variable.h +108 -0
  51. data/ext/enclave/mruby/build/host/include/mruby/version.h +143 -0
  52. data/ext/enclave/mruby/build/host/include/mruby.h +1632 -0
  53. data/ext/enclave/mruby/build/host/mrbc/include/mruby/presym/id.h +281 -0
  54. data/ext/enclave/mruby/build/host/mrbc/include/mruby/presym/table.h +559 -0
  55. data/ext/enclave/mruby/build/host/mrbgems/gem_init.c +164 -0
  56. data/ext/enclave/mruby/build/host/mrbgems/mruby-array-ext/gem_init.c +650 -0
  57. data/ext/enclave/mruby/build/host/mrbgems/mruby-binding/gem_init.c +21 -0
  58. data/ext/enclave/mruby/build/host/mrbgems/mruby-catch/gem_init.c +86 -0
  59. data/ext/enclave/mruby/build/host/mrbgems/mruby-class-ext/gem_init.c +21 -0
  60. data/ext/enclave/mruby/build/host/mrbgems/mruby-compar-ext/gem_init.c +99 -0
  61. data/ext/enclave/mruby/build/host/mrbgems/mruby-complex/gem_init.c +362 -0
  62. data/ext/enclave/mruby/build/host/mrbgems/mruby-data/gem_init.c +21 -0
  63. data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-chain/gem_init.c +229 -0
  64. data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-ext/gem_init.c +1420 -0
  65. data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-lazy/gem_init.c +602 -0
  66. data/ext/enclave/mruby/build/host/mrbgems/mruby-enumerator/gem_init.c +822 -0
  67. data/ext/enclave/mruby/build/host/mrbgems/mruby-eval/gem_init.c +21 -0
  68. data/ext/enclave/mruby/build/host/mrbgems/mruby-fiber/gem_init.c +21 -0
  69. data/ext/enclave/mruby/build/host/mrbgems/mruby-hash-ext/gem_init.c +591 -0
  70. data/ext/enclave/mruby/build/host/mrbgems/mruby-kernel-ext/gem_init.c +21 -0
  71. data/ext/enclave/mruby/build/host/mrbgems/mruby-math/gem_init.c +21 -0
  72. data/ext/enclave/mruby/build/host/mrbgems/mruby-metaprog/gem_init.c +21 -0
  73. data/ext/enclave/mruby/build/host/mrbgems/mruby-method/gem_init.c +153 -0
  74. data/ext/enclave/mruby/build/host/mrbgems/mruby-numeric-ext/gem_init.c +211 -0
  75. data/ext/enclave/mruby/build/host/mrbgems/mruby-object-ext/gem_init.c +94 -0
  76. data/ext/enclave/mruby/build/host/mrbgems/mruby-objectspace/gem_init.c +21 -0
  77. data/ext/enclave/mruby/build/host/mrbgems/mruby-pack/gem_init.c +21 -0
  78. data/ext/enclave/mruby/build/host/mrbgems/mruby-proc-binding/gem_init.c +21 -0
  79. data/ext/enclave/mruby/build/host/mrbgems/mruby-proc-ext/gem_init.c +237 -0
  80. data/ext/enclave/mruby/build/host/mrbgems/mruby-random/gem_init.c +21 -0
  81. data/ext/enclave/mruby/build/host/mrbgems/mruby-range-ext/gem_init.c +205 -0
  82. data/ext/enclave/mruby/build/host/mrbgems/mruby-rational/gem_init.c +147 -0
  83. data/ext/enclave/mruby/build/host/mrbgems/mruby-set/gem_init.c +487 -0
  84. data/ext/enclave/mruby/build/host/mrbgems/mruby-sprintf/gem_init.c +83 -0
  85. data/ext/enclave/mruby/build/host/mrbgems/mruby-string-ext/gem_init.c +220 -0
  86. data/ext/enclave/mruby/build/host/mrbgems/mruby-struct/gem_init.c +175 -0
  87. data/ext/enclave/mruby/build/host/mrbgems/mruby-symbol-ext/gem_init.c +153 -0
  88. data/ext/enclave/mruby/build/host/mrbgems/mruby-time/gem_init.c +21 -0
  89. data/ext/enclave/mruby/build/host/mrbgems/mruby-toplevel-ext/gem_init.c +78 -0
  90. data/ext/enclave/mruby/build/host/mrblib/mrblib.c +1758 -0
  91. data/ext/enclave/mruby/build_config/ArduinoDue.rb +72 -0
  92. data/ext/enclave/mruby/build_config/IntelEdison.rb +69 -0
  93. data/ext/enclave/mruby/build_config/IntelGalileo.rb +88 -0
  94. data/ext/enclave/mruby/build_config/RX630.rb +63 -0
  95. data/ext/enclave/mruby/build_config/android_arm64_v8a.rb +11 -0
  96. data/ext/enclave/mruby/build_config/android_armeabi_v7a_neon_hard.rb +13 -0
  97. data/ext/enclave/mruby/build_config/bench.rb +11 -0
  98. data/ext/enclave/mruby/build_config/boxing.rb +19 -0
  99. data/ext/enclave/mruby/build_config/chipKITMax32.rb +68 -0
  100. data/ext/enclave/mruby/build_config/ci/gcc-clang.rb +40 -0
  101. data/ext/enclave/mruby/build_config/ci/msvc.rb +20 -0
  102. data/ext/enclave/mruby/build_config/clang-asan.rb +11 -0
  103. data/ext/enclave/mruby/build_config/cosmopolitan.rb +86 -0
  104. data/ext/enclave/mruby/build_config/cross-32bit.rb +14 -0
  105. data/ext/enclave/mruby/build_config/cross-mingw-winetest.rb +90 -0
  106. data/ext/enclave/mruby/build_config/cross-mingw.rb +14 -0
  107. data/ext/enclave/mruby/build_config/default.rb +83 -0
  108. data/ext/enclave/mruby/build_config/dreamcast_shelf.rb +81 -0
  109. data/ext/enclave/mruby/build_config/emscripten-cxx.rb +12 -0
  110. data/ext/enclave/mruby/build_config/emscripten.rb +10 -0
  111. data/ext/enclave/mruby/build_config/gameboyadvance.rb +72 -0
  112. data/ext/enclave/mruby/build_config/helpers/wine_runner.rb +71 -0
  113. data/ext/enclave/mruby/build_config/host-cxx.rb +12 -0
  114. data/ext/enclave/mruby/build_config/host-debug.rb +20 -0
  115. data/ext/enclave/mruby/build_config/host-f32.rb +14 -0
  116. data/ext/enclave/mruby/build_config/host-gprof.rb +14 -0
  117. data/ext/enclave/mruby/build_config/host-m32.rb +15 -0
  118. data/ext/enclave/mruby/build_config/host-nofloat.rb +22 -0
  119. data/ext/enclave/mruby/build_config/host-shared.rb +36 -0
  120. data/ext/enclave/mruby/build_config/i586-pc-msdosdjgpp.rb +76 -0
  121. data/ext/enclave/mruby/build_config/luckfox_pico.rb +106 -0
  122. data/ext/enclave/mruby/build_config/milkv_duo.rb +106 -0
  123. data/ext/enclave/mruby/build_config/minimal.rb +4 -0
  124. data/ext/enclave/mruby/build_config/mrbc.rb +10 -0
  125. data/ext/enclave/mruby/build_config/nintendo_switch.rb +73 -0
  126. data/ext/enclave/mruby/build_config/nintendo_wii.rb +95 -0
  127. data/ext/enclave/mruby/build_config/no-float.rb +17 -0
  128. data/ext/enclave/mruby/build_config/playstationportable.rb +78 -0
  129. data/ext/enclave/mruby/build_config/serenity.rb +26 -0
  130. data/ext/enclave/mruby/build_config.rb +9 -0
  131. data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb +5 -0
  132. data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c +23 -0
  133. data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb +7 -0
  134. data/ext/enclave/mruby/examples/mrbgems/c_extension_example/src/example.c +23 -0
  135. data/ext/enclave/mruby/examples/mrbgems/c_extension_example/test/example.c +7 -0
  136. data/ext/enclave/mruby/examples/mrbgems/c_extension_example/test/example.rb +3 -0
  137. data/ext/enclave/mruby/examples/mrbgems/cdata_extension_example/src/example.c +77 -0
  138. data/ext/enclave/mruby/examples/mrbgems/cdata_extension_example/test/example.c +7 -0
  139. data/ext/enclave/mruby/examples/mrbgems/mruby-YOUR-bigint/core/bigint.c +70 -0
  140. data/ext/enclave/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb +5 -0
  141. data/ext/enclave/mruby/examples/mrbgems/ruby_extension_example/test/example.rb +3 -0
  142. data/ext/enclave/mruby/include/mrbconf.h +230 -0
  143. data/ext/enclave/mruby/include/mruby/array.h +303 -0
  144. data/ext/enclave/mruby/include/mruby/boxing_nan.h +169 -0
  145. data/ext/enclave/mruby/include/mruby/boxing_no.h +59 -0
  146. data/ext/enclave/mruby/include/mruby/boxing_word.h +248 -0
  147. data/ext/enclave/mruby/include/mruby/class.h +157 -0
  148. data/ext/enclave/mruby/include/mruby/common.h +127 -0
  149. data/ext/enclave/mruby/include/mruby/compile.h +187 -0
  150. data/ext/enclave/mruby/include/mruby/data.h +76 -0
  151. data/ext/enclave/mruby/include/mruby/debug.h +75 -0
  152. data/ext/enclave/mruby/include/mruby/dump.h +159 -0
  153. data/ext/enclave/mruby/include/mruby/endian.h +44 -0
  154. data/ext/enclave/mruby/include/mruby/error.h +168 -0
  155. data/ext/enclave/mruby/include/mruby/gc.h +77 -0
  156. data/ext/enclave/mruby/include/mruby/hash.h +234 -0
  157. data/ext/enclave/mruby/include/mruby/internal.h +278 -0
  158. data/ext/enclave/mruby/include/mruby/irep.h +142 -0
  159. data/ext/enclave/mruby/include/mruby/istruct.h +50 -0
  160. data/ext/enclave/mruby/include/mruby/khash.h +455 -0
  161. data/ext/enclave/mruby/include/mruby/mempool.h +19 -0
  162. data/ext/enclave/mruby/include/mruby/numeric.h +174 -0
  163. data/ext/enclave/mruby/include/mruby/object.h +44 -0
  164. data/ext/enclave/mruby/include/mruby/opcode.h +73 -0
  165. data/ext/enclave/mruby/include/mruby/ops.h +133 -0
  166. data/ext/enclave/mruby/include/mruby/presym/scanning.h +82 -0
  167. data/ext/enclave/mruby/include/mruby/presym.h +65 -0
  168. data/ext/enclave/mruby/include/mruby/proc.h +184 -0
  169. data/ext/enclave/mruby/include/mruby/range.h +77 -0
  170. data/ext/enclave/mruby/include/mruby/re.h +16 -0
  171. data/ext/enclave/mruby/include/mruby/string.h +428 -0
  172. data/ext/enclave/mruby/include/mruby/throw.h +81 -0
  173. data/ext/enclave/mruby/include/mruby/value.h +471 -0
  174. data/ext/enclave/mruby/include/mruby/variable.h +108 -0
  175. data/ext/enclave/mruby/include/mruby/version.h +143 -0
  176. data/ext/enclave/mruby/include/mruby.h +1632 -0
  177. data/ext/enclave/mruby/lib/mruby/amalgam.rb +568 -0
  178. data/ext/enclave/mruby/lib/mruby/build/command.rb +383 -0
  179. data/ext/enclave/mruby/lib/mruby/build/load_gems.rb +383 -0
  180. data/ext/enclave/mruby/lib/mruby/build.rb +616 -0
  181. data/ext/enclave/mruby/lib/mruby/core_ext.rb +61 -0
  182. data/ext/enclave/mruby/lib/mruby/doc.rb +51 -0
  183. data/ext/enclave/mruby/lib/mruby/gem.rb +585 -0
  184. data/ext/enclave/mruby/lib/mruby/lockfile.rb +81 -0
  185. data/ext/enclave/mruby/lib/mruby/presym.rb +167 -0
  186. data/ext/enclave/mruby/lib/mruby/source.rb +32 -0
  187. data/ext/enclave/mruby/mrbgems/default-no-fpu.gembox +3 -0
  188. data/ext/enclave/mruby/mrbgems/default-no-stdio.gembox +4 -0
  189. data/ext/enclave/mruby/mrbgems/default.gembox +25 -0
  190. data/ext/enclave/mruby/mrbgems/full-core.gembox +6 -0
  191. data/ext/enclave/mruby/mrbgems/hal-posix-dir/mrbgem.rake +7 -0
  192. data/ext/enclave/mruby/mrbgems/hal-posix-dir/src/dir_hal.c +193 -0
  193. data/ext/enclave/mruby/mrbgems/hal-posix-io/mrbgem.rake +8 -0
  194. data/ext/enclave/mruby/mrbgems/hal-posix-io/src/io_hal.c +602 -0
  195. data/ext/enclave/mruby/mrbgems/hal-posix-socket/mrbgem.rake +8 -0
  196. data/ext/enclave/mruby/mrbgems/hal-posix-socket/src/socket_hal.c +158 -0
  197. data/ext/enclave/mruby/mrbgems/hal-posix-task/README.md +102 -0
  198. data/ext/enclave/mruby/mrbgems/hal-posix-task/mrbgem.rake +8 -0
  199. data/ext/enclave/mruby/mrbgems/hal-posix-task/src/task_hal.c +252 -0
  200. data/ext/enclave/mruby/mrbgems/hal-win-dir/mrbgem.rake +7 -0
  201. data/ext/enclave/mruby/mrbgems/hal-win-dir/src/dir_hal.c +249 -0
  202. data/ext/enclave/mruby/mrbgems/hal-win-io/mrbgem.rake +11 -0
  203. data/ext/enclave/mruby/mrbgems/hal-win-io/src/io_hal.c +646 -0
  204. data/ext/enclave/mruby/mrbgems/hal-win-socket/mrbgem.rake +12 -0
  205. data/ext/enclave/mruby/mrbgems/hal-win-socket/src/socket_hal.c +177 -0
  206. data/ext/enclave/mruby/mrbgems/hal-win-task/README.md +109 -0
  207. data/ext/enclave/mruby/mrbgems/hal-win-task/mrbgem.rake +11 -0
  208. data/ext/enclave/mruby/mrbgems/hal-win-task/src/task_hal.c +187 -0
  209. data/ext/enclave/mruby/mrbgems/math.gembox +12 -0
  210. data/ext/enclave/mruby/mrbgems/metaprog.gembox +21 -0
  211. data/ext/enclave/mruby/mrbgems/mruby-array-ext/README.md +87 -0
  212. data/ext/enclave/mruby/mrbgems/mruby-array-ext/mrbgem.rake +5 -0
  213. data/ext/enclave/mruby/mrbgems/mruby-array-ext/mrblib/array.rb +784 -0
  214. data/ext/enclave/mruby/mrbgems/mruby-array-ext/src/array.c +1583 -0
  215. data/ext/enclave/mruby/mrbgems/mruby-array-ext/test/array.rb +849 -0
  216. data/ext/enclave/mruby/mrbgems/mruby-benchmark/README.md +257 -0
  217. data/ext/enclave/mruby/mrbgems/mruby-benchmark/mrbgem.rake +10 -0
  218. data/ext/enclave/mruby/mrbgems/mruby-benchmark/mrblib/benchmark.rb +131 -0
  219. data/ext/enclave/mruby/mrbgems/mruby-benchmark/test/benchmark.rb +244 -0
  220. data/ext/enclave/mruby/mrbgems/mruby-bigint/README-fgmp.md +154 -0
  221. data/ext/enclave/mruby/mrbgems/mruby-bigint/README.md +44 -0
  222. data/ext/enclave/mruby/mrbgems/mruby-bigint/core/bigint.c +6335 -0
  223. data/ext/enclave/mruby/mrbgems/mruby-bigint/core/bigint.h +117 -0
  224. data/ext/enclave/mruby/mrbgems/mruby-bigint/mrbgem.rake +10 -0
  225. data/ext/enclave/mruby/mrbgems/mruby-bigint/test/bigint.rb +157 -0
  226. data/ext/enclave/mruby/mrbgems/mruby-bin-config/README.md +46 -0
  227. data/ext/enclave/mruby/mrbgems/mruby-bin-config/mrbgem.rake +49 -0
  228. data/ext/enclave/mruby/mrbgems/mruby-bin-config/mruby-config +46 -0
  229. data/ext/enclave/mruby/mrbgems/mruby-bin-config/mruby-config.bat +92 -0
  230. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/README.md +63 -0
  231. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb +283 -0
  232. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb +703 -0
  233. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake +10 -0
  234. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c +523 -0
  235. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h +26 -0
  236. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c +238 -0
  237. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h +14 -0
  238. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c +88 -0
  239. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h +13 -0
  240. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apistring.c +34 -0
  241. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apistring.h +14 -0
  242. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c +436 -0
  243. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c +509 -0
  244. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c +71 -0
  245. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c +64 -0
  246. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +768 -0
  247. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h +159 -0
  248. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h +24 -0
  249. data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h +19 -0
  250. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/README.md +94 -0
  251. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb +58 -0
  252. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake +7 -0
  253. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +808 -0
  254. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_buffer.c +1035 -0
  255. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_buffer.h +185 -0
  256. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.c +797 -0
  257. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.h +132 -0
  258. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c +1118 -0
  259. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.h +153 -0
  260. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_highlight.c +516 -0
  261. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_highlight.h +95 -0
  262. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_history.c +185 -0
  263. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_history.h +76 -0
  264. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_term.c +491 -0
  265. data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_term.h +137 -0
  266. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/README.md +58 -0
  267. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/bintest/mrbc.rb +30 -0
  268. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake +15 -0
  269. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c +362 -0
  270. data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/stub.c +104 -0
  271. data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/README.md +47 -0
  272. data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb +178 -0
  273. data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/mrbgem.rake +7 -0
  274. data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +380 -0
  275. data/ext/enclave/mruby/mrbgems/mruby-bin-strip/README.md +38 -0
  276. data/ext/enclave/mruby/mrbgems/mruby-bin-strip/bintest/mruby_strip.rb +73 -0
  277. data/ext/enclave/mruby/mrbgems/mruby-bin-strip/mrbgem.rake +7 -0
  278. data/ext/enclave/mruby/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby_strip.c +139 -0
  279. data/ext/enclave/mruby/mrbgems/mruby-binding/README.md +256 -0
  280. data/ext/enclave/mruby/mrbgems/mruby-binding/mrbgem.rake +7 -0
  281. data/ext/enclave/mruby/mrbgems/mruby-binding/src/binding.c +518 -0
  282. data/ext/enclave/mruby/mrbgems/mruby-binding/test/binding.c +14 -0
  283. data/ext/enclave/mruby/mrbgems/mruby-binding/test/binding.rb +64 -0
  284. data/ext/enclave/mruby/mrbgems/mruby-catch/README.md +94 -0
  285. data/ext/enclave/mruby/mrbgems/mruby-catch/mrbgem.rake +5 -0
  286. data/ext/enclave/mruby/mrbgems/mruby-catch/mrblib/catch.rb +29 -0
  287. data/ext/enclave/mruby/mrbgems/mruby-catch/src/catch.c +149 -0
  288. data/ext/enclave/mruby/mrbgems/mruby-catch/test/catch.rb +86 -0
  289. data/ext/enclave/mruby/mrbgems/mruby-class-ext/README.md +81 -0
  290. data/ext/enclave/mruby/mrbgems/mruby-class-ext/mrbgem.rake +5 -0
  291. data/ext/enclave/mruby/mrbgems/mruby-class-ext/src/class.c +377 -0
  292. data/ext/enclave/mruby/mrbgems/mruby-class-ext/test/class.rb +46 -0
  293. data/ext/enclave/mruby/mrbgems/mruby-class-ext/test/module.rb +109 -0
  294. data/ext/enclave/mruby/mrbgems/mruby-cmath/README.md +45 -0
  295. data/ext/enclave/mruby/mrbgems/mruby-cmath/mrbgem.rake +8 -0
  296. data/ext/enclave/mruby/mrbgems/mruby-cmath/src/cmath.c +426 -0
  297. data/ext/enclave/mruby/mrbgems/mruby-cmath/test/cmath.rb +41 -0
  298. data/ext/enclave/mruby/mrbgems/mruby-compar-ext/README.md +65 -0
  299. data/ext/enclave/mruby/mrbgems/mruby-compar-ext/mrbgem.rake +5 -0
  300. data/ext/enclave/mruby/mrbgems/mruby-compar-ext/mrblib/compar.rb +75 -0
  301. data/ext/enclave/mruby/mrbgems/mruby-compar-ext/test/compar.rb +21 -0
  302. data/ext/enclave/mruby/mrbgems/mruby-compiler/README.md +28 -0
  303. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/codegen.c +7316 -0
  304. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/keywords +52 -0
  305. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/lex.def +207 -0
  306. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/node.h +784 -0
  307. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/parse.y +8977 -0
  308. data/ext/enclave/mruby/mrbgems/mruby-compiler/core/y.tab.c +16136 -0
  309. data/ext/enclave/mruby/mrbgems/mruby-compiler/mrbgem.rake +42 -0
  310. data/ext/enclave/mruby/mrbgems/mruby-complex/README.md +55 -0
  311. data/ext/enclave/mruby/mrbgems/mruby-complex/mrbgem.rake +7 -0
  312. data/ext/enclave/mruby/mrbgems/mruby-complex/mrblib/complex.rb +259 -0
  313. data/ext/enclave/mruby/mrbgems/mruby-complex/src/complex.c +597 -0
  314. data/ext/enclave/mruby/mrbgems/mruby-complex/test/complex.rb +174 -0
  315. data/ext/enclave/mruby/mrbgems/mruby-data/README.md +126 -0
  316. data/ext/enclave/mruby/mrbgems/mruby-data/mrbgem.rake +5 -0
  317. data/ext/enclave/mruby/mrbgems/mruby-data/src/data.c +550 -0
  318. data/ext/enclave/mruby/mrbgems/mruby-data/test/data.rb +76 -0
  319. data/ext/enclave/mruby/mrbgems/mruby-dir/README.md +53 -0
  320. data/ext/enclave/mruby/mrbgems/mruby-dir/include/dir_hal.h +79 -0
  321. data/ext/enclave/mruby/mrbgems/mruby-dir/mrbgem.rake +35 -0
  322. data/ext/enclave/mruby/mrbgems/mruby-dir/mrblib/dir.rb +124 -0
  323. data/ext/enclave/mruby/mrbgems/mruby-dir/src/dir.c +493 -0
  324. data/ext/enclave/mruby/mrbgems/mruby-dir/test/dir.rb +138 -0
  325. data/ext/enclave/mruby/mrbgems/mruby-dir/test/dirtest.c +125 -0
  326. data/ext/enclave/mruby/mrbgems/mruby-encoding/README.md +96 -0
  327. data/ext/enclave/mruby/mrbgems/mruby-encoding/mrbgem.rake +8 -0
  328. data/ext/enclave/mruby/mrbgems/mruby-encoding/src/encoding.c +128 -0
  329. data/ext/enclave/mruby/mrbgems/mruby-encoding/test/numeric.rb +27 -0
  330. data/ext/enclave/mruby/mrbgems/mruby-encoding/test/string.rb +30 -0
  331. data/ext/enclave/mruby/mrbgems/mruby-enum-chain/README.md +80 -0
  332. data/ext/enclave/mruby/mrbgems/mruby-enum-chain/mrbgem.rake +6 -0
  333. data/ext/enclave/mruby/mrbgems/mruby-enum-chain/mrblib/chain.rb +149 -0
  334. data/ext/enclave/mruby/mrbgems/mruby-enum-chain/test/enum_chain.rb +108 -0
  335. data/ext/enclave/mruby/mrbgems/mruby-enum-ext/README.md +487 -0
  336. data/ext/enclave/mruby/mrbgems/mruby-enum-ext/mrbgem.rake +5 -0
  337. data/ext/enclave/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb +938 -0
  338. data/ext/enclave/mruby/mrbgems/mruby-enum-ext/test/enum.rb +223 -0
  339. data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/README.md +91 -0
  340. data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake +7 -0
  341. data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb +363 -0
  342. data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb +59 -0
  343. data/ext/enclave/mruby/mrbgems/mruby-enumerator/README.md +89 -0
  344. data/ext/enclave/mruby/mrbgems/mruby-enumerator/mrbgem.rake +6 -0
  345. data/ext/enclave/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb +861 -0
  346. data/ext/enclave/mruby/mrbgems/mruby-enumerator/test/enumerator.rb +664 -0
  347. data/ext/enclave/mruby/mrbgems/mruby-errno/README.md +83 -0
  348. data/ext/enclave/mruby/mrbgems/mruby-errno/mrbgem.rake +5 -0
  349. data/ext/enclave/mruby/mrbgems/mruby-errno/mrblib/errno.rb +50 -0
  350. data/ext/enclave/mruby/mrbgems/mruby-errno/src/errno.c +335 -0
  351. data/ext/enclave/mruby/mrbgems/mruby-errno/src/gen.rb +18 -0
  352. data/ext/enclave/mruby/mrbgems/mruby-errno/src/known_errors.def +156 -0
  353. data/ext/enclave/mruby/mrbgems/mruby-errno/src/known_errors_def.cstub +780 -0
  354. data/ext/enclave/mruby/mrbgems/mruby-errno/test/errno.rb +57 -0
  355. data/ext/enclave/mruby/mrbgems/mruby-error/README.md +103 -0
  356. data/ext/enclave/mruby/mrbgems/mruby-error/mrbgem.rake +5 -0
  357. data/ext/enclave/mruby/mrbgems/mruby-error/src/exception.c +143 -0
  358. data/ext/enclave/mruby/mrbgems/mruby-error/test/exception.c +60 -0
  359. data/ext/enclave/mruby/mrbgems/mruby-error/test/exception.rb +55 -0
  360. data/ext/enclave/mruby/mrbgems/mruby-eval/README.md +26 -0
  361. data/ext/enclave/mruby/mrbgems/mruby-eval/mrbgem.rake +10 -0
  362. data/ext/enclave/mruby/mrbgems/mruby-eval/src/eval.c +437 -0
  363. data/ext/enclave/mruby/mrbgems/mruby-eval/test/binding.rb +81 -0
  364. data/ext/enclave/mruby/mrbgems/mruby-eval/test/eval.rb +185 -0
  365. data/ext/enclave/mruby/mrbgems/mruby-exit/mrbgem.rake +5 -0
  366. data/ext/enclave/mruby/mrbgems/mruby-exit/src/mruby_exit.c +83 -0
  367. data/ext/enclave/mruby/mrbgems/mruby-fiber/mrbgem.rake +5 -0
  368. data/ext/enclave/mruby/mrbgems/mruby-fiber/src/fiber.c +575 -0
  369. data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fiber.rb +210 -0
  370. data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fiber2.rb +155 -0
  371. data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fibertest.c +87 -0
  372. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/README.md +392 -0
  373. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/mrbgem.rake +6 -0
  374. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb +408 -0
  375. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/src/hash_ext.c +392 -0
  376. data/ext/enclave/mruby/mrbgems/mruby-hash-ext/test/hash.rb +317 -0
  377. data/ext/enclave/mruby/mrbgems/mruby-io/README.md +198 -0
  378. data/ext/enclave/mruby/mrbgems/mruby-io/include/io_hal.h +451 -0
  379. data/ext/enclave/mruby/mrbgems/mruby-io/include/mruby/io.h +76 -0
  380. data/ext/enclave/mruby/mrbgems/mruby-io/mrbgem.rake +34 -0
  381. data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/file.rb +109 -0
  382. data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/file_constants.rb +24 -0
  383. data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/io.rb +303 -0
  384. data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/kernel.rb +175 -0
  385. data/ext/enclave/mruby/mrbgems/mruby-io/src/file.c +1192 -0
  386. data/ext/enclave/mruby/mrbgems/mruby-io/src/file_test.c +403 -0
  387. data/ext/enclave/mruby/mrbgems/mruby-io/src/io.c +2260 -0
  388. data/ext/enclave/mruby/mrbgems/mruby-io/src/mruby_io_gem.c +21 -0
  389. data/ext/enclave/mruby/mrbgems/mruby-io/test/file.rb +415 -0
  390. data/ext/enclave/mruby/mrbgems/mruby-io/test/file_test.rb +112 -0
  391. data/ext/enclave/mruby/mrbgems/mruby-io/test/io.rb +668 -0
  392. data/ext/enclave/mruby/mrbgems/mruby-io/test/mruby_io_test.c +293 -0
  393. data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/README.md +165 -0
  394. data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake +5 -0
  395. data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/src/kernel.c +316 -0
  396. data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb +134 -0
  397. data/ext/enclave/mruby/mrbgems/mruby-math/README.md +77 -0
  398. data/ext/enclave/mruby/mrbgems/mruby-math/mrbgem.rake +5 -0
  399. data/ext/enclave/mruby/mrbgems/mruby-math/src/math.c +753 -0
  400. data/ext/enclave/mruby/mrbgems/mruby-math/test/math.rb +201 -0
  401. data/ext/enclave/mruby/mrbgems/mruby-metaprog/README.md +123 -0
  402. data/ext/enclave/mruby/mrbgems/mruby-metaprog/mrbgem.rake +5 -0
  403. data/ext/enclave/mruby/mrbgems/mruby-metaprog/src/metaprog.c +739 -0
  404. data/ext/enclave/mruby/mrbgems/mruby-metaprog/test/metaprog.rb +465 -0
  405. data/ext/enclave/mruby/mrbgems/mruby-method/README.md +66 -0
  406. data/ext/enclave/mruby/mrbgems/mruby-method/mrbgem.rake +7 -0
  407. data/ext/enclave/mruby/mrbgems/mruby-method/mrblib/method.rb +73 -0
  408. data/ext/enclave/mruby/mrbgems/mruby-method/src/method.c +890 -0
  409. data/ext/enclave/mruby/mrbgems/mruby-method/test/method.rb +514 -0
  410. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/README.md +78 -0
  411. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake +5 -0
  412. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb +125 -0
  413. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c +527 -0
  414. data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb +137 -0
  415. data/ext/enclave/mruby/mrbgems/mruby-object-ext/README.md +144 -0
  416. data/ext/enclave/mruby/mrbgems/mruby-object-ext/mrbgem.rake +5 -0
  417. data/ext/enclave/mruby/mrbgems/mruby-object-ext/mrblib/object.rb +33 -0
  418. data/ext/enclave/mruby/mrbgems/mruby-object-ext/src/object.c +128 -0
  419. data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/nil.rb +16 -0
  420. data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/object.rb +67 -0
  421. data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/object_ext.c +17 -0
  422. data/ext/enclave/mruby/mrbgems/mruby-objectspace/README.md +59 -0
  423. data/ext/enclave/mruby/mrbgems/mruby-objectspace/mrbgem.rake +5 -0
  424. data/ext/enclave/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c +188 -0
  425. data/ext/enclave/mruby/mrbgems/mruby-objectspace/test/objectspace.rb +60 -0
  426. data/ext/enclave/mruby/mrbgems/mruby-os-memsize/README.md +75 -0
  427. data/ext/enclave/mruby/mrbgems/mruby-os-memsize/mrbgem.rake +10 -0
  428. data/ext/enclave/mruby/mrbgems/mruby-os-memsize/src/memsize.c +271 -0
  429. data/ext/enclave/mruby/mrbgems/mruby-os-memsize/test/memsize.rb +63 -0
  430. data/ext/enclave/mruby/mrbgems/mruby-pack/README.md +140 -0
  431. data/ext/enclave/mruby/mrbgems/mruby-pack/mrbgem.rake +5 -0
  432. data/ext/enclave/mruby/mrbgems/mruby-pack/src/pack.c +2129 -0
  433. data/ext/enclave/mruby/mrbgems/mruby-pack/test/pack.rb +202 -0
  434. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/README.md +140 -0
  435. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/mrbgem.rake +10 -0
  436. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/src/proc_binding.c +76 -0
  437. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/test/proc_binding.c +14 -0
  438. data/ext/enclave/mruby/mrbgems/mruby-proc-binding/test/proc_binding.rb +22 -0
  439. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/README.md +107 -0
  440. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/mrbgem.rake +5 -0
  441. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb +130 -0
  442. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/src/proc.c +267 -0
  443. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/test/proc.c +62 -0
  444. data/ext/enclave/mruby/mrbgems/mruby-proc-ext/test/proc.rb +130 -0
  445. data/ext/enclave/mruby/mrbgems/mruby-random/README.md +272 -0
  446. data/ext/enclave/mruby/mrbgems/mruby-random/mrbgem.rake +5 -0
  447. data/ext/enclave/mruby/mrbgems/mruby-random/src/random.c +608 -0
  448. data/ext/enclave/mruby/mrbgems/mruby-random/test/random.rb +151 -0
  449. data/ext/enclave/mruby/mrbgems/mruby-range-ext/README.md +93 -0
  450. data/ext/enclave/mruby/mrbgems/mruby-range-ext/mrbgem.rake +5 -0
  451. data/ext/enclave/mruby/mrbgems/mruby-range-ext/mrblib/range.rb +155 -0
  452. data/ext/enclave/mruby/mrbgems/mruby-range-ext/src/range.c +236 -0
  453. data/ext/enclave/mruby/mrbgems/mruby-range-ext/test/range.rb +211 -0
  454. data/ext/enclave/mruby/mrbgems/mruby-rational/README.md +61 -0
  455. data/ext/enclave/mruby/mrbgems/mruby-rational/mrbgem.rake +7 -0
  456. data/ext/enclave/mruby/mrbgems/mruby-rational/mrblib/rational.rb +66 -0
  457. data/ext/enclave/mruby/mrbgems/mruby-rational/src/rational.c +1269 -0
  458. data/ext/enclave/mruby/mrbgems/mruby-rational/test/rational.rb +316 -0
  459. data/ext/enclave/mruby/mrbgems/mruby-set/LICENSE +24 -0
  460. data/ext/enclave/mruby/mrbgems/mruby-set/README.md +260 -0
  461. data/ext/enclave/mruby/mrbgems/mruby-set/mrbgem.rake +9 -0
  462. data/ext/enclave/mruby/mrbgems/mruby-set/mrblib/set.rb +325 -0
  463. data/ext/enclave/mruby/mrbgems/mruby-set/mruby-set.gem +6 -0
  464. data/ext/enclave/mruby/mrbgems/mruby-set/src/set.c +1535 -0
  465. data/ext/enclave/mruby/mrbgems/mruby-set/test/set.rb +764 -0
  466. data/ext/enclave/mruby/mrbgems/mruby-sleep/README.md +29 -0
  467. data/ext/enclave/mruby/mrbgems/mruby-sleep/example/sleep.rb +2 -0
  468. data/ext/enclave/mruby/mrbgems/mruby-sleep/mrbgem.rake +5 -0
  469. data/ext/enclave/mruby/mrbgems/mruby-sleep/src/sleep.c +187 -0
  470. data/ext/enclave/mruby/mrbgems/mruby-sleep/test/sleep_test.rb +29 -0
  471. data/ext/enclave/mruby/mrbgems/mruby-socket/README.md +56 -0
  472. data/ext/enclave/mruby/mrbgems/mruby-socket/include/socket_hal.h +83 -0
  473. data/ext/enclave/mruby/mrbgems/mruby-socket/mrbgem.rake +37 -0
  474. data/ext/enclave/mruby/mrbgems/mruby-socket/mrblib/socket.rb +1131 -0
  475. data/ext/enclave/mruby/mrbgems/mruby-socket/src/const.cstub +480 -0
  476. data/ext/enclave/mruby/mrbgems/mruby-socket/src/const.def +172 -0
  477. data/ext/enclave/mruby/mrbgems/mruby-socket/src/gen.rb +17 -0
  478. data/ext/enclave/mruby/mrbgems/mruby-socket/src/socket.c +1374 -0
  479. data/ext/enclave/mruby/mrbgems/mruby-socket/test/addrinfo.rb +91 -0
  480. data/ext/enclave/mruby/mrbgems/mruby-socket/test/basicsocket.rb +17 -0
  481. data/ext/enclave/mruby/mrbgems/mruby-socket/test/ipsocket.rb +44 -0
  482. data/ext/enclave/mruby/mrbgems/mruby-socket/test/socket.rb +38 -0
  483. data/ext/enclave/mruby/mrbgems/mruby-socket/test/sockettest.c +84 -0
  484. data/ext/enclave/mruby/mrbgems/mruby-socket/test/tcpsocket.rb +4 -0
  485. data/ext/enclave/mruby/mrbgems/mruby-socket/test/udpsocket.rb +16 -0
  486. data/ext/enclave/mruby/mrbgems/mruby-socket/test/unix.rb +130 -0
  487. data/ext/enclave/mruby/mrbgems/mruby-sprintf/README.md +235 -0
  488. data/ext/enclave/mruby/mrbgems/mruby-sprintf/mrbgem.rake +5 -0
  489. data/ext/enclave/mruby/mrbgems/mruby-sprintf/mrblib/string.rb +24 -0
  490. data/ext/enclave/mruby/mrbgems/mruby-sprintf/src/sprintf.c +1195 -0
  491. data/ext/enclave/mruby/mrbgems/mruby-sprintf/test/sprintf.rb +92 -0
  492. data/ext/enclave/mruby/mrbgems/mruby-strftime/README.md +140 -0
  493. data/ext/enclave/mruby/mrbgems/mruby-strftime/mrbgem.rake +7 -0
  494. data/ext/enclave/mruby/mrbgems/mruby-strftime/src/strftime.c +119 -0
  495. data/ext/enclave/mruby/mrbgems/mruby-strftime/test/strftime.rb +152 -0
  496. data/ext/enclave/mruby/mrbgems/mruby-string-ext/README.md +886 -0
  497. data/ext/enclave/mruby/mrbgems/mruby-string-ext/mrbgem.rake +5 -0
  498. data/ext/enclave/mruby/mrbgems/mruby-string-ext/mrblib/string.rb +166 -0
  499. data/ext/enclave/mruby/mrbgems/mruby-string-ext/src/string.c +2290 -0
  500. data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/numeric.rb +27 -0
  501. data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/range.rb +26 -0
  502. data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/string.rb +765 -0
  503. data/ext/enclave/mruby/mrbgems/mruby-struct/README.md +105 -0
  504. data/ext/enclave/mruby/mrbgems/mruby-struct/mrbgem.rake +5 -0
  505. data/ext/enclave/mruby/mrbgems/mruby-struct/mrblib/struct.rb +69 -0
  506. data/ext/enclave/mruby/mrbgems/mruby-struct/src/struct.c +812 -0
  507. data/ext/enclave/mruby/mrbgems/mruby-struct/test/struct.rb +303 -0
  508. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/README.md +50 -0
  509. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake +5 -0
  510. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb +72 -0
  511. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/src/symbol.c +79 -0
  512. data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb +55 -0
  513. data/ext/enclave/mruby/mrbgems/mruby-task/README.md +770 -0
  514. data/ext/enclave/mruby/mrbgems/mruby-task/examples/inspection.rb +65 -0
  515. data/ext/enclave/mruby/mrbgems/mruby-task/examples/priority.rb +41 -0
  516. data/ext/enclave/mruby/mrbgems/mruby-task/examples/producer_consumer.rb +58 -0
  517. data/ext/enclave/mruby/mrbgems/mruby-task/examples/simple.rb +27 -0
  518. data/ext/enclave/mruby/mrbgems/mruby-task/examples/statistics.rb +59 -0
  519. data/ext/enclave/mruby/mrbgems/mruby-task/examples/suspend_resume.rb +47 -0
  520. data/ext/enclave/mruby/mrbgems/mruby-task/examples/task_pass.rb +21 -0
  521. data/ext/enclave/mruby/mrbgems/mruby-task/include/task.h +143 -0
  522. data/ext/enclave/mruby/mrbgems/mruby-task/include/task_hal.h +162 -0
  523. data/ext/enclave/mruby/mrbgems/mruby-task/mrbgem.rake +36 -0
  524. data/ext/enclave/mruby/mrbgems/mruby-task/src/task.c +1573 -0
  525. data/ext/enclave/mruby/mrbgems/mruby-task/test/task.rb +185 -0
  526. data/ext/enclave/mruby/mrbgems/mruby-test/README.md +7 -0
  527. data/ext/enclave/mruby/mrbgems/mruby-test/driver.c +315 -0
  528. data/ext/enclave/mruby/mrbgems/mruby-test/mrbgem.rake +173 -0
  529. data/ext/enclave/mruby/mrbgems/mruby-test/vformat.c +151 -0
  530. data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/mrbgem.rake +5 -0
  531. data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/test/inline.c +92 -0
  532. data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/test/inline.rb +118 -0
  533. data/ext/enclave/mruby/mrbgems/mruby-time/README.md +102 -0
  534. data/ext/enclave/mruby/mrbgems/mruby-time/include/mruby/time.h +27 -0
  535. data/ext/enclave/mruby/mrbgems/mruby-time/mrbgem.rake +5 -0
  536. data/ext/enclave/mruby/mrbgems/mruby-time/src/time.c +1739 -0
  537. data/ext/enclave/mruby/mrbgems/mruby-time/test/time.rb +313 -0
  538. data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/README.md +32 -0
  539. data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake +5 -0
  540. data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb +24 -0
  541. data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb +23 -0
  542. data/ext/enclave/mruby/mrbgems/stdlib-ext.gembox +21 -0
  543. data/ext/enclave/mruby/mrbgems/stdlib-io.gembox +15 -0
  544. data/ext/enclave/mruby/mrbgems/stdlib.gembox +63 -0
  545. data/ext/enclave/mruby/mrblib/10error.rb +23 -0
  546. data/ext/enclave/mruby/mrblib/array.rb +102 -0
  547. data/ext/enclave/mruby/mrblib/compar.rb +102 -0
  548. data/ext/enclave/mruby/mrblib/enum.rb +358 -0
  549. data/ext/enclave/mruby/mrblib/hash.rb +276 -0
  550. data/ext/enclave/mruby/mrblib/kernel.rb +45 -0
  551. data/ext/enclave/mruby/mrblib/numeric.rb +160 -0
  552. data/ext/enclave/mruby/mrblib/range.rb +98 -0
  553. data/ext/enclave/mruby/mrblib/string.rb +173 -0
  554. data/ext/enclave/mruby/mrblib/symbol.rb +8 -0
  555. data/ext/enclave/mruby/oss-fuzz/mruby_fuzzer.c +18 -0
  556. data/ext/enclave/mruby/oss-fuzz/proto_to_ruby.h +55 -0
  557. data/ext/enclave/mruby/src/allocf.c +37 -0
  558. data/ext/enclave/mruby/src/array.c +2302 -0
  559. data/ext/enclave/mruby/src/backtrace.c +294 -0
  560. data/ext/enclave/mruby/src/cdump.c +498 -0
  561. data/ext/enclave/mruby/src/class.c +4394 -0
  562. data/ext/enclave/mruby/src/codedump.c +693 -0
  563. data/ext/enclave/mruby/src/debug.c +290 -0
  564. data/ext/enclave/mruby/src/dump.c +998 -0
  565. data/ext/enclave/mruby/src/enum.c +30 -0
  566. data/ext/enclave/mruby/src/error.c +937 -0
  567. data/ext/enclave/mruby/src/etc.c +421 -0
  568. data/ext/enclave/mruby/src/fmt_fp.c +372 -0
  569. data/ext/enclave/mruby/src/gc.c +1610 -0
  570. data/ext/enclave/mruby/src/hash.c +2355 -0
  571. data/ext/enclave/mruby/src/init.c +50 -0
  572. data/ext/enclave/mruby/src/kernel.c +718 -0
  573. data/ext/enclave/mruby/src/load.c +760 -0
  574. data/ext/enclave/mruby/src/mempool.c +225 -0
  575. data/ext/enclave/mruby/src/numeric.c +2420 -0
  576. data/ext/enclave/mruby/src/numops.c +112 -0
  577. data/ext/enclave/mruby/src/object.c +883 -0
  578. data/ext/enclave/mruby/src/print.c +136 -0
  579. data/ext/enclave/mruby/src/proc.c +572 -0
  580. data/ext/enclave/mruby/src/range.c +597 -0
  581. data/ext/enclave/mruby/src/readfloat.c +228 -0
  582. data/ext/enclave/mruby/src/readint.c +27 -0
  583. data/ext/enclave/mruby/src/readnum.c +43 -0
  584. data/ext/enclave/mruby/src/state.c +247 -0
  585. data/ext/enclave/mruby/src/string.c +3577 -0
  586. data/ext/enclave/mruby/src/symbol.c +1023 -0
  587. data/ext/enclave/mruby/src/value_array.h +28 -0
  588. data/ext/enclave/mruby/src/variable.c +1475 -0
  589. data/ext/enclave/mruby/src/version.c +17 -0
  590. data/ext/enclave/mruby/src/vm.c +3696 -0
  591. data/ext/enclave/mruby/tasks/amalgam.rake +34 -0
  592. data/ext/enclave/mruby/tasks/benchmark.rake +93 -0
  593. data/ext/enclave/mruby/tasks/bin.rake +23 -0
  594. data/ext/enclave/mruby/tasks/core.rake +12 -0
  595. data/ext/enclave/mruby/tasks/doc.rake +118 -0
  596. data/ext/enclave/mruby/tasks/install.rake +40 -0
  597. data/ext/enclave/mruby/tasks/libmruby.rake +90 -0
  598. data/ext/enclave/mruby/tasks/mrbgems.rake +152 -0
  599. data/ext/enclave/mruby/tasks/mrblib.rake +29 -0
  600. data/ext/enclave/mruby/tasks/presym.rake +57 -0
  601. data/ext/enclave/mruby/tasks/test.rake +84 -0
  602. data/ext/enclave/mruby/tasks/toolchains/android.rake +228 -0
  603. data/ext/enclave/mruby/tasks/toolchains/clang.rake +8 -0
  604. data/ext/enclave/mruby/tasks/toolchains/emscripten.rake +57 -0
  605. data/ext/enclave/mruby/tasks/toolchains/gcc.rake +74 -0
  606. data/ext/enclave/mruby/tasks/toolchains/openwrt.rake +32 -0
  607. data/ext/enclave/mruby/tasks/toolchains/visualcpp.rake +48 -0
  608. data/ext/enclave/mruby/test/assert.rb +404 -0
  609. data/ext/enclave/mruby/test/bintest.rb +55 -0
  610. data/ext/enclave/mruby/test/t/argumenterror.rb +37 -0
  611. data/ext/enclave/mruby/test/t/array.rb +478 -0
  612. data/ext/enclave/mruby/test/t/basicobject.rb +10 -0
  613. data/ext/enclave/mruby/test/t/bs_block.rb +621 -0
  614. data/ext/enclave/mruby/test/t/bs_literal.rb +38 -0
  615. data/ext/enclave/mruby/test/t/class.rb +505 -0
  616. data/ext/enclave/mruby/test/t/codegen.rb +196 -0
  617. data/ext/enclave/mruby/test/t/comparable.rb +79 -0
  618. data/ext/enclave/mruby/test/t/ensure.rb +36 -0
  619. data/ext/enclave/mruby/test/t/enumerable.rb +134 -0
  620. data/ext/enclave/mruby/test/t/exception.rb +425 -0
  621. data/ext/enclave/mruby/test/t/false.rb +31 -0
  622. data/ext/enclave/mruby/test/t/float.rb +296 -0
  623. data/ext/enclave/mruby/test/t/gc.rb +45 -0
  624. data/ext/enclave/mruby/test/t/hash.rb +976 -0
  625. data/ext/enclave/mruby/test/t/indexerror.rb +6 -0
  626. data/ext/enclave/mruby/test/t/integer.rb +247 -0
  627. data/ext/enclave/mruby/test/t/iterations.rb +61 -0
  628. data/ext/enclave/mruby/test/t/kernel.rb +462 -0
  629. data/ext/enclave/mruby/test/t/lang.rb +74 -0
  630. data/ext/enclave/mruby/test/t/literals.rb +386 -0
  631. data/ext/enclave/mruby/test/t/localjumperror.rb +13 -0
  632. data/ext/enclave/mruby/test/t/methods.rb +138 -0
  633. data/ext/enclave/mruby/test/t/module.rb +931 -0
  634. data/ext/enclave/mruby/test/t/nameerror.rb +28 -0
  635. data/ext/enclave/mruby/test/t/nil.rb +39 -0
  636. data/ext/enclave/mruby/test/t/nomethoderror.rb +22 -0
  637. data/ext/enclave/mruby/test/t/numeric.rb +114 -0
  638. data/ext/enclave/mruby/test/t/object.rb +10 -0
  639. data/ext/enclave/mruby/test/t/proc.rb +198 -0
  640. data/ext/enclave/mruby/test/t/range.rb +194 -0
  641. data/ext/enclave/mruby/test/t/rangeerror.rb +6 -0
  642. data/ext/enclave/mruby/test/t/regexperror.rb +4 -0
  643. data/ext/enclave/mruby/test/t/runtimeerror.rb +6 -0
  644. data/ext/enclave/mruby/test/t/standarderror.rb +6 -0
  645. data/ext/enclave/mruby/test/t/string.rb +981 -0
  646. data/ext/enclave/mruby/test/t/superclass.rb +46 -0
  647. data/ext/enclave/mruby/test/t/symbol.rb +30 -0
  648. data/ext/enclave/mruby/test/t/syntax.rb +1296 -0
  649. data/ext/enclave/mruby/test/t/true.rb +31 -0
  650. data/ext/enclave/mruby/test/t/typeerror.rb +6 -0
  651. data/ext/enclave/mruby/test/t/unicode.rb +39 -0
  652. data/ext/enclave/mruby/test/t/vformat.rb +57 -0
  653. data/ext/enclave/mruby/tools/lrama/LEGAL.md +12 -0
  654. data/ext/enclave/mruby/tools/lrama/MIT +21 -0
  655. data/ext/enclave/mruby/tools/lrama/NEWS.md +696 -0
  656. data/ext/enclave/mruby/tools/lrama/exe/lrama +7 -0
  657. data/ext/enclave/mruby/tools/lrama/lib/lrama/bitmap.rb +34 -0
  658. data/ext/enclave/mruby/tools/lrama/lib/lrama/command.rb +68 -0
  659. data/ext/enclave/mruby/tools/lrama/lib/lrama/context.rb +499 -0
  660. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/derivation.rb +66 -0
  661. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/example.rb +129 -0
  662. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/path.rb +29 -0
  663. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/production_path.rb +19 -0
  664. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/start_path.rb +23 -0
  665. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/state_item.rb +8 -0
  666. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/transition_path.rb +19 -0
  667. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/triple.rb +23 -0
  668. data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples.rb +298 -0
  669. data/ext/enclave/mruby/tools/lrama/lib/lrama/diagnostics.rb +36 -0
  670. data/ext/enclave/mruby/tools/lrama/lib/lrama/digraph.rb +83 -0
  671. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/auxiliary.rb +9 -0
  672. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/binding.rb +67 -0
  673. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/destructor_code.rb +42 -0
  674. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/initial_action_code.rb +36 -0
  675. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/no_reference_code.rb +30 -0
  676. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/printer_code.rb +42 -0
  677. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/rule_action.rb +92 -0
  678. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code.rb +53 -0
  679. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/counter.rb +17 -0
  680. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/destructor.rb +11 -0
  681. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/error_token.rb +11 -0
  682. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb +62 -0
  683. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb +40 -0
  684. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb +24 -0
  685. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule.rb +5 -0
  686. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/percent_code.rb +14 -0
  687. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/precedence.rb +13 -0
  688. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/printer.rb +11 -0
  689. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/reference.rb +16 -0
  690. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/rule.rb +75 -0
  691. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/rule_builder.rb +255 -0
  692. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/stdlib.y +122 -0
  693. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbol.rb +105 -0
  694. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbols/resolver.rb +301 -0
  695. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbols.rb +3 -0
  696. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/type.rb +20 -0
  697. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/union.rb +12 -0
  698. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar.rb +407 -0
  699. data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar_validator.rb +37 -0
  700. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/grammar_file.rb +40 -0
  701. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/location.rb +115 -0
  702. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/char.rb +11 -0
  703. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/ident.rb +11 -0
  704. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/instantiate_rule.rb +30 -0
  705. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/tag.rb +16 -0
  706. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/user_code.rb +83 -0
  707. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token.rb +70 -0
  708. data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer.rb +191 -0
  709. data/ext/enclave/mruby/tools/lrama/lib/lrama/logger.rb +21 -0
  710. data/ext/enclave/mruby/tools/lrama/lib/lrama/option_parser.rb +169 -0
  711. data/ext/enclave/mruby/tools/lrama/lib/lrama/options.rb +28 -0
  712. data/ext/enclave/mruby/tools/lrama/lib/lrama/output.rb +459 -0
  713. data/ext/enclave/mruby/tools/lrama/lib/lrama/parser.rb +2144 -0
  714. data/ext/enclave/mruby/tools/lrama/lib/lrama/report/duration.rb +27 -0
  715. data/ext/enclave/mruby/tools/lrama/lib/lrama/report/profile.rb +16 -0
  716. data/ext/enclave/mruby/tools/lrama/lib/lrama/report.rb +4 -0
  717. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/reduce.rb +37 -0
  718. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/reduce_reduce_conflict.rb +11 -0
  719. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/resolved_conflict.rb +31 -0
  720. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/shift.rb +15 -0
  721. data/ext/enclave/mruby/tools/lrama/lib/lrama/state/shift_reduce_conflict.rb +11 -0
  722. data/ext/enclave/mruby/tools/lrama/lib/lrama/state.rb +433 -0
  723. data/ext/enclave/mruby/tools/lrama/lib/lrama/states/item.rb +91 -0
  724. data/ext/enclave/mruby/tools/lrama/lib/lrama/states.rb +595 -0
  725. data/ext/enclave/mruby/tools/lrama/lib/lrama/states_reporter.rb +362 -0
  726. data/ext/enclave/mruby/tools/lrama/lib/lrama/trace_reporter.rb +45 -0
  727. data/ext/enclave/mruby/tools/lrama/lib/lrama/version.rb +5 -0
  728. data/ext/enclave/mruby/tools/lrama/lib/lrama.rb +22 -0
  729. data/ext/enclave/mruby/tools/lrama/template/bison/_yacc.h +71 -0
  730. data/ext/enclave/mruby/tools/lrama/template/bison/yacc.c +2068 -0
  731. data/ext/enclave/mruby/tools/lrama/template/bison/yacc.h +40 -0
  732. data/ext/enclave/sandbox_build_config.rb +15 -0
  733. data/ext/enclave/sandbox_core.c +722 -0
  734. data/ext/enclave/sandbox_core.h +87 -0
  735. data/lib/enclave/result.rb +29 -0
  736. data/lib/enclave/tool.rb +38 -0
  737. data/lib/enclave/version.rb +3 -0
  738. data/lib/enclave.rb +73 -0
  739. metadata +819 -0
@@ -0,0 +1,3577 @@
1
+ /*
2
+ ** string.c - String class
3
+ **
4
+ ** See Copyright Notice in mruby.h
5
+ */
6
+
7
+ #ifdef _MSC_VER
8
+ # define _CRT_NONSTDC_NO_DEPRECATE
9
+ # define WIN32_LEAN_AND_MEAN
10
+ #endif
11
+
12
+ #include <mruby.h>
13
+ #include <mruby/array.h>
14
+ #include <mruby/class.h>
15
+ #include <mruby/range.h>
16
+ #include <mruby/string.h>
17
+ #include <mruby/numeric.h>
18
+ #include <mruby/internal.h>
19
+ #include <mruby/presym.h>
20
+ #include <string.h>
21
+
22
+ typedef struct mrb_shared_string {
23
+ int refcnt;
24
+ mrb_int capa;
25
+ char *ptr;
26
+ } mrb_shared_string;
27
+
28
+ const char mrb_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
29
+
30
+ #define mrb_obj_alloc_string(mrb) MRB_OBJ_ALLOC((mrb), MRB_TT_STRING, (mrb)->string_class)
31
+
32
+ #ifndef MRB_STR_LENGTH_MAX
33
+ #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
34
+ #define MRB_STR_LENGTH_MAX 0
35
+ #else
36
+ #define MRB_STR_LENGTH_MAX 1048576
37
+ #endif
38
+ #endif
39
+
40
+ static void
41
+ str_check_length(mrb_state *mrb, mrb_int len)
42
+ {
43
+ if (len < 0 || len == MRB_INT_MAX) {
44
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "negative (or overflowed) string size");
45
+ }
46
+ #if MRB_STR_LENGTH_MAX != 0
47
+ if (len > MRB_STR_LENGTH_MAX-1) {
48
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "string too long (len=%i max=" MRB_STRINGIZE(MRB_STR_LENGTH_MAX) ")", len);
49
+ }
50
+ #endif
51
+ }
52
+
53
+ mrb_bool
54
+ mrb_strcasecmp_p(const char *s1, mrb_int len1, const char *s2, mrb_int len2)
55
+ {
56
+ if (len1 != len2) return FALSE;
57
+
58
+ const char *e1 = s1 + len1;
59
+ while (s1 < e1) {
60
+ if (*s1 != *s2 && TOUPPER(*s1) != TOUPPER(*s2)) return FALSE;
61
+ s1++;
62
+ s2++;
63
+ }
64
+ return TRUE;
65
+ }
66
+
67
+ static struct RString*
68
+ str_init_normal_capa(mrb_state *mrb, struct RString *s,
69
+ const char *p, mrb_int len, mrb_int capa)
70
+ {
71
+ str_check_length(mrb, capa);
72
+ char *dst = (char*)mrb_malloc(mrb, capa + 1);
73
+ if (p) memcpy(dst, p, len);
74
+ dst[len] = '\0';
75
+ s->as.heap.ptr = dst;
76
+ s->as.heap.len = len;
77
+ s->as.heap.aux.capa = capa;
78
+ RSTR_SET_TYPE(s, NORMAL);
79
+ return s;
80
+ }
81
+
82
+ static struct RString*
83
+ str_init_normal(mrb_state *mrb, struct RString *s, const char *p, mrb_int len)
84
+ {
85
+ return str_init_normal_capa(mrb, s, p, len, len);
86
+ }
87
+
88
+ static struct RString*
89
+ str_init_embed(struct RString *s, const char *p, mrb_int len)
90
+ {
91
+ mrb_assert(len >= 0);
92
+ if (p) memcpy(RSTR_EMBED_PTR(s), p, len);
93
+ RSTR_EMBED_PTR(s)[len] = '\0';
94
+ RSTR_SET_TYPE(s, EMBED);
95
+ RSTR_SET_EMBED_LEN(s, len);
96
+ return s;
97
+ }
98
+
99
+ static struct RString*
100
+ str_init_nofree(struct RString *s, const char *p, mrb_int len)
101
+ {
102
+ s->as.heap.ptr = (char*)p;
103
+ s->as.heap.len = len;
104
+ s->as.heap.aux.capa = 0; /* nofree */
105
+ RSTR_SET_TYPE(s, NOFREE);
106
+ return s;
107
+ }
108
+
109
+ static struct RString*
110
+ str_init_shared(mrb_state *mrb, const struct RString *orig, struct RString *s, mrb_shared_string *shared)
111
+ {
112
+ if (shared) {
113
+ shared->refcnt++;
114
+ }
115
+ else {
116
+ shared = (mrb_shared_string*)mrb_malloc(mrb, sizeof(mrb_shared_string));
117
+ shared->refcnt = 1;
118
+ shared->ptr = orig->as.heap.ptr;
119
+ shared->capa = orig->as.heap.aux.capa;
120
+ }
121
+ s->as.heap.ptr = orig->as.heap.ptr;
122
+ s->as.heap.len = orig->as.heap.len;
123
+ s->as.heap.aux.shared = shared;
124
+ RSTR_SET_TYPE(s, SHARED);
125
+ return s;
126
+ }
127
+
128
+ static struct RString*
129
+ str_init_fshared(const struct RString *orig, struct RString *s, struct RString *fshared)
130
+ {
131
+ s->as.heap.ptr = orig->as.heap.ptr;
132
+ s->as.heap.len = orig->as.heap.len;
133
+ s->as.heap.aux.fshared = fshared;
134
+ RSTR_SET_TYPE(s, FSHARED);
135
+ return s;
136
+ }
137
+
138
+ static struct RString*
139
+ str_init_modifiable(mrb_state *mrb, struct RString *s, const char *p, mrb_int len)
140
+ {
141
+ if (RSTR_EMBEDDABLE_P(len)) {
142
+ return str_init_embed(s, p, len);
143
+ }
144
+ return str_init_normal(mrb, s, p, len);
145
+ }
146
+
147
+ static struct RString*
148
+ str_new_static(mrb_state *mrb, const char *p, mrb_int len)
149
+ {
150
+ if (RSTR_EMBEDDABLE_P(len)) {
151
+ return str_init_embed(mrb_obj_alloc_string(mrb), p, len);
152
+ }
153
+ return str_init_nofree(mrb_obj_alloc_string(mrb), p, len);
154
+ }
155
+
156
+ static struct RString*
157
+ str_new(mrb_state *mrb, const char *p, mrb_int len)
158
+ {
159
+ str_check_length(mrb, len);
160
+ if (RSTR_EMBEDDABLE_P(len)) {
161
+ return str_init_embed(mrb_obj_alloc_string(mrb), p, len);
162
+ }
163
+ if (p && mrb_ro_data_p(p)) {
164
+ return str_init_nofree(mrb_obj_alloc_string(mrb), p, len);
165
+ }
166
+ return str_init_normal(mrb, mrb_obj_alloc_string(mrb), p, len);
167
+ }
168
+
169
+ /*
170
+ * @param mrb The mruby state.
171
+ * @param capa The desired capacity of the new string.
172
+ * @return A new mruby string with the specified capacity.
173
+ *
174
+ * Creates a new mruby string with a given initial capacity.
175
+ * The string is initially empty.
176
+ */
177
+ MRB_API mrb_value
178
+ mrb_str_new_capa(mrb_state *mrb, mrb_int capa)
179
+ {
180
+ struct RString *s = mrb_obj_alloc_string(mrb);
181
+
182
+ if (RSTR_EMBEDDABLE_P(capa)) {
183
+ s = str_init_embed(s, NULL, 0);
184
+ }
185
+ else {
186
+ s = str_init_normal_capa(mrb, s, NULL, 0, capa);
187
+ }
188
+ return mrb_obj_value(s);
189
+ }
190
+
191
+ static void
192
+ resize_capa(mrb_state *mrb, struct RString *s, mrb_int capacity)
193
+ {
194
+ if (RSTR_EMBED_P(s)) {
195
+ if (!RSTR_EMBEDDABLE_P(capacity)) {
196
+ str_init_normal_capa(mrb, s, RSTR_EMBED_PTR(s), RSTR_EMBED_LEN(s), capacity);
197
+ }
198
+ }
199
+ else {
200
+ str_check_length(mrb, capacity);
201
+ s->as.heap.ptr = (char*)mrb_realloc(mrb, RSTR_PTR(s), capacity+1);
202
+ s->as.heap.aux.capa = (mrb_ssize)capacity;
203
+ }
204
+ }
205
+
206
+ /*
207
+ * @param mrb The mruby state.
208
+ * @param p A pointer to the C string to copy.
209
+ * @param len The length of the C string.
210
+ * @return A new mruby string containing the copied C string.
211
+ *
212
+ * Creates a new mruby string from a C string and a specified length.
213
+ * If `p` is NULL, an empty string is created.
214
+ */
215
+ MRB_API mrb_value
216
+ mrb_str_new(mrb_state *mrb, const char *p, mrb_int len)
217
+ {
218
+ return mrb_obj_value(str_new(mrb, p, len));
219
+ }
220
+
221
+ /*
222
+ * @param mrb The mruby state.
223
+ * @param p A pointer to the null-terminated C string to copy.
224
+ * @return A new mruby string containing the copied C string.
225
+ *
226
+ * Creates a new mruby string from a null-terminated C string.
227
+ * If `p` is NULL, an empty string is created.
228
+ */
229
+ MRB_API mrb_value
230
+ mrb_str_new_cstr(mrb_state *mrb, const char *p)
231
+ {
232
+ struct RString *s;
233
+ mrb_int len;
234
+
235
+ if (p) {
236
+ len = strlen(p);
237
+ }
238
+ else {
239
+ len = 0;
240
+ }
241
+
242
+ s = str_new(mrb, p, len);
243
+
244
+ return mrb_obj_value(s);
245
+ }
246
+
247
+ /*
248
+ * @param mrb The mruby state.
249
+ * @param p A pointer to the static C string.
250
+ * @param len The length of the static C string.
251
+ * @return A new mruby string referencing the static C string.
252
+ *
253
+ * Creates a new mruby string that directly references a static C string.
254
+ * The C string is not copied and must remain valid for the lifetime of the mruby string.
255
+ * This is typically used for string literals.
256
+ */
257
+ MRB_API mrb_value
258
+ mrb_str_new_static(mrb_state *mrb, const char *p, mrb_int len)
259
+ {
260
+ struct RString *s = str_new_static(mrb, p, len);
261
+ return mrb_obj_value(s);
262
+ }
263
+
264
+ static void
265
+ str_decref(mrb_state *mrb, mrb_shared_string *shared)
266
+ {
267
+ shared->refcnt--;
268
+ if (shared->refcnt == 0) {
269
+ mrb_free(mrb, shared->ptr);
270
+ mrb_free(mrb, shared);
271
+ }
272
+ }
273
+
274
+ static void
275
+ str_unshare_buffer(mrb_state *mrb, struct RString *s)
276
+ {
277
+ if (RSTR_SHARED_P(s)) {
278
+ mrb_shared_string *shared = s->as.heap.aux.shared;
279
+
280
+ if (shared->refcnt == 1 && s->as.heap.ptr == shared->ptr) {
281
+ s->as.heap.aux.capa = shared->capa;
282
+ s->as.heap.ptr[s->as.heap.len] = '\0';
283
+ RSTR_SET_TYPE(s, NORMAL);
284
+ mrb_free(mrb, shared);
285
+ }
286
+ else {
287
+ str_init_modifiable(mrb, s, s->as.heap.ptr, s->as.heap.len);
288
+ str_decref(mrb, shared);
289
+ }
290
+ }
291
+ else if (RSTR_NOFREE_P(s) || RSTR_FSHARED_P(s)) {
292
+ str_init_modifiable(mrb, s, s->as.heap.ptr, s->as.heap.len);
293
+ }
294
+ }
295
+
296
+ static void
297
+ check_null_byte(mrb_state *mrb, struct RString *str)
298
+ {
299
+ const char *p = RSTR_PTR(str);
300
+ if (p && memchr(p, '\0', RSTR_LEN(str))) {
301
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
302
+ }
303
+ }
304
+
305
+ void
306
+ mrb_gc_free_str(mrb_state *mrb, struct RString *str)
307
+ {
308
+ if (RSTR_EMBED_P(str))
309
+ /* no code */;
310
+ else if (RSTR_SHARED_P(str))
311
+ str_decref(mrb, str->as.heap.aux.shared);
312
+ else if (!RSTR_NOFREE_P(str) && !RSTR_FSHARED_P(str))
313
+ mrb_free(mrb, str->as.heap.ptr);
314
+ }
315
+
316
+ #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \
317
+ defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || \
318
+ defined(__powerpc64__) || defined(__POWERPC__) || defined(__aarch64__) || \
319
+ defined(__mc68020__)
320
+ # define ALIGNED_WORD_ACCESS 0
321
+ #else
322
+ # define ALIGNED_WORD_ACCESS 1
323
+ #endif
324
+
325
+ #ifdef MRB_64BIT
326
+ #define bitint uint64_t
327
+ #define MASK01 0x0101010101010101ull
328
+ #else
329
+ #define bitint uint32_t
330
+ #define MASK01 0x01010101ul
331
+ #endif
332
+
333
+ /*
334
+ * Encode a Unicode codepoint to UTF-8 bytes.
335
+ * buf must have at least 4 bytes of space.
336
+ * Returns the number of bytes written (1-4), or 0 for invalid codepoint.
337
+ */
338
+ mrb_int
339
+ mrb_utf8_to_buf(char *buf, uint32_t cp)
340
+ {
341
+ if (cp < 0x80) {
342
+ buf[0] = (char)cp;
343
+ return 1;
344
+ }
345
+ else if (cp < 0x800) {
346
+ buf[0] = (char)(0xC0 | (cp >> 6));
347
+ buf[1] = (char)(0x80 | (cp & 0x3F));
348
+ return 2;
349
+ }
350
+ else if (cp < 0x10000) {
351
+ buf[0] = (char)(0xE0 | (cp >> 12));
352
+ buf[1] = (char)(0x80 | ((cp >> 6) & 0x3F));
353
+ buf[2] = (char)(0x80 | (cp & 0x3F));
354
+ return 3;
355
+ }
356
+ else if (cp <= 0x10FFFF) {
357
+ buf[0] = (char)(0xF0 | (cp >> 18));
358
+ buf[1] = (char)(0x80 | ((cp >> 12) & 0x3F));
359
+ buf[2] = (char)(0x80 | ((cp >> 6) & 0x3F));
360
+ buf[3] = (char)(0x80 | (cp & 0x3F));
361
+ return 4;
362
+ }
363
+ return 0; /* invalid codepoint */
364
+ }
365
+
366
+ #ifdef MRB_UTF8_STRING
367
+
368
+ #define NOASCII(c) ((c) & 0x80)
369
+
370
+ #ifdef SIMPLE_SEARCH_NONASCII
371
+ /* the naive implementation. define SIMPLE_SEARCH_NONASCII, */
372
+ /* if you need it for any constraint (e.g. code size). */
373
+ static const char*
374
+ search_nonascii(const char* p, const char *e)
375
+ {
376
+ for (; p < e; ++p) {
377
+ if (NOASCII(*p)) return p;
378
+ }
379
+ return e;
380
+ }
381
+
382
+ #elif defined(__SSE2__)
383
+ # include <emmintrin.h>
384
+
385
+ static inline const char *
386
+ search_nonascii(const char *p, const char *e)
387
+ {
388
+ if (sizeof(__m128i) < (size_t)(e - p)) {
389
+ if (!_mm_movemask_epi8(_mm_loadu_si128((__m128i const*)p))) {
390
+ const intptr_t lowbits = sizeof(__m128i) - 1;
391
+ const __m128i *s, *t;
392
+ s = (const __m128i*)(~lowbits & ((intptr_t)p + lowbits));
393
+ t = (const __m128i*)(~lowbits & (intptr_t)e);
394
+ for (; s < t; ++s) {
395
+ if (_mm_movemask_epi8(_mm_load_si128(s))) break;
396
+ }
397
+ p = (const char *)s;
398
+ }
399
+ }
400
+ switch (e - p) {
401
+ default:
402
+ case 15: if (NOASCII(*p)) return p; ++p;
403
+ case 14: if (NOASCII(*p)) return p; ++p;
404
+ case 13: if (NOASCII(*p)) return p; ++p;
405
+ case 12: if (NOASCII(*p)) return p; ++p;
406
+ case 11: if (NOASCII(*p)) return p; ++p;
407
+ case 10: if (NOASCII(*p)) return p; ++p;
408
+ case 9: if (NOASCII(*p)) return p; ++p;
409
+ case 8: if (NOASCII(*p)) return p; ++p;
410
+ case 7: if (NOASCII(*p)) return p; ++p;
411
+ case 6: if (NOASCII(*p)) return p; ++p;
412
+ case 5: if (NOASCII(*p)) return p; ++p;
413
+ case 4: if (NOASCII(*p)) return p; ++p;
414
+ case 3: if (NOASCII(*p)) return p; ++p;
415
+ case 2: if (NOASCII(*p)) return p; ++p;
416
+ case 1: if (NOASCII(*p)) return p; ++p;
417
+ if (NOASCII(*p)) return p;
418
+ case 0: break;
419
+ }
420
+ return e;
421
+ }
422
+
423
+ #else
424
+
425
+ static const char*
426
+ search_nonascii(const char *p, const char *e)
427
+ {
428
+ ptrdiff_t byte_len = e - p;
429
+
430
+ const char *be = p + sizeof(bitint) * (byte_len / sizeof(bitint));
431
+ for (; p < be; p+=sizeof(bitint)) {
432
+ bitint t0;
433
+
434
+ memcpy(&t0, p, sizeof(bitint));
435
+ const bitint t1 = t0 & (MASK01*0x80);
436
+ if (t1) {
437
+ e = p + sizeof(bitint)-1;
438
+ byte_len = sizeof(bitint)-1;
439
+ break;
440
+ }
441
+ }
442
+
443
+ switch (byte_len % sizeof(bitint)) {
444
+ #ifdef MRB_64BIT
445
+ case 7: if (e[-7]&0x80) return e-7;
446
+ case 6: if (e[-6]&0x80) return e-6;
447
+ case 5: if (e[-5]&0x80) return e-5;
448
+ case 4: if (e[-4]&0x80) return e-4;
449
+ #endif
450
+ case 3: if (e[-3]&0x80) return e-3;
451
+ case 2: if (e[-2]&0x80) return e-2;
452
+ case 1: if (e[-1]&0x80) return e-1;
453
+ }
454
+ return e;
455
+ }
456
+
457
+ #endif /* SIMPLE_SEARCH_NONASCII */
458
+
459
+ #define utf8_islead(c) ((unsigned char)((c)&0xc0) != 0x80)
460
+
461
+ extern const char mrb_utf8len_table[];
462
+ const char mrb_utf8len_table[] = {
463
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
464
+ 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0
465
+ };
466
+
467
+ mrb_int
468
+ mrb_utf8len(const char* p, const char* e)
469
+ {
470
+ mrb_int len = mrb_utf8len_table[(unsigned char)p[0] >> 3];
471
+ if (len > e - p) return 1;
472
+ switch (len) {
473
+ case 0:
474
+ return 1;
475
+ case 4:
476
+ if (utf8_islead(p[3])) return 1;
477
+ case 3:
478
+ if (utf8_islead(p[2])) return 1;
479
+ case 2:
480
+ if (utf8_islead(p[1])) return 1;
481
+ }
482
+ return len;
483
+ }
484
+
485
+ #if defined(__GNUC__) || __has_builtin(__builtin_popcount)
486
+ # ifdef MRB_64BIT
487
+ # define popcount(x) __builtin_popcountll(x)
488
+ # else
489
+ # define popcount(x) __builtin_popcountl(x)
490
+ # endif
491
+ #else
492
+ #define POPC_SHIFT (8 * sizeof(bitint) - 8)
493
+ static inline uint32_t popcount(bitint x)
494
+ {
495
+ x = (x & (MASK01*0x55)) + ((x >> 1) & (MASK01*0x55));
496
+ x = (x & (MASK01*0x33)) + ((x >> 2) & (MASK01*0x33));
497
+ x = (x & (MASK01*0x0F)) + ((x >> 4) & (MASK01*0x0F));
498
+ return (uint32_t)((x * MASK01) >> POPC_SHIFT);
499
+ }
500
+ #endif
501
+
502
+ mrb_int
503
+ mrb_utf8_strlen(const char *str, mrb_int byte_len)
504
+ {
505
+ const char *p = str;
506
+ const char *e = str + byte_len;
507
+ mrb_int len = 0;
508
+
509
+ while (p < e) {
510
+ const char *np = search_nonascii(p, e);
511
+
512
+ len += np - p;
513
+ if (np == e) break;
514
+ p = np;
515
+ while (NOASCII(*p)) {
516
+ p += mrb_utf8len(p, e);
517
+ len++;
518
+ }
519
+ }
520
+ return len;
521
+ }
522
+
523
+ static mrb_int
524
+ utf8_strlen(mrb_value str)
525
+ {
526
+ struct RString *s = mrb_str_ptr(str);
527
+ mrb_int byte_len = RSTR_LEN(s);
528
+
529
+ if (RSTR_SINGLE_BYTE_P(s)) {
530
+ return byte_len;
531
+ }
532
+ else {
533
+ mrb_int utf8_len = mrb_utf8_strlen(RSTR_PTR(s), byte_len);
534
+ mrb_assert(utf8_len <= byte_len);
535
+ if (byte_len == utf8_len) RSTR_SET_SINGLE_BYTE_FLAG(s);
536
+ return utf8_len;
537
+ }
538
+ }
539
+
540
+ #define RSTRING_CHAR_LEN(s) utf8_strlen(s)
541
+
542
+ /* map character index to byte offset index */
543
+ static mrb_int
544
+ chars2bytes(mrb_value str, mrb_int off, mrb_int idx)
545
+ {
546
+ struct RString *s = mrb_str_ptr(str);
547
+ if (RSTR_SINGLE_BYTE_P(s) || RSTR_BINARY_P(s)) {
548
+ return idx;
549
+ }
550
+
551
+ const char *o = RSTR_PTR(s);
552
+ const char *p0 = o + off;
553
+ const char *p = p0;
554
+ const char *e = o + RSTR_LEN(s);
555
+ mrb_int i = 0;
556
+
557
+ while (p<e && i<idx) {
558
+ if ((*p & 0x80) == 0) {
559
+ const char *np = search_nonascii(p, e);
560
+ ptrdiff_t alen = np - p;
561
+ if (idx < i+alen) {
562
+ p += idx-i;
563
+ i=idx;
564
+ }
565
+ else {
566
+ p = np;
567
+ i += alen;
568
+ }
569
+ }
570
+ else {
571
+ p += mrb_utf8len(p, e);
572
+ i++;
573
+ }
574
+ }
575
+
576
+ mrb_int len = (mrb_int)(p-p0);
577
+ if (i<idx) len++;
578
+ return len;
579
+ }
580
+
581
+ /* map byte offset to character index */
582
+ static mrb_int
583
+ bytes2chars(mrb_value str, mrb_int bi)
584
+ {
585
+ struct RString *s = mrb_str_ptr(str);
586
+ if (RSTR_SINGLE_BYTE_P(s) || RSTR_BINARY_P(s)) {
587
+ return bi;
588
+ }
589
+
590
+ const char *p = RSTR_PTR(s);
591
+ const char *e = p + RSTR_LEN(s);
592
+ const char *pivot = p + bi;
593
+ mrb_int i = 0;
594
+
595
+ if (e < pivot) return -1;
596
+ while (p < pivot) {
597
+ if ((*p & 0x80) == 0) {
598
+ const char *np = search_nonascii(p, pivot);
599
+ i += np - p;
600
+ p = np;
601
+ }
602
+ else {
603
+ p += mrb_utf8len(p, e);
604
+ i++;
605
+ }
606
+ }
607
+ if (p != pivot) return -1;
608
+ return i;
609
+ }
610
+
611
+ static const char*
612
+ char_adjust(const char *ptr, const char *end)
613
+ {
614
+ ptrdiff_t len = end - ptr;
615
+ if (len < 1 || utf8_islead(ptr[0])) return ptr;
616
+ if (len > 1 && utf8_islead(ptr[1])) return ptr+1;
617
+ if (len > 2 && utf8_islead(ptr[2])) return ptr+2;
618
+ if (len > 3 && utf8_islead(ptr[3])) return ptr+3;
619
+ return ptr;
620
+ }
621
+
622
+ static const char*
623
+ char_backtrack(const char *ptr, const char *end)
624
+ {
625
+ ptrdiff_t len = end - ptr;
626
+ if (len < 1 || utf8_islead(end[-1])) return end-1;
627
+ if (len > 1 && utf8_islead(end[-2])) return end-2;
628
+ if (len > 2 && utf8_islead(end[-3])) return end-3;
629
+ if (len > 3 && utf8_islead(end[-4])) return end-4;
630
+ return end - 1;
631
+ }
632
+
633
+ static mrb_int
634
+ str_index_str_by_char(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
635
+ {
636
+ const char *ptr = RSTRING_PTR(sub);
637
+ mrb_int len = RSTRING_LEN(sub);
638
+
639
+ if (pos > 0) {
640
+ pos = chars2bytes(str, 0, pos);
641
+ }
642
+
643
+ pos = mrb_str_index(mrb, str, ptr, len, pos);
644
+
645
+ if (pos > 0) {
646
+ pos = bytes2chars(str, pos);
647
+ }
648
+ return pos;
649
+ }
650
+
651
+ #else
652
+ #define RSTRING_CHAR_LEN(s) RSTRING_LEN(s)
653
+ #define chars2bytes(s, off, ci) (ci)
654
+ #define bytes2chars(s, bi) (bi)
655
+ #define char_adjust(ptr, end) (ptr)
656
+ #define char_backtrack(ptr, end) ((end) - 1)
657
+ #define str_index_str_by_char(mrb, str, sub, pos) str_index_str((mrb), (str), (sub), (pos))
658
+ #endif
659
+
660
+ /* memsearch_swar (SWAR stands for SIMD within a register) */
661
+ /* See https://en.wikipedia.org/wiki/SWAR */
662
+ /* The function is taken from http://0x80.pl/articles/simd-strfind.html */
663
+ /* The original source code is under 2-clause BSD license; see LEGAL file. */
664
+ /* The modifications:
665
+ * port from C++ to C
666
+ * returns mrb_int
667
+ * remove alignment issue
668
+ * support bigendian CPU
669
+ * fixed potential buffer overflow
670
+ */
671
+ static inline mrb_int
672
+ memsearch_swar(const char *xs, mrb_int m, const char *ys, mrb_int n)
673
+ {
674
+ #define MASK7f (MASK01*0x7f)
675
+ #define MASK80 (MASK01*0x80)
676
+ #if defined(MRB_ENDIAN_BIG)
677
+ #ifdef MRB_64BIT
678
+ #define MASKtop 0x8000000000000000ull
679
+ #else
680
+ #define MASKtop 0x80000000ul
681
+ #endif
682
+ #else
683
+ #define MASKtop 0x80
684
+ #endif
685
+
686
+ const bitint first = MASK01 * (uint8_t)xs[0];
687
+ const bitint last = MASK01 * (uint8_t)xs[m-1];
688
+
689
+ const char *s0 = ys;
690
+ const char *s1 = ys+m-1;
691
+
692
+ const mrb_int lim = n - m - (mrb_int)sizeof(bitint);
693
+ mrb_int i;
694
+
695
+ for (i=0; i < lim; i+=sizeof(bitint)) {
696
+ bitint t0, t1;
697
+
698
+ memcpy(&t0, s0+i, sizeof(bitint));
699
+ memcpy(&t1, s1+i, sizeof(bitint));
700
+
701
+ const bitint eq = (t0 ^ first) | (t1 ^ last);
702
+ bitint zeros = ((~eq & MASK7f) + MASK01) & (~eq & MASK80);
703
+
704
+ for (size_t j = 0; zeros; j++) {
705
+ if (zeros & MASKtop) {
706
+ const mrb_int idx = i + j;
707
+ const char* p = s0 + idx + 1;
708
+ if (memcmp(p, xs + 1, m - 2) == 0) {
709
+ return idx;
710
+ }
711
+ }
712
+
713
+ #if defined(MRB_ENDIAN_BIG)
714
+ zeros <<= 8;
715
+ #else
716
+ zeros >>= 8;
717
+ #endif
718
+ }
719
+ }
720
+
721
+ if (i+m < n) {
722
+ const char *p = s0;
723
+ const char *e = ys + n;
724
+ while (p<e) {
725
+ p = (const char*)memchr(p, *xs, e - p);
726
+ if (p == NULL || (e - p) < m) break;
727
+ if (memcmp(p+1, xs+1, m-1) == 0) return (mrb_int)(p - ys);
728
+ p++;
729
+ }
730
+ }
731
+
732
+ return -1;
733
+ }
734
+
735
+ static mrb_int
736
+ mrb_memsearch(const char *x, mrb_int m, const char *y, mrb_int n)
737
+ {
738
+ if (m > n) return -1;
739
+ else if (m == n) {
740
+ return memcmp(x, y, m) == 0 ? 0 : -1;
741
+ }
742
+ else if (m < 1) {
743
+ return 0;
744
+ }
745
+ else if (m == 1) {
746
+ const char *p = (const char*)memchr(y, *x, n);
747
+
748
+ if (p) return (mrb_int)(p - y);
749
+ return -1;
750
+ }
751
+ return memsearch_swar(x, m, y, n);
752
+ }
753
+
754
+ static void
755
+ str_share(mrb_state *mrb, struct RString *orig, struct RString *s)
756
+ {
757
+ size_t len = (size_t)orig->as.heap.len;
758
+
759
+ mrb_assert(!RSTR_EMBED_P(orig));
760
+ if (RSTR_NOFREE_P(orig)) {
761
+ str_init_nofree(s, orig->as.heap.ptr, len);
762
+ }
763
+ else if (RSTR_SHARED_P(orig)) {
764
+ str_init_shared(mrb, orig, s, orig->as.heap.aux.shared);
765
+ }
766
+ else if (RSTR_FSHARED_P(orig)) {
767
+ str_init_fshared(orig, s, orig->as.heap.aux.fshared);
768
+ }
769
+ else {
770
+ if (orig->as.heap.aux.capa > orig->as.heap.len) {
771
+ orig->as.heap.ptr = (char*)mrb_realloc(mrb, orig->as.heap.ptr, len+1);
772
+ orig->as.heap.aux.capa = (mrb_ssize)len;
773
+ }
774
+ str_init_shared(mrb, orig, s, NULL);
775
+ str_init_shared(mrb, orig, orig, s->as.heap.aux.shared);
776
+ }
777
+ }
778
+
779
+ /*
780
+ * @param mrb The mruby state.
781
+ * @param str The original mruby string.
782
+ * @param beg The starting byte offset of the substring.
783
+ * @param len The length in bytes of the substring.
784
+ * @return A new mruby string representing the byte subsequence.
785
+ *
786
+ * Creates a new mruby string that is a subsequence of an existing string,
787
+ * based on byte offsets and length. This function may share the underlying
788
+ * buffer with the original string if possible.
789
+ */
790
+ mrb_value
791
+ mrb_str_byte_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
792
+ {
793
+ struct RString *orig = mrb_str_ptr(str);
794
+ struct RString *s = mrb_obj_alloc_string(mrb);
795
+
796
+ if (RSTR_EMBEDDABLE_P(len)) {
797
+ str_init_embed(s, RSTR_PTR(orig)+beg, len);
798
+ }
799
+ else {
800
+ str_share(mrb, orig, s);
801
+ s->as.heap.ptr += (mrb_ssize)beg;
802
+ s->as.heap.len = (mrb_ssize)len;
803
+ }
804
+ RSTR_COPY_SINGLE_BYTE_FLAG(s, orig);
805
+ return mrb_obj_value(s);
806
+ }
807
+
808
+ #ifdef MRB_UTF8_STRING
809
+ static inline mrb_value
810
+ str_subseq(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
811
+ {
812
+ beg = chars2bytes(str, 0, beg);
813
+ len = chars2bytes(str, beg, len);
814
+ return mrb_str_byte_subseq(mrb, str, beg, len);
815
+ }
816
+ #else
817
+ #define str_subseq(mrb, str, beg, len) mrb_str_byte_subseq(mrb, str, beg, len)
818
+ #endif
819
+
820
+ mrb_bool
821
+ mrb_str_beg_len(mrb_int str_len, mrb_int *begp, mrb_int *lenp)
822
+ {
823
+ if (str_len < *begp || *lenp < 0) return FALSE;
824
+ if (*begp < 0) {
825
+ *begp += str_len;
826
+ if (*begp < 0) return FALSE;
827
+ }
828
+ if (*lenp > str_len - *begp)
829
+ *lenp = str_len - *begp;
830
+ if (*lenp <= 0) {
831
+ *lenp = 0;
832
+ }
833
+ return TRUE;
834
+ }
835
+
836
+ static mrb_value
837
+ str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
838
+ {
839
+ return mrb_str_beg_len(RSTRING_CHAR_LEN(str), &beg, &len) ?
840
+ str_subseq(mrb, str, beg, len) : mrb_nil_value();
841
+ }
842
+
843
+ /*
844
+ * @param mrb The mruby state.
845
+ * @param str The mruby string to search in.
846
+ * @param sptr A pointer to the C string to search for.
847
+ * @param slen The length of the C string to search for.
848
+ * @param offset The byte offset at which to start the search.
849
+ * @return The byte offset of the first occurrence of the substring, or -1 if not found.
850
+ *
851
+ * Finds the first occurrence of a C string within an mruby string, starting from a given offset.
852
+ * The search is performed on a byte-by-byte basis.
853
+ */
854
+ MRB_API mrb_int
855
+ mrb_str_index(mrb_state *mrb, mrb_value str, const char *sptr, mrb_int slen, mrb_int offset)
856
+ {
857
+ mrb_int len = RSTRING_LEN(str);
858
+
859
+ if (offset < 0) {
860
+ offset += len;
861
+ if (offset < 0) return -1;
862
+ }
863
+ if (len - offset < slen) return -1;
864
+
865
+ char *s = RSTRING_PTR(str);
866
+ if (offset) {
867
+ s += offset;
868
+ }
869
+ if (slen == 0) return offset;
870
+ /* need proceed one character at a time */
871
+ len = RSTRING_LEN(str) - offset;
872
+
873
+ mrb_int pos = mrb_memsearch(sptr, slen, s, len);
874
+ if (pos < 0) return pos;
875
+ return pos + offset;
876
+ }
877
+
878
+ static mrb_int
879
+ str_index_str(mrb_state *mrb, mrb_value str, mrb_value str2, mrb_int offset)
880
+ {
881
+ const char *ptr = RSTRING_PTR(str2);
882
+ mrb_int len = RSTRING_LEN(str2);
883
+
884
+ return mrb_str_index(mrb, str, ptr, len, offset);
885
+ }
886
+
887
+ static mrb_value
888
+ str_replace(mrb_state *mrb, struct RString *s1, struct RString *s2)
889
+ {
890
+ mrb_check_frozen(mrb, s1);
891
+ if (s1 == s2) return mrb_obj_value(s1);
892
+ RSTR_COPY_SINGLE_BYTE_FLAG(s1, s2);
893
+ if (RSTR_SHARED_P(s1)) {
894
+ str_decref(mrb, s1->as.heap.aux.shared);
895
+ }
896
+ else if (!RSTR_EMBED_P(s1) && !RSTR_NOFREE_P(s1) && !RSTR_FSHARED_P(s1)) {
897
+ mrb_free(mrb, s1->as.heap.ptr);
898
+ }
899
+
900
+ size_t len = (size_t)RSTR_LEN(s2);
901
+ if (RSTR_EMBEDDABLE_P(len)) {
902
+ str_init_embed(s1, RSTR_PTR(s2), len);
903
+ }
904
+ else {
905
+ str_share(mrb, s2, s1);
906
+ }
907
+
908
+ return mrb_obj_value(s1);
909
+ }
910
+
911
+ static mrb_int
912
+ str_rindex(mrb_state *mrb, mrb_value str, mrb_value sub, mrb_int pos)
913
+ {
914
+ const char *s, *sbeg, *send, *t;
915
+ struct RString *ps = mrb_str_ptr(str);
916
+ mrb_int len = RSTRING_LEN(sub);
917
+ mrb_int slen = RSTR_LEN(ps);
918
+
919
+ /* substring longer than string */
920
+ if (slen < len) return -1;
921
+ if (slen - pos < len) {
922
+ pos = slen - len;
923
+ }
924
+ sbeg = RSTR_PTR(ps);
925
+ send = sbeg + slen;
926
+ s = sbeg + pos;
927
+ t = RSTRING_PTR(sub);
928
+ if (len) {
929
+ s = char_adjust(s, send);
930
+ while (sbeg <= s) {
931
+ if ((mrb_int)(send - s) >= len && memcmp(s, t, len) == 0) {
932
+ return (mrb_int)(s - sbeg);
933
+ }
934
+ s = char_backtrack(sbeg, s);
935
+ }
936
+ return -1;
937
+ }
938
+ else {
939
+ return pos;
940
+ }
941
+ }
942
+
943
+ #ifdef _WIN32
944
+ #include <stdlib.h>
945
+ #include <malloc.h>
946
+ #include <windows.h>
947
+
948
+ char*
949
+ mrb_utf8_from_locale(const char *str, int len)
950
+ {
951
+ wchar_t* wcsp;
952
+ char* mbsp;
953
+ int mbssize, wcssize;
954
+
955
+ if (len == 0)
956
+ return strdup("");
957
+ if (len == -1)
958
+ len = (int)strlen(str);
959
+ wcssize = MultiByteToWideChar(GetACP(), 0, str, len, NULL, 0);
960
+ wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
961
+ if (!wcsp)
962
+ return NULL;
963
+ wcssize = MultiByteToWideChar(GetACP(), 0, str, len, wcsp, wcssize + 1);
964
+ wcsp[wcssize] = 0;
965
+
966
+ mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL);
967
+ mbsp = (char*) malloc((mbssize + 1));
968
+ if (!mbsp) {
969
+ free(wcsp);
970
+ return NULL;
971
+ }
972
+ mbssize = WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
973
+ mbsp[mbssize] = 0;
974
+ free(wcsp);
975
+ return mbsp;
976
+ }
977
+
978
+ char*
979
+ mrb_locale_from_utf8(const char *utf8, int len)
980
+ {
981
+ wchar_t* wcsp;
982
+ char* mbsp;
983
+ int mbssize, wcssize;
984
+
985
+ if (len == 0)
986
+ return strdup("");
987
+ if (len == -1)
988
+ len = (int)strlen(utf8);
989
+ wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
990
+ wcsp = (wchar_t*) malloc((wcssize + 1) * sizeof(wchar_t));
991
+ if (!wcsp)
992
+ return NULL;
993
+ wcssize = MultiByteToWideChar(CP_UTF8, 0, utf8, len, wcsp, wcssize + 1);
994
+ wcsp[wcssize] = 0;
995
+ mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, NULL, 0, NULL, NULL);
996
+ mbsp = (char*) malloc((mbssize + 1));
997
+ if (!mbsp) {
998
+ free(wcsp);
999
+ return NULL;
1000
+ }
1001
+ mbssize = WideCharToMultiByte(GetACP(), 0, (LPCWSTR) wcsp, -1, mbsp, mbssize, NULL, NULL);
1002
+ mbsp[mbssize] = 0;
1003
+ free(wcsp);
1004
+ return mbsp;
1005
+ }
1006
+ #endif
1007
+
1008
+ /*
1009
+ * @param mrb The mruby state.
1010
+ * @param s The RString structure to modify.
1011
+ *
1012
+ * Prepares a string for modification. If the string is shared or not extensible,
1013
+ * it will be unshared or converted to a normal string. This version preserves
1014
+ * the ASCII/single-byte nature of the string if it was already set.
1015
+ * Raises an error if the string is frozen.
1016
+ */
1017
+ MRB_API void
1018
+ mrb_str_modify_keep_ascii(mrb_state *mrb, struct RString *s)
1019
+ {
1020
+ mrb_check_frozen(mrb, s);
1021
+ str_unshare_buffer(mrb, s);
1022
+ }
1023
+
1024
+ /*
1025
+ * @param mrb The mruby state.
1026
+ * @param s The RString structure to modify.
1027
+ *
1028
+ * Prepares a string for modification. Similar to `mrb_str_modify_keep_ascii`,
1029
+ * but also unsets the single-byte flag, assuming the modification might
1030
+ * introduce multi-byte characters.
1031
+ * Raises an error if the string is frozen.
1032
+ */
1033
+ MRB_API void
1034
+ mrb_str_modify(mrb_state *mrb, struct RString *s)
1035
+ {
1036
+ mrb_str_modify_keep_ascii(mrb, s);
1037
+ RSTR_UNSET_SINGLE_BYTE_FLAG(s);
1038
+ }
1039
+
1040
+ /*
1041
+ * @param mrb The mruby state.
1042
+ * @param str The mruby string to resize.
1043
+ * @param len The new desired length of the string.
1044
+ * @return The resized mruby string.
1045
+ *
1046
+ * Resizes an mruby string to a new length.
1047
+ * If the new length is shorter, the string is truncated.
1048
+ * If the new length is longer, the string is extended, and the new portion's
1049
+ * content is undefined (it might be null bytes or garbage).
1050
+ * The string is modified in place.
1051
+ */
1052
+ MRB_API mrb_value
1053
+ mrb_str_resize(mrb_state *mrb, mrb_value str, mrb_int len)
1054
+ {
1055
+ struct RString *s = mrb_str_ptr(str);
1056
+
1057
+ str_check_length(mrb, len);
1058
+ mrb_str_modify(mrb, s);
1059
+ mrb_int slen = RSTR_LEN(s);
1060
+ if (len != slen) {
1061
+ if (slen < len || slen - len > 256) {
1062
+ resize_capa(mrb, s, len);
1063
+ }
1064
+ RSTR_SET_LEN(s, len);
1065
+ RSTR_PTR(s)[len] = '\0'; /* sentinel */
1066
+ }
1067
+ return str;
1068
+ }
1069
+
1070
+ /*
1071
+ * @param mrb The mruby state.
1072
+ * @param str0 The mruby string to convert.
1073
+ * @return A pointer to a null-terminated C string.
1074
+ *
1075
+ * Converts an mruby string to a null-terminated C string.
1076
+ * This function may allocate a new C string if the mruby string
1077
+ * contains null bytes or is not already null-terminated.
1078
+ * The caller is responsible for managing the memory of the returned C string
1079
+ * if it's different from the string's internal buffer.
1080
+ * Raises E_ARGUMENT_ERROR if the string contains a null byte.
1081
+ * Note: This function creates a *new* RString object to hold the C-string version if modification is needed.
1082
+ * It's generally recommended to use RSTRING_PTR and RSTRING_LEN for direct access
1083
+ * and ensure null termination manually if needed, or use mrb_string_cstr for a (potentially new) null-terminated string.
1084
+ */
1085
+ MRB_API char*
1086
+ mrb_str_to_cstr(mrb_state *mrb, mrb_value str0)
1087
+ {
1088
+ struct RString *s;
1089
+
1090
+ const char *p = RSTRING_PTR(str0);
1091
+ mrb_int len = RSTRING_LEN(str0);
1092
+ check_null_byte(mrb, RSTRING(str0));
1093
+ s = str_init_modifiable(mrb, mrb_obj_alloc_string(mrb), p, len);
1094
+ return RSTR_PTR(s);
1095
+ }
1096
+
1097
+ /*
1098
+ * @param mrb The mruby state.
1099
+ * @param self The mruby string to append to (modified in place).
1100
+ * @param other The mruby value to append (will be converted to a string).
1101
+ *
1102
+ * Concatenates the string representation of `other` to `self`.
1103
+ * `self` is modified in place.
1104
+ */
1105
+ MRB_API void
1106
+ mrb_str_concat(mrb_state *mrb, mrb_value self, mrb_value other)
1107
+ {
1108
+ other = mrb_obj_as_string(mrb, other);
1109
+ mrb_str_cat_str(mrb, self, other);
1110
+ }
1111
+
1112
+ /*
1113
+ * @param mrb The mruby state.
1114
+ * @param a The first mruby string.
1115
+ * @param b The second mruby string.
1116
+ * @return A new mruby string that is the concatenation of `a` and `b`.
1117
+ *
1118
+ * Creates a new mruby string by concatenating two existing mruby strings.
1119
+ */
1120
+ MRB_API mrb_value
1121
+ mrb_str_plus(mrb_state *mrb, mrb_value a, mrb_value b)
1122
+ {
1123
+ struct RString *s = mrb_str_ptr(a);
1124
+ struct RString *s2 = mrb_str_ptr(b);
1125
+ struct RString *t;
1126
+ mrb_int slen = RSTR_LEN(s);
1127
+ mrb_int s2len = RSTR_LEN(s2);
1128
+ const char *p = RSTR_PTR(s);
1129
+ const char *p2 = RSTR_PTR(s2);
1130
+
1131
+ t = str_new(mrb, 0, slen + s2len);
1132
+ char *pt = RSTR_PTR(t);
1133
+ memcpy(pt, p, slen);
1134
+ memcpy(pt + slen, p2, s2len);
1135
+
1136
+ return mrb_obj_value(t);
1137
+ }
1138
+
1139
+ /* 15.2.10.5.2 */
1140
+
1141
+ /*
1142
+ * call-seq:
1143
+ * str + other_str -> new_str
1144
+ *
1145
+ * Concatenation---Returns a new `String` containing
1146
+ * `other_str` concatenated to `str`.
1147
+ *
1148
+ * "Hello from " + self.to_s #=> "Hello from main"
1149
+ */
1150
+ static mrb_value
1151
+ mrb_str_plus_m(mrb_state *mrb, mrb_value self)
1152
+ {
1153
+ mrb_value str;
1154
+
1155
+ mrb_get_args(mrb, "S", &str);
1156
+ return mrb_str_plus(mrb, self, str);
1157
+ }
1158
+
1159
+ /* 15.2.10.5.26 */
1160
+ /* 15.2.10.5.33 */
1161
+ /*
1162
+ * call-seq:
1163
+ * "abcd".size => int
1164
+ *
1165
+ * Returns the length of string.
1166
+ */
1167
+ static mrb_value
1168
+ mrb_str_size(mrb_state *mrb, mrb_value self)
1169
+ {
1170
+ mrb_int len = RSTRING_CHAR_LEN(self);
1171
+ return mrb_int_value(mrb, len);
1172
+ }
1173
+
1174
+ static mrb_value
1175
+ mrb_str_bytesize(mrb_state *mrb, mrb_value self)
1176
+ {
1177
+ return mrb_int_value(mrb, RSTRING_LEN(self));
1178
+ }
1179
+
1180
+ /* 15.2.10.5.1 */
1181
+ /*
1182
+ * call-seq:
1183
+ * str * integer => new_str
1184
+ *
1185
+ * Copy---Returns a new `String` containing `integer` copies of
1186
+ * the receiver.
1187
+ *
1188
+ * "Ho! " * 3 #=> "Ho! Ho! Ho! "
1189
+ */
1190
+ static mrb_value
1191
+ mrb_str_times(mrb_state *mrb, mrb_value self)
1192
+ {
1193
+ mrb_int len, times;
1194
+
1195
+ mrb_get_args(mrb, "i", &times);
1196
+ if (times < 0) {
1197
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
1198
+ }
1199
+ if (mrb_int_mul_overflow(RSTRING_LEN(self), times, &len)) {
1200
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "argument too big");
1201
+ }
1202
+
1203
+ struct RString *str2 = str_new(mrb, 0, len);
1204
+ char *p = RSTR_PTR(str2);
1205
+ if (len > 0) {
1206
+ mrb_int n = RSTRING_LEN(self);
1207
+ memcpy(p, RSTRING_PTR(self), n);
1208
+ while (n <= len/2) {
1209
+ memcpy(p + n, p, n);
1210
+ n *= 2;
1211
+ }
1212
+ memcpy(p + n, p, len-n);
1213
+ }
1214
+ p[RSTR_LEN(str2)] = '\0';
1215
+ RSTR_COPY_SINGLE_BYTE_FLAG(str2, mrb_str_ptr(self));
1216
+
1217
+ return mrb_obj_value(str2);
1218
+ }
1219
+ /* -------------------------------------------------------------- */
1220
+
1221
+ #define lesser(a,b) (((a)>(b))?(b):(a))
1222
+
1223
+ /* ---------------------------*/
1224
+ /*
1225
+ * call-seq:
1226
+ * mrb_value str1 <=> mrb_value str2 => int
1227
+ * > 1
1228
+ * = 0
1229
+ * < -1
1230
+ */
1231
+ /*
1232
+ * @param mrb The mruby state.
1233
+ * @param str1 The first mruby string for comparison.
1234
+ * @param str2 The second mruby string for comparison (must be a string).
1235
+ * @return An integer less than, equal to, or greater than zero if `str1` is less than,
1236
+ * equal to, or greater than `str2`, respectively.
1237
+ *
1238
+ * Compares two mruby strings lexicographically.
1239
+ * Assumes `str2` is already a string. For a version that checks and converts, see `mrb_str_cmp_m`.
1240
+ */
1241
+ MRB_API int
1242
+ mrb_str_cmp(mrb_state *mrb, mrb_value str1, mrb_value str2)
1243
+ {
1244
+ struct RString *s1 = mrb_str_ptr(str1);
1245
+ struct RString *s2 = mrb_str_ptr(str2);
1246
+
1247
+ mrb_int len1 = RSTR_LEN(s1);
1248
+ mrb_int len2 = RSTR_LEN(s2);
1249
+ mrb_int len = lesser(len1, len2);
1250
+ mrb_int retval = (len == 0) ? 0 : memcmp(RSTR_PTR(s1), RSTR_PTR(s2), len);
1251
+
1252
+ if (retval == 0) {
1253
+ if (len1 == len2) return 0;
1254
+ if (len1 > len2) return 1;
1255
+ return -1;
1256
+ }
1257
+ if (retval > 0) return 1;
1258
+ return -1;
1259
+ }
1260
+ #undef lesser
1261
+
1262
+ /* 15.2.10.5.3 */
1263
+
1264
+ /*
1265
+ * call-seq:
1266
+ * str <=> other_str => -1, 0, +1
1267
+ *
1268
+ * Comparison---Returns -1 if `other_str` is less than, 0 if
1269
+ * `other_str` is equal to, and +1 if `other_str` is greater than
1270
+ * `str`. If the strings are of different lengths, and the strings are
1271
+ * equal when compared up to the shortest length, then the longer string is
1272
+ * considered greater than the shorter one. If the variable `$=` is
1273
+ * `false`, the comparison is based on comparing the binary values
1274
+ * of each character in the string. In older versions of Ruby, setting
1275
+ * `$=` allowed case-insensitive comparisons; this is now deprecated
1276
+ * in favor of using `String#casecmp`.
1277
+ *
1278
+ * `<=>` is the basis for the methods `<`, `<=`, `>`, `>=`, and `between?`,
1279
+ * included from module `Comparable`. The method `String#==` does not use
1280
+ * `Comparable#==`.
1281
+ *
1282
+ * "abcdef" <=> "abcde" #=> 1
1283
+ * "abcdef" <=> "abcdef" #=> 0
1284
+ * "abcdef" <=> "abcdefg" #=> -1
1285
+ * "abcdef" <=> "ABCDEF" #=> 1
1286
+ */
1287
+ static mrb_value
1288
+ mrb_str_cmp_m(mrb_state *mrb, mrb_value str1)
1289
+ {
1290
+ mrb_value str2 = mrb_get_arg1(mrb);
1291
+
1292
+ if (!mrb_string_p(str2)) {
1293
+ return mrb_nil_value();
1294
+ }
1295
+
1296
+ mrb_int result = mrb_str_cmp(mrb, str1, str2);
1297
+ return mrb_int_value(mrb, result);
1298
+ }
1299
+
1300
+ static mrb_bool
1301
+ str_eql(mrb_state *mrb, const mrb_value str1, const mrb_value str2)
1302
+ {
1303
+ const mrb_int len = RSTRING_LEN(str1);
1304
+
1305
+ if (len != RSTRING_LEN(str2)) return FALSE;
1306
+ return (memcmp(RSTRING_PTR(str1), RSTRING_PTR(str2), (size_t)len) == 0);
1307
+ }
1308
+
1309
+ /*
1310
+ * @param mrb The mruby state.
1311
+ * @param str1 The first mruby string.
1312
+ * @param str2 The second mruby value to compare with.
1313
+ * @return `TRUE` if `str1` and `str2` are equal strings, `FALSE` otherwise.
1314
+ *
1315
+ * Checks if two mruby strings are equal.
1316
+ * Returns `FALSE` if `str2` is not a string.
1317
+ */
1318
+ MRB_API mrb_bool
1319
+ mrb_str_equal(mrb_state *mrb, mrb_value str1, mrb_value str2)
1320
+ {
1321
+ if (!mrb_string_p(str2)) return FALSE;
1322
+ return str_eql(mrb, str1, str2);
1323
+ }
1324
+
1325
+ /* 15.2.10.5.4 */
1326
+ /*
1327
+ * call-seq:
1328
+ * str == obj => true or false
1329
+ *
1330
+ * Equality---
1331
+ * If `obj` is not a `String`, returns `false`.
1332
+ * Otherwise, returns `false` or `true`
1333
+ *
1334
+ * caution:if `str` `<=>` `obj` returns zero.
1335
+ */
1336
+ static mrb_value
1337
+ mrb_str_equal_m(mrb_state *mrb, mrb_value str1)
1338
+ {
1339
+ mrb_value str2 = mrb_get_arg1(mrb);
1340
+
1341
+ return mrb_bool_value(mrb_str_equal(mrb, str1, str2));
1342
+ }
1343
+ /* ---------------------------------- */
1344
+
1345
+ /*
1346
+ * @param mrb The mruby state.
1347
+ * @param str The mruby string to duplicate.
1348
+ * @return A new mruby string that is a copy of the original.
1349
+ *
1350
+ * Creates a new mruby string that is a duplicate of the given string.
1351
+ * The new string will have its own buffer.
1352
+ */
1353
+ MRB_API mrb_value
1354
+ mrb_str_dup(mrb_state *mrb, mrb_value str)
1355
+ {
1356
+ struct RString *s = mrb_str_ptr(str);
1357
+ struct RString *dup = str_new(mrb, 0, 0);
1358
+
1359
+ return str_replace(mrb, dup, s);
1360
+ }
1361
+
1362
+ enum str_convert_range {
1363
+ /* `beg` and `len` are byte unit in `0 ... str.bytesize` */
1364
+ STR_BYTE_RANGE_CORRECTED = 1,
1365
+
1366
+ /* `beg` and `len` are char unit in any range */
1367
+ STR_CHAR_RANGE = 2,
1368
+
1369
+ /* `beg` and `len` are char unit in `0 ... str.size` */
1370
+ STR_CHAR_RANGE_CORRECTED = 3,
1371
+
1372
+ /* `beg` is out of range */
1373
+ STR_OUT_OF_RANGE = -1
1374
+ };
1375
+
1376
+ static enum str_convert_range
1377
+ str_convert_range(mrb_state *mrb, mrb_value str, mrb_value idx, mrb_value alen, mrb_int *beg, mrb_int *len)
1378
+ {
1379
+ if (!mrb_undef_p(alen)) {
1380
+ *beg = mrb_as_int(mrb, idx);
1381
+ *len = mrb_as_int(mrb, alen);
1382
+ return STR_CHAR_RANGE;
1383
+ }
1384
+ else {
1385
+ switch (mrb_type(idx)) {
1386
+ default:
1387
+ idx = mrb_ensure_int_type(mrb, idx);
1388
+ /* fall through */
1389
+ case MRB_TT_INTEGER:
1390
+ *beg = mrb_integer(idx);
1391
+ *len = 1;
1392
+ return STR_CHAR_RANGE;
1393
+
1394
+ case MRB_TT_STRING:
1395
+ *beg = str_index_str(mrb, str, idx, 0);
1396
+ if (*beg < 0) { break; }
1397
+ *len = RSTRING_LEN(idx);
1398
+ return STR_BYTE_RANGE_CORRECTED;
1399
+
1400
+ case MRB_TT_RANGE:
1401
+ *len = RSTRING_CHAR_LEN(str);
1402
+ switch (mrb_range_beg_len(mrb, idx, beg, len, *len, TRUE)) {
1403
+ case MRB_RANGE_OK:
1404
+ return STR_CHAR_RANGE_CORRECTED;
1405
+ case MRB_RANGE_OUT:
1406
+ return STR_OUT_OF_RANGE;
1407
+ default:
1408
+ break;
1409
+ }
1410
+ }
1411
+ }
1412
+ return STR_OUT_OF_RANGE;
1413
+ }
1414
+
1415
+ /*
1416
+ * @param mrb The mruby state.
1417
+ * @param str The mruby string.
1418
+ * @param idx The index or range. Can be an integer, a string, or a range.
1419
+ * @param alen An optional length (if `idx` is an integer).
1420
+ * @return A new mruby string (substring), or nil if out of bounds or not found.
1421
+ *
1422
+ * Implements string element reference (e.g., `str[idx]`, `str[idx, len]`).
1423
+ * - If `idx` is an Integer, returns a substring of 1 character at that index (or `len` characters if `alen` is provided).
1424
+ * - If `idx` is a String, returns that string if it's a substring of `str`.
1425
+ * - If `idx` is a Range, returns the substring specified by the range.
1426
+ * Character indexing is used if UTF-8 is enabled, otherwise byte indexing.
1427
+ */
1428
+ mrb_value
1429
+ mrb_str_aref(mrb_state *mrb, mrb_value str, mrb_value idx, mrb_value alen)
1430
+ {
1431
+ mrb_int beg, len;
1432
+
1433
+ switch (str_convert_range(mrb, str, idx, alen, &beg, &len)) {
1434
+ case STR_CHAR_RANGE_CORRECTED:
1435
+ return str_subseq(mrb, str, beg, len);
1436
+ case STR_CHAR_RANGE:
1437
+ str = str_substr(mrb, str, beg, len);
1438
+ if (mrb_undef_p(alen) && !mrb_nil_p(str) && RSTRING_LEN(str) == 0) return mrb_nil_value();
1439
+ return str;
1440
+ case STR_BYTE_RANGE_CORRECTED:
1441
+ if (mrb_string_p(idx)) {
1442
+ return mrb_str_dup(mrb, idx);
1443
+ }
1444
+ else {
1445
+ return mrb_str_byte_subseq(mrb, str, beg, len);
1446
+ }
1447
+ case STR_OUT_OF_RANGE:
1448
+ default:
1449
+ return mrb_nil_value();
1450
+ }
1451
+ }
1452
+
1453
+ /* 15.2.10.5.6 */
1454
+ /* 15.2.10.5.34 */
1455
+ /*
1456
+ * call-seq:
1457
+ * str[int] => int or nil
1458
+ * str[int, int] => new_str or nil
1459
+ * str[range] => new_str or nil
1460
+ * str[other_str] => new_str or nil
1461
+ * str.slice(int) => int or nil
1462
+ * str.slice(int, int) => new_str or nil
1463
+ * str.slice(range) => new_str or nil
1464
+ * str.slice(other_str) => new_str or nil
1465
+ *
1466
+ * Element Reference---If passed a single `Integer`, returns the code
1467
+ * of the character at that position. If passed two `Integer`
1468
+ * objects, returns a substring starting at the offset given by the first, and
1469
+ * a length given by the second. If given a range, a substring containing
1470
+ * characters at offsets given by the range is returned. In all three cases, if
1471
+ * an offset is negative, it is counted from the end of *str*. Returns
1472
+ * `nil` if the initial offset falls outside the string, the length
1473
+ * is negative, or the beginning of the range is greater than the end.
1474
+ *
1475
+ * If a `String` is given, that string is returned if it occurs in
1476
+ * *str*. In both cases, `nil` is returned if there is no
1477
+ * match.
1478
+ *
1479
+ * a = "hello there"
1480
+ * a[1] #=> 101(1.8.7) "e"(1.9.2)
1481
+ * a[1.1] #=> "e"(1.9.2)
1482
+ * a[1,3] #=> "ell"
1483
+ * a[1..3] #=> "ell"
1484
+ * a[-3,2] #=> "er"
1485
+ * a[-4..-2] #=> "her"
1486
+ * a[12..-1] #=> nil
1487
+ * a[-2..-4] #=> ""
1488
+ * a["lo"] #=> "lo"
1489
+ * a["bye"] #=> nil
1490
+ */
1491
+ static mrb_value
1492
+ mrb_str_aref_m(mrb_state *mrb, mrb_value str)
1493
+ {
1494
+ mrb_value a1, a2;
1495
+
1496
+ if (mrb_get_args(mrb, "o|o", &a1, &a2) == 1) {
1497
+ a2 = mrb_undef_value();
1498
+ }
1499
+
1500
+ return mrb_str_aref(mrb, str, a1, a2);
1501
+ }
1502
+
1503
+ static mrb_noreturn void
1504
+ str_out_of_index(mrb_state *mrb, mrb_value index)
1505
+ {
1506
+ mrb_raisef(mrb, E_INDEX_ERROR, "index %v out of string", index);
1507
+ }
1508
+
1509
+ static mrb_value
1510
+ str_replace_partial(mrb_state *mrb, mrb_value src, mrb_int pos, mrb_int end, mrb_value rep)
1511
+ {
1512
+ const mrb_int shrink_threshold = 256;
1513
+ struct RString *str = mrb_str_ptr(src);
1514
+ mrb_int len = RSTR_LEN(str);
1515
+ mrb_int replen, newlen;
1516
+ char *strp;
1517
+
1518
+ if (end > len) { end = len; }
1519
+
1520
+ if (pos < 0 || pos > len) {
1521
+ str_out_of_index(mrb, mrb_int_value(mrb, pos));
1522
+ }
1523
+
1524
+ replen = (mrb_nil_p(rep) ? 0 : RSTRING_LEN(rep));
1525
+ if (mrb_int_add_overflow(replen, len - (end - pos), &newlen)) {
1526
+ mrb_raise(mrb, E_RUNTIME_ERROR, "string size too big");
1527
+ }
1528
+
1529
+ mrb_str_modify(mrb, str);
1530
+
1531
+ if (len < newlen) {
1532
+ resize_capa(mrb, str, newlen);
1533
+ }
1534
+
1535
+ strp = RSTR_PTR(str);
1536
+
1537
+ memmove(strp + newlen - (len - end), strp + end, len - end);
1538
+ if (!mrb_nil_p(rep)) {
1539
+ memmove(strp + pos, RSTRING_PTR(rep), replen);
1540
+ }
1541
+ RSTR_SET_LEN(str, newlen);
1542
+ strp[newlen] = '\0';
1543
+
1544
+ if (len - newlen >= shrink_threshold) {
1545
+ resize_capa(mrb, str, newlen);
1546
+ }
1547
+
1548
+ return src;
1549
+ }
1550
+
1551
+ #define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
1552
+
1553
+ static mrb_value
1554
+ str_escape(mrb_state *mrb, mrb_value str, mrb_bool inspect)
1555
+ {
1556
+ const char *p, *pend;
1557
+ char buf[4]; /* `\x??` or UTF-8 character */
1558
+ mrb_value result = mrb_str_new_lit(mrb, "\"");
1559
+ #ifdef MRB_UTF8_STRING
1560
+ uint32_t sb_flag = MRB_STR_SINGLE_BYTE;
1561
+ #endif
1562
+
1563
+ p = RSTRING_PTR(str); pend = RSTRING_END(str);
1564
+ for (;p < pend; p++) {
1565
+ unsigned char c, cc;
1566
+ #ifdef MRB_UTF8_STRING
1567
+ if (inspect) {
1568
+ mrb_int clen = mrb_utf8len(p, pend);
1569
+ if (clen > 1) {
1570
+ mrb_str_cat(mrb, result, p, clen);
1571
+ p += clen-1;
1572
+ sb_flag = 0;
1573
+ continue;
1574
+ }
1575
+ }
1576
+ #endif
1577
+ c = *p;
1578
+ if (c == '"'|| c == '\\' || (c == '#' && IS_EVSTR(p+1, pend))) {
1579
+ buf[0] = '\\'; buf[1] = c;
1580
+ mrb_str_cat(mrb, result, buf, 2);
1581
+ continue;
1582
+ }
1583
+ if (ISPRINT(c)) {
1584
+ buf[0] = c;
1585
+ mrb_str_cat(mrb, result, buf, 1);
1586
+ continue;
1587
+ }
1588
+ switch (c) {
1589
+ case '\n': cc = 'n'; break;
1590
+ case '\r': cc = 'r'; break;
1591
+ case '\t': cc = 't'; break;
1592
+ case '\f': cc = 'f'; break;
1593
+ case '\013': cc = 'v'; break;
1594
+ case '\010': cc = 'b'; break;
1595
+ case '\007': cc = 'a'; break;
1596
+ case 033: cc = 'e'; break;
1597
+ default: cc = 0; break;
1598
+ }
1599
+ buf[0] = '\\';
1600
+ if (cc) {
1601
+ buf[1] = (char)cc;
1602
+ mrb_str_cat(mrb, result, buf, 2);
1603
+ }
1604
+ else {
1605
+ buf[1] = 'x';
1606
+ buf[3] = mrb_digitmap[c % 16]; c /= 16;
1607
+ buf[2] = mrb_digitmap[c % 16];
1608
+ mrb_str_cat(mrb, result, buf, 4);
1609
+ }
1610
+ }
1611
+ mrb_str_cat_lit(mrb, result, "\"");
1612
+ #ifdef MRB_UTF8_STRING
1613
+ if (inspect) {
1614
+ mrb_str_ptr(str)->flags |= sb_flag;
1615
+ mrb_str_ptr(result)->flags |= sb_flag;
1616
+ }
1617
+ else {
1618
+ RSTR_SET_SINGLE_BYTE_FLAG(mrb_str_ptr(result));
1619
+ }
1620
+ #endif
1621
+
1622
+ return result;
1623
+ }
1624
+
1625
+ static void
1626
+ mrb_str_aset(mrb_state *mrb, mrb_value str, mrb_value idx, mrb_value alen, mrb_value replace)
1627
+ {
1628
+ mrb_int beg, len, charlen;
1629
+
1630
+ mrb_ensure_string_type(mrb, replace);
1631
+ switch (str_convert_range(mrb, str, idx, alen, &beg, &len)) {
1632
+ case STR_OUT_OF_RANGE:
1633
+ default:
1634
+ mrb_raise(mrb, E_INDEX_ERROR, "string not matched");
1635
+ case STR_CHAR_RANGE:
1636
+ if (len < 0) {
1637
+ mrb_raisef(mrb, E_INDEX_ERROR, "negative length %v", alen);
1638
+ }
1639
+ charlen = RSTRING_CHAR_LEN(str);
1640
+ if (beg < 0) { beg += charlen; }
1641
+ if (beg < 0 || beg > charlen) { str_out_of_index(mrb, idx); }
1642
+ /* fall through */
1643
+ case STR_CHAR_RANGE_CORRECTED:
1644
+ beg = chars2bytes(str, 0, beg);
1645
+ len = chars2bytes(str, beg, len);
1646
+ /* fall through */
1647
+ case STR_BYTE_RANGE_CORRECTED:
1648
+ if (mrb_int_add_overflow(beg, len, &len)) {
1649
+ mrb_raise(mrb, E_RUNTIME_ERROR, "string index too big");
1650
+ }
1651
+ str_replace_partial(mrb, str, beg, len, replace);
1652
+ }
1653
+ }
1654
+
1655
+ /*
1656
+ * call-seq:
1657
+ * str[int] = replace
1658
+ * str[int, int] = replace
1659
+ * str[range] = replace
1660
+ * str[other_str] = replace
1661
+ *
1662
+ * Modify `self` by replacing the content of `self`.
1663
+ * The portion of the string affected is determined using the same criteria as +String#[]+.
1664
+ * The return value of this expression is `replace`.
1665
+ */
1666
+ static mrb_value
1667
+ mrb_str_aset_m(mrb_state *mrb, mrb_value str)
1668
+ {
1669
+ mrb_value idx, alen, replace;
1670
+
1671
+ switch (mrb_get_args(mrb, "oo|S!", &idx, &alen, &replace)) {
1672
+ case 2:
1673
+ replace = alen;
1674
+ alen = mrb_undef_value();
1675
+ break;
1676
+ case 3:
1677
+ break;
1678
+ }
1679
+ mrb_str_aset(mrb, str, idx, alen, replace);
1680
+ return replace;
1681
+ }
1682
+
1683
+ /* 15.2.10.5.8 */
1684
+ /*
1685
+ * call-seq:
1686
+ * str.capitalize! => str or nil
1687
+ *
1688
+ * Modifies *str* by converting the first character to uppercase and the
1689
+ * remainder to lowercase. Returns `nil` if no changes are made.
1690
+ *
1691
+ * a = "hello"
1692
+ * a.capitalize! #=> "Hello"
1693
+ * a #=> "Hello"
1694
+ * a.capitalize! #=> nil
1695
+ */
1696
+ static mrb_value
1697
+ mrb_str_capitalize_bang(mrb_state *mrb, mrb_value str)
1698
+ {
1699
+ mrb_bool modify = FALSE;
1700
+ struct RString *s = mrb_str_ptr(str);
1701
+ mrb_int len = RSTR_LEN(s);
1702
+
1703
+ mrb_str_modify_keep_ascii(mrb, s);
1704
+ char *p = RSTR_PTR(s);
1705
+ char *pend = RSTR_PTR(s) + len;
1706
+ if (len == 0 || p == NULL) return mrb_nil_value();
1707
+ if (ISLOWER(*p)) {
1708
+ *p = TOUPPER(*p);
1709
+ modify = TRUE;
1710
+ }
1711
+ while (++p < pend) {
1712
+ if (ISUPPER(*p)) {
1713
+ *p = TOLOWER(*p);
1714
+ modify = TRUE;
1715
+ }
1716
+ }
1717
+ if (modify) return str;
1718
+ return mrb_nil_value();
1719
+ }
1720
+
1721
+ /* 15.2.10.5.7 */
1722
+ /*
1723
+ * call-seq:
1724
+ * str.capitalize => new_str
1725
+ *
1726
+ * Returns a copy of *str* with the first character converted to uppercase
1727
+ * and the remainder to lowercase.
1728
+ *
1729
+ * "hello".capitalize #=> "Hello"
1730
+ * "HELLO".capitalize #=> "Hello"
1731
+ * "123ABC".capitalize #=> "123abc"
1732
+ */
1733
+ static mrb_value
1734
+ mrb_str_capitalize(mrb_state *mrb, mrb_value self)
1735
+ {
1736
+ mrb_value str = mrb_str_dup(mrb, self);
1737
+ mrb_str_capitalize_bang(mrb, str);
1738
+ return str;
1739
+ }
1740
+
1741
+ /* 15.2.10.5.10 */
1742
+ /*
1743
+ * call-seq:
1744
+ * str.chomp!(separator="\n") => str or nil
1745
+ *
1746
+ * Modifies *str* in place as described for `String#chomp`,
1747
+ * returning *str*, or `nil` if no modifications were made.
1748
+ */
1749
+ static mrb_value
1750
+ mrb_str_chomp_bang(mrb_state *mrb, mrb_value str)
1751
+ {
1752
+ mrb_value rs;
1753
+ mrb_int argc = mrb_get_args(mrb, "|S", &rs);
1754
+ struct RString *s = mrb_str_ptr(str);
1755
+
1756
+ mrb_str_modify_keep_ascii(mrb, s);
1757
+ mrb_int len = RSTR_LEN(s);
1758
+ if (argc == 0) {
1759
+ if (len == 0) return mrb_nil_value();
1760
+ smart_chomp:
1761
+ if (RSTR_PTR(s)[len-1] == '\n') {
1762
+ RSTR_SET_LEN(s, RSTR_LEN(s) - 1);
1763
+ if (RSTR_LEN(s) > 0 &&
1764
+ RSTR_PTR(s)[RSTR_LEN(s)-1] == '\r') {
1765
+ RSTR_SET_LEN(s, RSTR_LEN(s) - 1);
1766
+ }
1767
+ }
1768
+ else if (RSTR_PTR(s)[len-1] == '\r') {
1769
+ RSTR_SET_LEN(s, RSTR_LEN(s) - 1);
1770
+ }
1771
+ else {
1772
+ return mrb_nil_value();
1773
+ }
1774
+ RSTR_PTR(s)[RSTR_LEN(s)] = '\0';
1775
+ return str;
1776
+ }
1777
+
1778
+ if (len == 0 || mrb_nil_p(rs)) return mrb_nil_value();
1779
+ char *p = RSTR_PTR(s);
1780
+ mrb_int rslen = RSTRING_LEN(rs);
1781
+ if (rslen == 0) {
1782
+ while (len>0 && p[len-1] == '\n') {
1783
+ len--;
1784
+ if (len>0 && p[len-1] == '\r')
1785
+ len--;
1786
+ }
1787
+ if (len < RSTR_LEN(s)) {
1788
+ RSTR_SET_LEN(s, len);
1789
+ p[len] = '\0';
1790
+ return str;
1791
+ }
1792
+ return mrb_nil_value();
1793
+ }
1794
+ if (rslen > len) return mrb_nil_value();
1795
+ mrb_int newline = RSTRING_PTR(rs)[rslen-1];
1796
+ if (rslen == 1 && newline == '\n')
1797
+ newline = RSTRING_PTR(rs)[rslen-1];
1798
+ if (rslen == 1 && newline == '\n')
1799
+ goto smart_chomp;
1800
+
1801
+ char *pp = p + len - rslen;
1802
+ if (p[len-1] == newline &&
1803
+ (rslen <= 1 ||
1804
+ memcmp(RSTRING_PTR(rs), pp, rslen) == 0)) {
1805
+ RSTR_SET_LEN(s, len - rslen);
1806
+ p[RSTR_LEN(s)] = '\0';
1807
+ return str;
1808
+ }
1809
+ return mrb_nil_value();
1810
+ }
1811
+
1812
+ /* 15.2.10.5.9 */
1813
+ /*
1814
+ * call-seq:
1815
+ * str.chomp(separator="\n") => new_str
1816
+ *
1817
+ * Returns a new `String` with the given record separator removed
1818
+ * from the end of *str* (if present). `chomp` also removes
1819
+ * carriage return characters (that is it will remove `\n`,
1820
+ * `\r`, and `\r\n`).
1821
+ *
1822
+ * "hello".chomp #=> "hello"
1823
+ * "hello\n".chomp #=> "hello"
1824
+ * "hello\r\n".chomp #=> "hello"
1825
+ * "hello\n\r".chomp #=> "hello\n"
1826
+ * "hello\r".chomp #=> "hello"
1827
+ * "hello \n there".chomp #=> "hello \n there"
1828
+ * "hello".chomp("llo") #=> "he"
1829
+ */
1830
+ static mrb_value
1831
+ mrb_str_chomp(mrb_state *mrb, mrb_value self)
1832
+ {
1833
+ mrb_value str = mrb_str_dup(mrb, self);
1834
+ mrb_str_chomp_bang(mrb, str);
1835
+ return str;
1836
+ }
1837
+
1838
+ /* 15.2.10.5.12 */
1839
+ /*
1840
+ * call-seq:
1841
+ * str.chop! => str or nil
1842
+ *
1843
+ * Processes *str* as for `String#chop`, returning *str*,
1844
+ * or `nil` if *str* is the empty string. See also
1845
+ * `String#chomp!`.
1846
+ */
1847
+ static mrb_value
1848
+ mrb_str_chop_bang(mrb_state *mrb, mrb_value str)
1849
+ {
1850
+ struct RString *s = mrb_str_ptr(str);
1851
+
1852
+ mrb_str_modify_keep_ascii(mrb, s);
1853
+ if (RSTR_LEN(s) > 0) {
1854
+ mrb_int len;
1855
+ #ifdef MRB_UTF8_STRING
1856
+ const char* t = RSTR_PTR(s), *p = t;
1857
+ const char* e = p + RSTR_LEN(s);
1858
+ while (p<e) {
1859
+ mrb_int clen = mrb_utf8len(p, e);
1860
+ if (p + clen>=e) break;
1861
+ p += clen;
1862
+ }
1863
+ len = p - t;
1864
+ #else
1865
+ len = RSTR_LEN(s) - 1;
1866
+ #endif
1867
+ if (RSTR_PTR(s)[len] == '\n') {
1868
+ if (len > 0 &&
1869
+ RSTR_PTR(s)[len-1] == '\r') {
1870
+ len--;
1871
+ }
1872
+ }
1873
+ RSTR_SET_LEN(s, len);
1874
+ RSTR_PTR(s)[len] = '\0';
1875
+ return str;
1876
+ }
1877
+ return mrb_nil_value();
1878
+ }
1879
+
1880
+ /* 15.2.10.5.11 */
1881
+ /*
1882
+ * call-seq:
1883
+ * str.chop => new_str
1884
+ *
1885
+ * Returns a new `String` with the last character removed. If the
1886
+ * string ends with `\r\n`, both characters are removed. Applying
1887
+ * `chop` to an empty string returns an empty
1888
+ * string. `String#chomp` is often a safer alternative, as it leaves
1889
+ * the string unchanged if it doesn't end in a record separator.
1890
+ *
1891
+ * "string\r\n".chop #=> "string"
1892
+ * "string\n\r".chop #=> "string\n"
1893
+ * "string\n".chop #=> "string"
1894
+ * "string".chop #=> "strin"
1895
+ * "x".chop #=> ""
1896
+ */
1897
+ static mrb_value
1898
+ mrb_str_chop(mrb_state *mrb, mrb_value self)
1899
+ {
1900
+ mrb_value str = mrb_str_dup(mrb, self);
1901
+ mrb_str_chop_bang(mrb, str);
1902
+ return str;
1903
+ }
1904
+
1905
+ /* 15.2.10.5.14 */
1906
+ /*
1907
+ * call-seq:
1908
+ * str.downcase! => str or nil
1909
+ *
1910
+ * Downcases the contents of *str*, returning `nil` if no
1911
+ * changes were made.
1912
+ */
1913
+ static mrb_value
1914
+ mrb_str_downcase_bang(mrb_state *mrb, mrb_value str)
1915
+ {
1916
+ char *p, *pend;
1917
+ mrb_bool modify = FALSE;
1918
+ struct RString *s = mrb_str_ptr(str);
1919
+
1920
+ mrb_str_modify_keep_ascii(mrb, s);
1921
+ p = RSTR_PTR(s);
1922
+ pend = RSTR_PTR(s) + RSTR_LEN(s);
1923
+ while (p < pend) {
1924
+ if (ISUPPER(*p)) {
1925
+ *p = TOLOWER(*p);
1926
+ modify = TRUE;
1927
+ }
1928
+ p++;
1929
+ }
1930
+
1931
+ if (modify) return str;
1932
+ return mrb_nil_value();
1933
+ }
1934
+
1935
+ /* 15.2.10.5.13 */
1936
+ /*
1937
+ * call-seq:
1938
+ * str.downcase => new_str
1939
+ *
1940
+ * Returns a copy of *str* with all uppercase letters replaced with their
1941
+ * lowercase counterparts. The operation is locale insensitive---only
1942
+ * characters 'A' to 'Z' are affected.
1943
+ *
1944
+ * "hEllO".downcase #=> "hello"
1945
+ */
1946
+ static mrb_value
1947
+ mrb_str_downcase(mrb_state *mrb, mrb_value self)
1948
+ {
1949
+ mrb_value str = mrb_str_dup(mrb, self);
1950
+ mrb_str_downcase_bang(mrb, str);
1951
+ return str;
1952
+ }
1953
+
1954
+ /* 15.2.10.5.16 */
1955
+ /*
1956
+ * call-seq:
1957
+ * str.empty? => true or false
1958
+ *
1959
+ * Returns `true` if *str* has a length of zero.
1960
+ *
1961
+ * "hello".empty? #=> false
1962
+ * "".empty? #=> true
1963
+ */
1964
+ static mrb_value
1965
+ mrb_str_empty_p(mrb_state *mrb, mrb_value self)
1966
+ {
1967
+ struct RString *s = mrb_str_ptr(self);
1968
+
1969
+ return mrb_bool_value(RSTR_LEN(s) == 0);
1970
+ }
1971
+
1972
+ /* 15.2.10.5.17 */
1973
+ /*
1974
+ * call-seq:
1975
+ * str.eql?(other) => true or false
1976
+ *
1977
+ * Two strings are equal if the have the same length and content.
1978
+ */
1979
+ static mrb_value
1980
+ mrb_str_eql(mrb_state *mrb, mrb_value self)
1981
+ {
1982
+ mrb_value str2 = mrb_get_arg1(mrb);
1983
+ mrb_bool eql_p = (mrb_string_p(str2)) && str_eql(mrb, self, str2);
1984
+
1985
+ return mrb_bool_value(eql_p);
1986
+ }
1987
+
1988
+ /*
1989
+ * @param mrb The mruby state.
1990
+ * @param str The mruby string from which to take a substring.
1991
+ * @param beg The starting character index of the substring.
1992
+ * @param len The length in characters of the substring.
1993
+ * @return A new mruby string representing the substring, or nil if out of bounds.
1994
+ *
1995
+ * Creates a new mruby string that is a substring of an existing string.
1996
+ * This function considers character indices (which might differ from byte indices
1997
+ * if UTF-8 is enabled) and length.
1998
+ * Handles negative indices and adjusts length to fit within string boundaries.
1999
+ */
2000
+ MRB_API mrb_value
2001
+ mrb_str_substr(mrb_state *mrb, mrb_value str, mrb_int beg, mrb_int len)
2002
+ {
2003
+ return str_substr(mrb, str, beg, len);
2004
+ }
2005
+
2006
+ /*
2007
+ * 32-bit magic FNV-0 and FNV-1 prime
2008
+ b */
2009
+ #define FNV_32_PRIME ((uint32_t)0x01000193)
2010
+ #define FNV1_32_INIT ((uint32_t)0x811c9dc5)
2011
+
2012
+ uint32_t
2013
+ mrb_byte_hash_step(const uint8_t *s, mrb_int len, uint32_t hval)
2014
+ {
2015
+ const uint8_t *send = s + len;
2016
+
2017
+ /*
2018
+ * FNV-1 hash each octet in the buffer
2019
+ */
2020
+ while (s < send) {
2021
+ /* multiply by the 32-bit FNV magic prime mod 2^32 */
2022
+ #if defined(NO_FNV_GCC_OPTIMIZATION)
2023
+ hval *= FNV_32_PRIME;
2024
+ #else
2025
+ hval += (hval<<1) + (hval<<4) + (hval<<7) + (hval<<8) + (hval<<24);
2026
+ #endif
2027
+
2028
+ /* xor the bottom with the current octet */
2029
+ hval ^= (uint32_t)*s++;
2030
+ }
2031
+
2032
+ /* return our new hash value */
2033
+ return hval;
2034
+ }
2035
+
2036
+ uint32_t
2037
+ mrb_byte_hash(const uint8_t *s, mrb_int len)
2038
+ {
2039
+ return mrb_byte_hash_step(s, len, FNV1_32_INIT);
2040
+ }
2041
+
2042
+ uint32_t
2043
+ mrb_str_hash(mrb_state *mrb, mrb_value str)
2044
+ {
2045
+ struct RString *s = mrb_str_ptr(str);
2046
+ return mrb_byte_hash((uint8_t*)RSTR_PTR(s), RSTR_LEN(s));
2047
+ }
2048
+
2049
+ /* 15.2.10.5.20 */
2050
+ /*
2051
+ * call-seq:
2052
+ * str.hash => int
2053
+ *
2054
+ * Return a hash based on the string's length and content.
2055
+ */
2056
+ static mrb_value
2057
+ mrb_str_hash_m(mrb_state *mrb, mrb_value self)
2058
+ {
2059
+ mrb_int key = mrb_str_hash(mrb, self);
2060
+ return mrb_int_value(mrb, key);
2061
+ }
2062
+
2063
+ /* 15.2.10.5.21 */
2064
+ /*
2065
+ * call-seq:
2066
+ * str.include? other_str => true or false
2067
+ * str.include? int => true or false
2068
+ *
2069
+ * Returns `true` if *str* contains the given string or
2070
+ * character.
2071
+ *
2072
+ * "hello".include? "lo" #=> true
2073
+ * "hello".include? "ol" #=> false
2074
+ * "hello".include? ?h #=> true
2075
+ */
2076
+ static mrb_value
2077
+ mrb_str_include(mrb_state *mrb, mrb_value self)
2078
+ {
2079
+ mrb_value str2;
2080
+
2081
+ mrb_get_args(mrb, "S", &str2);
2082
+ if (str_index_str(mrb, self, str2, 0) < 0)
2083
+ return mrb_bool_value(FALSE);
2084
+ return mrb_bool_value(TRUE);
2085
+ }
2086
+
2087
+ /*
2088
+ * call-seq:
2089
+ * str.byteindex(substring, offset = 0) -> integer or nil
2090
+ *
2091
+ * Returns the \Integer byte-based index of the first occurrence of the given `substring`,
2092
+ * or `nil` if none found:
2093
+ *
2094
+ * 'foo'.byteindex('f') # => 0
2095
+ * 'foo'.byteindex('oo') # => 1
2096
+ * 'foo'.byteindex('ooo') # => nil
2097
+ */
2098
+ static mrb_value
2099
+ mrb_str_byteindex_m(mrb_state *mrb, mrb_value str)
2100
+ {
2101
+ mrb_value sub;
2102
+ mrb_int pos;
2103
+
2104
+ if (mrb_get_args(mrb, "S|i", &sub, &pos) == 1) {
2105
+ pos = 0;
2106
+ }
2107
+ else if (pos < 0) {
2108
+ pos += RSTRING_LEN(str);
2109
+ if (pos < 0) {
2110
+ return mrb_nil_value();
2111
+ }
2112
+ }
2113
+ pos = str_index_str(mrb, str, sub, pos);
2114
+
2115
+ if (pos == -1) return mrb_nil_value();
2116
+ return mrb_int_value(mrb, pos);
2117
+ }
2118
+
2119
+ /* 15.2.10.5.22 */
2120
+ /*
2121
+ * call-seq:
2122
+ * str.index(substring [, offset]) => int or nil
2123
+ *
2124
+ * Returns the index of the first occurrence of the given
2125
+ * *substring*. Returns `nil` if not found.
2126
+ * If the second parameter is present, it
2127
+ * specifies the position in the string to begin the search.
2128
+ *
2129
+ * "hello".index('l') #=> 2
2130
+ * "hello".index('lo') #=> 3
2131
+ * "hello".index('a') #=> nil
2132
+ * "hello".index('l', -2) #=> 3
2133
+ */
2134
+ #ifdef MRB_UTF8_STRING
2135
+ static mrb_value
2136
+ mrb_str_index_m(mrb_state *mrb, mrb_value str)
2137
+ {
2138
+ if (RSTR_SINGLE_BYTE_P(mrb_str_ptr(str))) {
2139
+ return mrb_str_byteindex_m(mrb, str);
2140
+ }
2141
+
2142
+ mrb_value sub;
2143
+ mrb_int pos;
2144
+
2145
+ if (mrb_get_args(mrb, "S|i", &sub, &pos) == 1) {
2146
+ pos = 0;
2147
+ }
2148
+ else if (pos < 0) {
2149
+ mrb_int clen = RSTRING_CHAR_LEN(str);
2150
+ pos += clen;
2151
+ if (pos < 0) {
2152
+ return mrb_nil_value();
2153
+ }
2154
+ }
2155
+ pos = str_index_str_by_char(mrb, str, sub, pos);
2156
+
2157
+ if (pos == -1) return mrb_nil_value();
2158
+ return mrb_int_value(mrb, pos);
2159
+ }
2160
+ #else
2161
+ #define mrb_str_index_m mrb_str_byteindex_m
2162
+ #endif
2163
+
2164
+ /* 15.2.10.5.24 */
2165
+ /* 15.2.10.5.28 */
2166
+ /*
2167
+ * call-seq:
2168
+ * str.replace(other_str) => str
2169
+ *
2170
+ * s = "hello" #=> "hello"
2171
+ * s.replace "world" #=> "world"
2172
+ */
2173
+ static mrb_value
2174
+ mrb_str_replace(mrb_state *mrb, mrb_value str)
2175
+ {
2176
+ mrb_value str2;
2177
+
2178
+ mrb_get_args(mrb, "S", &str2);
2179
+ return str_replace(mrb, mrb_str_ptr(str), mrb_str_ptr(str2));
2180
+ }
2181
+
2182
+ /* 15.2.10.5.23 */
2183
+ /*
2184
+ * call-seq:
2185
+ * String.new(str="") => new_str
2186
+ *
2187
+ * Returns a new string object containing a copy of *str*.
2188
+ */
2189
+ static mrb_value
2190
+ mrb_str_init(mrb_state *mrb, mrb_value self)
2191
+ {
2192
+ mrb_value str2;
2193
+
2194
+ if (mrb_get_args(mrb, "|S", &str2) == 0) {
2195
+ str2 = mrb_str_new(mrb, 0, 0);
2196
+ }
2197
+ str_replace(mrb, mrb_str_ptr(self), mrb_str_ptr(str2));
2198
+ return self;
2199
+ }
2200
+
2201
+ /* 15.2.10.5.25 */
2202
+ /* 15.2.10.5.41 */
2203
+ /*
2204
+ * call-seq:
2205
+ * str.intern => symbol
2206
+ * str.to_sym => symbol
2207
+ *
2208
+ * Returns the `Symbol` corresponding to *str*, creating the
2209
+ * symbol if it did not previously exist.
2210
+ *
2211
+ * "Koala".intern #=> :Koala
2212
+ * s = 'cat'.to_sym #=> :cat
2213
+ * s == :cat #=> true
2214
+ * s = '@cat'.to_sym #=> :@cat
2215
+ * s == :@cat #=> true
2216
+ *
2217
+ * This can also be used to create symbols that cannot be represented using the
2218
+ * `:xxx` notation.
2219
+ *
2220
+ * 'cat and dog'.to_sym #=> :"cat and dog"
2221
+ */
2222
+ /*
2223
+ * @param mrb The mruby state.
2224
+ * @param self The mruby string to convert to a symbol.
2225
+ * @return The mruby symbol corresponding to the string.
2226
+ *
2227
+ * Converts a mruby string to a symbol. If the symbol does not exist, it is created.
2228
+ */
2229
+ MRB_API mrb_value
2230
+ mrb_str_intern(mrb_state *mrb, mrb_value self)
2231
+ {
2232
+ return mrb_symbol_value(mrb_intern_str(mrb, self));
2233
+ }
2234
+ /* ---------------------------------- */
2235
+ /*
2236
+ * @param mrb The mruby state.
2237
+ * @param obj The mruby value to convert to a string.
2238
+ * @return The string representation of the mruby value.
2239
+ *
2240
+ * Converts any mruby object to its string representation.
2241
+ * For strings, it returns the object itself.
2242
+ * For symbols, it returns the symbol's name as a string.
2243
+ * For integers, it converts the integer to a string (base 10).
2244
+ * For classes/modules, it returns their name.
2245
+ * For other types, it calls the `to_s` method on the object.
2246
+ */
2247
+ MRB_API mrb_value
2248
+ mrb_obj_as_string(mrb_state *mrb, mrb_value obj)
2249
+ {
2250
+ switch (mrb_type(obj)) {
2251
+ case MRB_TT_STRING:
2252
+ return obj;
2253
+ case MRB_TT_SYMBOL:
2254
+ return mrb_sym_str(mrb, mrb_symbol(obj));
2255
+ case MRB_TT_INTEGER:
2256
+ return mrb_integer_to_str(mrb, obj, 10);
2257
+ case MRB_TT_SCLASS:
2258
+ case MRB_TT_CLASS:
2259
+ case MRB_TT_MODULE:
2260
+ return mrb_mod_to_s(mrb, obj);
2261
+ default:
2262
+ return mrb_type_convert(mrb, obj, MRB_TT_STRING, MRB_SYM(to_s));
2263
+ }
2264
+ }
2265
+
2266
+ /*
2267
+ * @param mrb The mruby state.
2268
+ * @param p The pointer to convert.
2269
+ * @return A new mruby string representing the pointer address.
2270
+ *
2271
+ * Converts a C pointer to a mruby string representation (e.g., "0x...").
2272
+ */
2273
+ MRB_API mrb_value
2274
+ mrb_ptr_to_str(mrb_state *mrb, void *p)
2275
+ {
2276
+ struct RString *p_str;
2277
+ char *p1;
2278
+ char *p2;
2279
+ uintptr_t n = (uintptr_t)p;
2280
+
2281
+ p_str = str_new(mrb, NULL, 2 + sizeof(uintptr_t) * CHAR_BIT / 4);
2282
+ p1 = RSTR_PTR(p_str);
2283
+ *p1++ = '0';
2284
+ *p1++ = 'x';
2285
+ p2 = p1;
2286
+
2287
+ do {
2288
+ *p2++ = mrb_digitmap[n % 16];
2289
+ n /= 16;
2290
+ } while (n > 0);
2291
+ *p2 = '\0';
2292
+ RSTR_SET_LEN(p_str, (mrb_int)(p2 - RSTR_PTR(p_str)));
2293
+
2294
+ while (p1 < p2) {
2295
+ const char c = *p1;
2296
+ *p1++ = *--p2;
2297
+ *p2 = c;
2298
+ }
2299
+
2300
+ return mrb_obj_value(p_str);
2301
+ }
2302
+
2303
+ static inline void
2304
+ str_reverse(char *p, char *e)
2305
+ {
2306
+ char c;
2307
+
2308
+ while (p < e) {
2309
+ c = *p;
2310
+ *p++ = *e;
2311
+ *e-- = c;
2312
+ }
2313
+ }
2314
+
2315
+ /* 15.2.10.5.30 */
2316
+ /*
2317
+ * call-seq:
2318
+ * str.reverse! => str
2319
+ *
2320
+ * Reverses *str* in place.
2321
+ */
2322
+ static mrb_value
2323
+ mrb_str_reverse_bang(mrb_state *mrb, mrb_value str)
2324
+ {
2325
+ struct RString *s = mrb_str_ptr(str);
2326
+ char *p, *e;
2327
+
2328
+ #ifdef MRB_UTF8_STRING
2329
+ mrb_int utf8_len = RSTRING_CHAR_LEN(str);
2330
+ mrb_int len = RSTR_LEN(s);
2331
+
2332
+ if (utf8_len < 2) return str;
2333
+ if (utf8_len < len) {
2334
+ mrb_str_modify(mrb, s);
2335
+ p = RSTR_PTR(s);
2336
+ e = p + RSTR_LEN(s);
2337
+ while (p<e) {
2338
+ mrb_int clen = mrb_utf8len(p, e);
2339
+ str_reverse(p, p + clen - 1);
2340
+ p += clen;
2341
+ }
2342
+ goto bytes;
2343
+ }
2344
+ #endif
2345
+
2346
+ if (RSTR_LEN(s) > 1) {
2347
+ mrb_str_modify(mrb, s);
2348
+ goto bytes;
2349
+ }
2350
+ return str;
2351
+
2352
+ bytes:
2353
+ p = RSTR_PTR(s);
2354
+ e = p + RSTR_LEN(s) - 1;
2355
+ str_reverse(p, e);
2356
+ return str;
2357
+ }
2358
+
2359
+ /* ---------------------------------- */
2360
+ /* 15.2.10.5.29 */
2361
+ /*
2362
+ * call-seq:
2363
+ * str.reverse => new_str
2364
+ *
2365
+ * Returns a new string with the characters from *str* in reverse order.
2366
+ *
2367
+ * "stressed".reverse #=> "desserts"
2368
+ */
2369
+ static mrb_value
2370
+ mrb_str_reverse(mrb_state *mrb, mrb_value str)
2371
+ {
2372
+ mrb_value str2 = mrb_str_dup(mrb, str);
2373
+ mrb_str_reverse_bang(mrb, str2);
2374
+ return str2;
2375
+ }
2376
+
2377
+ /*
2378
+ * call-seq:
2379
+ * byterindex(substring, offset = self.bytesize) -> integer or nil
2380
+ *
2381
+ * Returns the \Integer byte-based index of the _last_ occurrence of the given `substring`,
2382
+ * or `nil` if none found:
2383
+ *
2384
+ * 'foo'.byterindex('f') # => 0
2385
+ * 'foo'.byterindex('o') # => 2
2386
+ * 'foo'.byterindex('oo') # => 1
2387
+ * 'foo'.byterindex('ooo') # => nil
2388
+ */
2389
+ static mrb_value
2390
+ mrb_str_byterindex_m(mrb_state *mrb, mrb_value str)
2391
+ {
2392
+ mrb_int len = RSTRING_LEN(str);
2393
+ mrb_value sub;
2394
+ mrb_int pos;
2395
+
2396
+ if (mrb_get_args(mrb, "S|i", &sub, &pos) == 1) {
2397
+ pos = len;
2398
+ }
2399
+ else {
2400
+ if (pos < 0) {
2401
+ pos += len;
2402
+ if (pos < 0) {
2403
+ return mrb_nil_value();
2404
+ }
2405
+ }
2406
+ if (pos > len) pos = len;
2407
+ }
2408
+ pos = str_rindex(mrb, str, sub, pos);
2409
+ if (pos < 0) {
2410
+ return mrb_nil_value();
2411
+ }
2412
+ return mrb_int_value(mrb, pos);
2413
+ }
2414
+
2415
+ /* 15.2.10.5.31 */
2416
+ /*
2417
+ * call-seq:
2418
+ * str.rindex(substring [, offset]) => int or nil
2419
+ *
2420
+ * Returns the index of the last occurrence of the given *substring*.
2421
+ * Returns `nil` if not found. If the second parameter is
2422
+ * present, it specifies the position in the string to end the
2423
+ * search---characters beyond this point will not be considered.
2424
+ *
2425
+ * "hello".rindex('e') #=> 1
2426
+ * "hello".rindex('l') #=> 3
2427
+ * "hello".rindex('a') #=> nil
2428
+ * "hello".rindex('l', 2) #=> 2
2429
+ */
2430
+ #ifdef MRB_UTF8_STRING
2431
+ static mrb_value
2432
+ mrb_str_rindex_m(mrb_state *mrb, mrb_value str)
2433
+ {
2434
+ if (RSTR_SINGLE_BYTE_P(mrb_str_ptr(str))) {
2435
+ return mrb_str_byterindex_m(mrb, str);
2436
+ }
2437
+
2438
+ mrb_value sub;
2439
+ mrb_int pos;
2440
+
2441
+ if (mrb_get_args(mrb, "S|i", &sub, &pos) == 1) {
2442
+ pos = RSTRING_LEN(str);
2443
+ }
2444
+ else if (pos >= 0) {
2445
+ pos = chars2bytes(str, 0, pos);
2446
+ }
2447
+ else {
2448
+ const char *p = RSTRING_PTR(str);
2449
+ const char *e = RSTRING_END(str);
2450
+ while (pos++ < 0 && p < e) {
2451
+ e = char_backtrack(p, e);
2452
+ }
2453
+ if (p == e) return mrb_nil_value();
2454
+ pos = (mrb_int)(e - p);
2455
+ }
2456
+ pos = str_rindex(mrb, str, sub, pos);
2457
+ if (pos >= 0) {
2458
+ pos = bytes2chars(str, pos);
2459
+ if (pos < 0) return mrb_nil_value();
2460
+ return mrb_int_value(mrb, pos);
2461
+ }
2462
+ return mrb_nil_value();
2463
+ }
2464
+ #else
2465
+ #define mrb_str_rindex_m mrb_str_byterindex_m
2466
+ #endif
2467
+
2468
+ /* 15.2.10.5.35 */
2469
+
2470
+ /*
2471
+ * call-seq:
2472
+ * str.split(separator=nil, [limit]) => anArray
2473
+ *
2474
+ * Divides *str* into substrings based on a delimiter, returning an array
2475
+ * of these substrings.
2476
+ *
2477
+ * If *separator* is a `String`, then its contents are used as
2478
+ * the delimiter when splitting *str*. If *separator* is a single
2479
+ * space, *str* is split on whitespace, with leading whitespace and runs
2480
+ * of contiguous whitespace characters ignored.
2481
+ *
2482
+ * If *separator* is omitted or `nil` (which is the default),
2483
+ * *str* is split on whitespace as if ' ' were specified.
2484
+ *
2485
+ * If the *limit* parameter is omitted, trailing null fields are
2486
+ * suppressed. If *limit* is a positive number, at most that number of
2487
+ * fields will be returned (if *limit* is `1`, the entire
2488
+ * string is returned as the only entry in an array). If negative, there is no
2489
+ * limit to the number of fields returned, and trailing null fields are not
2490
+ * suppressed.
2491
+ *
2492
+ * " now's the time".split #=> ["now's", "the", "time"]
2493
+ * " now's the time".split(' ') #=> ["now's", "the", "time"]
2494
+ *
2495
+ * "mellow yellow".split("ello") #=> ["m", "w y", "w"]
2496
+ * "1,2,,3,4,,".split(',') #=> ["1", "2", "", "3", "4"]
2497
+ * "1,2,,3,4,,".split(',', 4) #=> ["1", "2", "", "3,4,,"]
2498
+ * "1,2,,3,4,,".split(',', -4) #=> ["1", "2", "", "3", "4", "", ""]
2499
+ */
2500
+
2501
+ static mrb_value
2502
+ mrb_str_split_m(mrb_state *mrb, mrb_value str)
2503
+ {
2504
+ mrb_value spat = mrb_nil_value();
2505
+ enum {awk, string} split_type = string;
2506
+ mrb_int i = 0;
2507
+ mrb_int lim = 0;
2508
+ mrb_value tmp;
2509
+
2510
+ mrb_int argc = mrb_get_args(mrb, "|oi", &spat, &lim);
2511
+ mrb_bool lim_p = (lim > 0 && argc == 2);
2512
+ if (argc == 2) {
2513
+ if (lim == 1) {
2514
+ if (RSTRING_LEN(str) == 0)
2515
+ return mrb_ary_new_capa(mrb, 0);
2516
+ return mrb_ary_new_from_values(mrb, 1, &str);
2517
+ }
2518
+ i = 1;
2519
+ }
2520
+
2521
+ if (argc == 0 || mrb_nil_p(spat)) {
2522
+ split_type = awk;
2523
+ }
2524
+ else if (!mrb_string_p(spat)) {
2525
+ mrb_raise(mrb, E_TYPE_ERROR, "expected String");
2526
+ }
2527
+ else if (RSTRING_LEN(spat) == 1 && RSTRING_PTR(spat)[0] == ' ') {
2528
+ split_type = awk;
2529
+ }
2530
+
2531
+ mrb_value result = mrb_ary_new(mrb);
2532
+ mrb_int beg = 0;
2533
+ if (split_type == awk) {
2534
+ mrb_bool skip = TRUE;
2535
+ mrb_int str_len = RSTRING_LEN(str);
2536
+ mrb_int idx = beg;
2537
+ mrb_int end = beg;
2538
+ int ai = mrb_gc_arena_save(mrb);
2539
+ unsigned int c;
2540
+
2541
+ while (idx < str_len) {
2542
+ c = (unsigned char)RSTRING_PTR(str)[idx++];
2543
+ if (skip) {
2544
+ if (ISSPACE(c)) {
2545
+ beg = idx;
2546
+ }
2547
+ else {
2548
+ end = idx;
2549
+ skip = FALSE;
2550
+ if (lim_p && lim <= i) break;
2551
+ }
2552
+ }
2553
+ else if (ISSPACE(c)) {
2554
+ mrb_ary_push(mrb, result, mrb_str_byte_subseq(mrb, str, beg, end-beg));
2555
+ mrb_gc_arena_restore(mrb, ai);
2556
+ skip = TRUE;
2557
+ beg = idx;
2558
+ if (lim_p) i++;
2559
+ }
2560
+ else {
2561
+ end = idx;
2562
+ }
2563
+ }
2564
+ }
2565
+ else { /* split_type == string */
2566
+ mrb_int str_len = RSTRING_LEN(str);
2567
+ mrb_int pat_len = RSTRING_LEN(spat);
2568
+ mrb_int idx = 0;
2569
+ int ai = mrb_gc_arena_save(mrb);
2570
+
2571
+ while (idx < str_len) {
2572
+ mrb_int end;
2573
+ if (pat_len > 0) {
2574
+ end = mrb_memsearch(RSTRING_PTR(spat), pat_len, RSTRING_PTR(str)+idx, str_len - idx);
2575
+ if (end < 0) break;
2576
+ }
2577
+ else {
2578
+ end = chars2bytes(str, idx, 1);
2579
+ }
2580
+ mrb_ary_push(mrb, result, mrb_str_byte_subseq(mrb, str, idx, end));
2581
+ mrb_gc_arena_restore(mrb, ai);
2582
+ idx += end + pat_len;
2583
+ if (lim_p && lim <= ++i) break;
2584
+ }
2585
+ beg = idx;
2586
+ }
2587
+ if (RSTRING_LEN(str) > 0 && (lim_p || RSTRING_LEN(str) > beg || lim < 0)) {
2588
+ if (RSTRING_LEN(str) == beg) {
2589
+ tmp = mrb_str_new(mrb, 0, 0);
2590
+ }
2591
+ else {
2592
+ tmp = mrb_str_byte_subseq(mrb, str, beg, RSTRING_LEN(str)-beg);
2593
+ }
2594
+ mrb_ary_push(mrb, result, tmp);
2595
+ }
2596
+ if (!lim_p && lim == 0) {
2597
+ mrb_int len;
2598
+ while ((len = RARRAY_LEN(result)) > 0 &&
2599
+ (tmp = RARRAY_PTR(result)[len-1], RSTRING_LEN(tmp) == 0))
2600
+ mrb_ary_pop(mrb, result);
2601
+ }
2602
+
2603
+ return result;
2604
+ }
2605
+
2606
+ static mrb_bool
2607
+ trailingbad(const char *str, const char *p, const char *pend)
2608
+ {
2609
+ if (p == str) return TRUE; /* no number */
2610
+ if (*(p - 1) == '_') return TRUE; /* trailing '_' */
2611
+ while (p<pend && ISSPACE(*p)) p++;
2612
+ if (p<pend) return TRUE; /* trailing garbage */
2613
+ return FALSE;
2614
+ }
2615
+
2616
+ static mrb_value
2617
+ mrb_str_len_to_integer(mrb_state *mrb, const char *str, size_t len, mrb_int base, int badcheck)
2618
+ {
2619
+ const char *p = str;
2620
+ const char *pend = str + len;
2621
+ #ifdef MRB_USE_BIGINT
2622
+ const char *p2 = NULL;
2623
+ #endif
2624
+ char sign = 1;
2625
+ int c;
2626
+ mrb_int n = 0;
2627
+ mrb_int val;
2628
+
2629
+ #define conv_digit(c) \
2630
+ (ISDIGIT(c) ? ((c) - '0') : \
2631
+ ISLOWER(c) ? ((c) - 'a' + 10) : \
2632
+ ISUPPER(c) ? ((c) - 'A' + 10) : \
2633
+ -1)
2634
+
2635
+ if (!p) {
2636
+ if (badcheck) goto bad;
2637
+ return mrb_fixnum_value(0);
2638
+ }
2639
+ while (p<pend && ISSPACE(*p))
2640
+ p++;
2641
+
2642
+ if (p[0] == '+') {
2643
+ p++;
2644
+ }
2645
+ else if (p[0] == '-') {
2646
+ p++;
2647
+ sign = 0;
2648
+ }
2649
+ if (base <= 0) {
2650
+ if (p[0] == '0') {
2651
+ switch (p[1]) {
2652
+ case 'x': case 'X':
2653
+ base = 16;
2654
+ break;
2655
+ case 'b': case 'B':
2656
+ base = 2;
2657
+ break;
2658
+ case 'o': case 'O':
2659
+ base = 8;
2660
+ break;
2661
+ case 'd': case 'D':
2662
+ base = 10;
2663
+ break;
2664
+ default:
2665
+ base = 8;
2666
+ break;
2667
+ }
2668
+ }
2669
+ else if (base < -1) {
2670
+ base = -base;
2671
+ }
2672
+ else {
2673
+ base = 10;
2674
+ }
2675
+ }
2676
+ switch (base) {
2677
+ case 2:
2678
+ if (p[0] == '0' && (p[1] == 'b'||p[1] == 'B')) {
2679
+ p += 2;
2680
+ }
2681
+ break;
2682
+ case 3:
2683
+ break;
2684
+ case 8:
2685
+ if (p[0] == '0' && (p[1] == 'o'||p[1] == 'O')) {
2686
+ p += 2;
2687
+ }
2688
+ case 4: case 5: case 6: case 7:
2689
+ break;
2690
+ case 10:
2691
+ if (p[0] == '0' && (p[1] == 'd'||p[1] == 'D')) {
2692
+ p += 2;
2693
+ }
2694
+ case 9: case 11: case 12: case 13: case 14: case 15:
2695
+ break;
2696
+ case 16:
2697
+ if (p[0] == '0' && (p[1] == 'x'||p[1] == 'X')) {
2698
+ p += 2;
2699
+ }
2700
+ break;
2701
+ default:
2702
+ if (base < 2 || 36 < base) {
2703
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %i", base);
2704
+ }
2705
+ break;
2706
+ } /* end of switch (base) { */
2707
+ if (p>=pend) {
2708
+ if (badcheck) goto bad;
2709
+ return mrb_fixnum_value(0);
2710
+ }
2711
+ if (*p == '0') { /* squeeze preceding 0s */
2712
+ p++;
2713
+ while (p<pend) {
2714
+ c = *p++;
2715
+ if (c == '_') {
2716
+ if (p<pend && *p == '_') {
2717
+ if (badcheck) goto bad;
2718
+ break;
2719
+ }
2720
+ continue;
2721
+ }
2722
+ if (c != '0') {
2723
+ p--;
2724
+ break;
2725
+ }
2726
+ }
2727
+ if (*(p - 1) == '0')
2728
+ p--;
2729
+ }
2730
+ if (p == pend || *p == '_') {
2731
+ if (badcheck) goto bad;
2732
+ return mrb_fixnum_value(0);
2733
+ }
2734
+ #ifdef MRB_USE_BIGINT
2735
+ p2 = p;
2736
+ #endif
2737
+ for (;p<pend; p++) {
2738
+ if (*p == '_') {
2739
+ p++;
2740
+ if (p==pend) {
2741
+ if (badcheck) goto bad;
2742
+ continue;
2743
+ }
2744
+ if (*p == '_') {
2745
+ if (badcheck) goto bad;
2746
+ break;
2747
+ }
2748
+ }
2749
+ if (badcheck && *p == '\0') {
2750
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string contains null byte");
2751
+ }
2752
+ c = conv_digit(*p);
2753
+ if (c < 0 || c >= base) {
2754
+ break;
2755
+ }
2756
+ if (mrb_int_mul_overflow(n, base, &n)) goto overflow;
2757
+ if (MRB_INT_MAX - c < n) {
2758
+ if (sign == 0 && MRB_INT_MAX - n == c - 1) {
2759
+ n = MRB_INT_MIN;
2760
+ sign = 1;
2761
+ break;
2762
+ }
2763
+ overflow:
2764
+ #ifdef MRB_USE_BIGINT
2765
+ ;
2766
+ const char *p3 = p2;
2767
+ while (p3 < pend) {
2768
+ char c = TOLOWER(*p3);
2769
+ const char *p4 = strchr(mrb_digitmap, c);
2770
+ if (p4 == NULL && c != '_') break;
2771
+ if (p4 - mrb_digitmap >= base) break;
2772
+ p3++;
2773
+ }
2774
+ if (badcheck && trailingbad(str, p, pend)) goto bad;
2775
+ return mrb_bint_new_str(mrb, p2, (mrb_int)(p3-p2), sign ? base : -base);
2776
+ #else
2777
+ mrb_raisef(mrb, E_RANGE_ERROR, "string (%l) too big for integer", str, pend-str);
2778
+ #endif
2779
+ }
2780
+ n += c;
2781
+ }
2782
+ val = (mrb_int)n;
2783
+ if (badcheck && trailingbad(str, p, pend)) goto bad;
2784
+ return mrb_int_value(mrb, sign ? val : -val);
2785
+ bad:
2786
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for number(%!l)", str, pend-str);
2787
+ /* not reached */
2788
+ return mrb_fixnum_value(0);
2789
+ }
2790
+
2791
+ /* obsolete: use RSTRING_CSTR() or mrb_string_cstr() */
2792
+ /*
2793
+ * @deprecated Use `RSTRING_CSTR()` or `mrb_string_cstr()` instead.
2794
+ * @param mrb The mruby state.
2795
+ * @param ptr Pointer to the mruby string value.
2796
+ * @return A pointer to a null-terminated C string.
2797
+ *
2798
+ * Ensures the mruby string pointed to by `ptr` is a string and returns its
2799
+ * C string representation. If the string contains null bytes, it raises an
2800
+ * E_ARGUMENT_ERROR. If the string is not null-terminated, it modifies the
2801
+ * string in place to add a null terminator (this might involve unsharing
2802
+ * the string buffer).
2803
+ */
2804
+ MRB_API const char*
2805
+ mrb_string_value_cstr(mrb_state *mrb, mrb_value *ptr)
2806
+ {
2807
+ struct RString *ps;
2808
+ const char *p;
2809
+ mrb_int len;
2810
+
2811
+ mrb_ensure_string_type(mrb, *ptr);
2812
+ ps = mrb_str_ptr(*ptr);
2813
+ check_null_byte(mrb, ps);
2814
+ p = RSTR_PTR(ps);
2815
+ len = RSTR_LEN(ps);
2816
+ if (p == NULL) return "";
2817
+ if (p[len] == '\0') {
2818
+ return p;
2819
+ }
2820
+
2821
+ /*
2822
+ * Even after str_modify_keep_ascii(), NULL termination is not ensured if
2823
+ * RSTR_SET_LEN() is used explicitly (e.g. String#delete_suffix!).
2824
+ */
2825
+ str_unshare_buffer(mrb, ps);
2826
+ RSTR_PTR(ps)[len] = '\0';
2827
+ return RSTR_PTR(ps);
2828
+ }
2829
+
2830
+ /*
2831
+ * @param mrb The mruby state.
2832
+ * @param str The mruby string value.
2833
+ * @return A pointer to a null-terminated C string.
2834
+ *
2835
+ * Ensures the mruby string `str` is a string and returns its C string representation.
2836
+ * This is a convenience wrapper around `mrb_string_value_cstr`.
2837
+ * If the string contains null bytes, it raises an E_ARGUMENT_ERROR.
2838
+ * If the string is not null-terminated, it modifies the string in place
2839
+ * to add a null terminator.
2840
+ */
2841
+ MRB_API const char*
2842
+ mrb_string_cstr(mrb_state *mrb, mrb_value str)
2843
+ {
2844
+ return mrb_string_value_cstr(mrb, &str);
2845
+ }
2846
+
2847
+ /*
2848
+ * @param mrb The mruby state.
2849
+ * @param str The mruby string to convert.
2850
+ * @param base The base for conversion (0 or 2-36).
2851
+ * @param badcheck If `TRUE`, raise an error on invalid input; otherwise, return 0.
2852
+ * @return An mruby integer value.
2853
+ *
2854
+ * Converts an mruby string to an mruby integer.
2855
+ * Interprets leading characters in `str` as an integer of the specified `base`.
2856
+ * If `base` is 0, it auto-detects the base (0x for hex, 0b for binary, 0o or 0 for octal, else decimal).
2857
+ * If `badcheck` is true, invalid characters will raise an `E_ARGUMENT_ERROR`.
2858
+ * Otherwise, extraneous characters are ignored, and 0 is returned for invalid numbers.
2859
+ */
2860
+ MRB_API mrb_value
2861
+ mrb_str_to_integer(mrb_state *mrb, mrb_value str, mrb_int base, mrb_bool badcheck)
2862
+ {
2863
+ mrb_ensure_string_type(mrb, str);
2864
+ const char *s = RSTRING_PTR(str);
2865
+ mrb_int len = RSTRING_LEN(str);
2866
+ return mrb_str_len_to_integer(mrb, s, len, base, badcheck);
2867
+ }
2868
+
2869
+ /* 15.2.10.5.38 */
2870
+ /*
2871
+ * call-seq:
2872
+ * str.to_i(base=10) => integer
2873
+ *
2874
+ * Returns the result of interpreting leading characters in *str* as an
2875
+ * integer base *base* (between 2 and 36). Extraneous characters past the
2876
+ * end of a valid number are ignored. If there is not a valid number at the
2877
+ * start of *str*, `0` is returned. This method never raises an
2878
+ * exception.
2879
+ *
2880
+ * "12345".to_i #=> 12345
2881
+ * "99 red balloons".to_i #=> 99
2882
+ * "0a".to_i #=> 0
2883
+ * "0a".to_i(16) #=> 10
2884
+ * "hello".to_i #=> 0
2885
+ * "1100101".to_i(2) #=> 101
2886
+ * "1100101".to_i(8) #=> 294977
2887
+ * "1100101".to_i(10) #=> 1100101
2888
+ * "1100101".to_i(16) #=> 17826049
2889
+ */
2890
+ static mrb_value
2891
+ mrb_str_to_i(mrb_state *mrb, mrb_value self)
2892
+ {
2893
+ mrb_int base = 10;
2894
+
2895
+ mrb_get_args(mrb, "|i", &base);
2896
+ if (base < 0 || 36 < base) {
2897
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal radix %i", base);
2898
+ }
2899
+ return mrb_str_to_integer(mrb, self, base, FALSE);
2900
+ }
2901
+
2902
+ #ifndef MRB_NO_FLOAT
2903
+ /* Internal helper for mrb_str_to_dbl */
2904
+ static double
2905
+ mrb_str_len_to_dbl(mrb_state *mrb, const char *s, size_t len, mrb_bool badcheck)
2906
+ {
2907
+ char buf[DBL_DIG * 4 + 20];
2908
+ const char *p = s, *p2;
2909
+ const char *pend = p + len;
2910
+ char *end;
2911
+ char *n;
2912
+ char prev = 0;
2913
+ double d;
2914
+ mrb_bool dot = FALSE;
2915
+
2916
+ if (!p) return 0.0;
2917
+ while (p<pend && ISSPACE(*p)) p++;
2918
+ p2 = p;
2919
+
2920
+ if (pend - p > 2 && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
2921
+ mrb_value x;
2922
+
2923
+ if (!badcheck) return 0.0;
2924
+ x = mrb_str_len_to_integer(mrb, p, pend-p, 0, badcheck);
2925
+ if (mrb_integer_p(x))
2926
+ d = (double)mrb_integer(x);
2927
+ else /* if (mrb_float_p(x)) */
2928
+ d = mrb_float(x);
2929
+ return d;
2930
+ }
2931
+ while (p < pend) {
2932
+ if (!*p) {
2933
+ if (badcheck) {
2934
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string for Float contains null byte");
2935
+ /* not reached */
2936
+ }
2937
+ pend = p;
2938
+ p = p2;
2939
+ goto nocopy;
2940
+ }
2941
+ if (!badcheck && *p == ' ') {
2942
+ pend = p;
2943
+ p = p2;
2944
+ goto nocopy;
2945
+ }
2946
+ if (*p == '_') break;
2947
+ p++;
2948
+ }
2949
+ p = p2;
2950
+ n = buf;
2951
+ while (p < pend) {
2952
+ char c = *p++;
2953
+ if (c == '.') dot = TRUE;
2954
+ if (c == '_') {
2955
+ /* remove an underscore between digits */
2956
+ if (n == buf || !ISDIGIT(prev) || p == pend) {
2957
+ if (badcheck) goto bad;
2958
+ break;
2959
+ }
2960
+ }
2961
+ else if (badcheck && prev == '_' && !ISDIGIT(c)) goto bad;
2962
+ else {
2963
+ const char *bend = buf+sizeof(buf)-1;
2964
+ if (n==bend) { /* buffer overflow */
2965
+ if (dot) break; /* cut off remaining fractions */
2966
+ return INFINITY;
2967
+ }
2968
+ *n++ = c;
2969
+ }
2970
+ prev = c;
2971
+ }
2972
+ *n = '\0';
2973
+ p = buf;
2974
+ pend = n;
2975
+ nocopy:
2976
+ if (mrb_read_float(p, &end, &d) == FALSE) {
2977
+ if (badcheck) {
2978
+ bad:
2979
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid string for float(%!s)", s);
2980
+ /* not reached */
2981
+ }
2982
+ return 0.0;
2983
+ }
2984
+ if (badcheck) {
2985
+ if (!end || p == end) goto bad;
2986
+ while (end<pend && ISSPACE(*end)) end++;
2987
+ if (end<pend) goto bad;
2988
+ }
2989
+ return d;
2990
+ }
2991
+
2992
+ /*
2993
+ * @param mrb The mruby state.
2994
+ * @param str The mruby string to convert.
2995
+ * @param badcheck If `TRUE`, raise an error on invalid input; otherwise, return 0.0.
2996
+ * @return A C double value.
2997
+ *
2998
+ * Converts an mruby string to a C double.
2999
+ * Interprets leading characters in `str` as a floating-point number.
3000
+ * If `badcheck` is true, invalid characters will raise an `E_ARGUMENT_ERROR`.
3001
+ * Otherwise, extraneous characters are ignored, and 0.0 is returned for invalid numbers.
3002
+ */
3003
+ MRB_API double
3004
+ mrb_str_to_dbl(mrb_state *mrb, mrb_value str, mrb_bool badcheck)
3005
+ {
3006
+ return mrb_str_len_to_dbl(mrb, RSTRING_PTR(str), RSTRING_LEN(str), badcheck);
3007
+ }
3008
+
3009
+ /* 15.2.10.5.39 */
3010
+ /*
3011
+ * call-seq:
3012
+ * str.to_f => float
3013
+ *
3014
+ * Returns the result of interpreting leading characters in *str* as a
3015
+ * floating-point number. Extraneous characters past the end of a valid number
3016
+ * are ignored. If there is not a valid number at the start of *str*,
3017
+ * `0.0` is returned. This method never raises an exception.
3018
+ *
3019
+ * "123.45e1".to_f #=> 1234.5
3020
+ * "45.67 degrees".to_f #=> 45.67
3021
+ * "thx1138".to_f #=> 0.0
3022
+ */
3023
+ static mrb_value
3024
+ mrb_str_to_f(mrb_state *mrb, mrb_value self)
3025
+ {
3026
+ return mrb_float_value(mrb, mrb_str_to_dbl(mrb, self, FALSE));
3027
+ }
3028
+ #endif
3029
+
3030
+ /* 15.2.10.5.40 */
3031
+ /*
3032
+ * call-seq:
3033
+ * str.to_s => str
3034
+ *
3035
+ * Returns the receiver.
3036
+ */
3037
+ static mrb_value
3038
+ mrb_str_to_s(mrb_state *mrb, mrb_value self)
3039
+ {
3040
+ if (mrb_obj_class(mrb, self) != mrb->string_class) {
3041
+ return mrb_str_dup(mrb, self);
3042
+ }
3043
+ return self;
3044
+ }
3045
+
3046
+ /* 15.2.10.5.43 */
3047
+ /*
3048
+ * call-seq:
3049
+ * str.upcase! => str or nil
3050
+ *
3051
+ * Upcases the contents of *str*, returning `nil` if no changes
3052
+ * were made.
3053
+ */
3054
+ static mrb_value
3055
+ mrb_str_upcase_bang(mrb_state *mrb, mrb_value str)
3056
+ {
3057
+ struct RString *s = mrb_str_ptr(str);
3058
+ char *p, *pend;
3059
+ mrb_bool modify = FALSE;
3060
+
3061
+ mrb_str_modify_keep_ascii(mrb, s);
3062
+ p = RSTRING_PTR(str);
3063
+ pend = RSTRING_END(str);
3064
+ while (p < pend) {
3065
+ if (ISLOWER(*p)) {
3066
+ *p = TOUPPER(*p);
3067
+ modify = TRUE;
3068
+ }
3069
+ p++;
3070
+ }
3071
+
3072
+ if (modify) return str;
3073
+ return mrb_nil_value();
3074
+ }
3075
+
3076
+ /* 15.2.10.5.42 */
3077
+ /*
3078
+ * call-seq:
3079
+ * str.upcase => new_str
3080
+ *
3081
+ * Returns a copy of *str* with all lowercase letters replaced with their
3082
+ * uppercase counterparts. The operation is locale insensitive---only
3083
+ * characters 'a' to 'z' are affected.
3084
+ *
3085
+ * "hEllO".upcase #=> "HELLO"
3086
+ */
3087
+ static mrb_value
3088
+ mrb_str_upcase(mrb_state *mrb, mrb_value self)
3089
+ {
3090
+ mrb_value str = mrb_str_dup(mrb, self);
3091
+ mrb_str_upcase_bang(mrb, str);
3092
+ return str;
3093
+ }
3094
+
3095
+ /*
3096
+ * call-seq:
3097
+ * str.dump -> new_str
3098
+ *
3099
+ * Produces a version of *str* with all nonprinting characters replaced by
3100
+ * `\nnn` notation and all special characters escaped.
3101
+ */
3102
+ mrb_value
3103
+ mrb_str_dump(mrb_state *mrb, mrb_value str)
3104
+ {
3105
+ return str_escape(mrb, str, FALSE);
3106
+ }
3107
+
3108
+ /*
3109
+ * @param mrb The mruby state.
3110
+ * @param str The mruby string to append to (modified in place).
3111
+ * @param ptr A pointer to the C string to append.
3112
+ * @param len The length of the C string to append.
3113
+ * @return The modified mruby string `str`.
3114
+ *
3115
+ * Appends a C string of a given length to an mruby string.
3116
+ * The mruby string `str` is modified in place. Handles resizing and
3117
+ * potential overlap if `ptr` is within `str`'s buffer.
3118
+ */
3119
+ MRB_API mrb_value
3120
+ mrb_str_cat(mrb_state *mrb, mrb_value str, const char *ptr, size_t len)
3121
+ {
3122
+ struct RString *s = mrb_str_ptr(str);
3123
+ ptrdiff_t off = -1;
3124
+
3125
+ if (len == 0) return str;
3126
+ mrb_str_modify(mrb, s);
3127
+ if (ptr >= RSTR_PTR(s) && ptr <= RSTR_PTR(s) + (size_t)RSTR_LEN(s)) {
3128
+ off = ptr - RSTR_PTR(s);
3129
+ }
3130
+
3131
+ mrb_int capa = RSTR_CAPA(s);
3132
+ mrb_int total;
3133
+ if (mrb_int_add_overflow(RSTR_LEN(s), len, &total)) {
3134
+ size_error:
3135
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "string size too big");
3136
+ }
3137
+ if (capa <= total) {
3138
+ if (capa == 0) capa = 1;
3139
+ while (capa <= total) {
3140
+ if (mrb_int_mul_overflow(capa, 2, &capa)) goto size_error;
3141
+ }
3142
+ resize_capa(mrb, s, capa);
3143
+ }
3144
+ if (off != -1) {
3145
+ ptr = RSTR_PTR(s) + off;
3146
+ }
3147
+ memcpy(RSTR_PTR(s) + RSTR_LEN(s), ptr, len);
3148
+ RSTR_SET_LEN(s, total);
3149
+ RSTR_PTR(s)[total] = '\0'; /* sentinel */
3150
+ return str;
3151
+ }
3152
+
3153
+ /*
3154
+ * @param mrb The mruby state.
3155
+ * @param str The mruby string to append to (modified in place).
3156
+ * @param ptr A pointer to the null-terminated C string to append.
3157
+ * @return The modified mruby string `str`.
3158
+ *
3159
+ * Appends a null-terminated C string to an mruby string.
3160
+ * The mruby string `str` is modified in place.
3161
+ */
3162
+ MRB_API mrb_value
3163
+ mrb_str_cat_cstr(mrb_state *mrb, mrb_value str, const char *ptr)
3164
+ {
3165
+ return mrb_str_cat(mrb, str, ptr, ptr ? strlen(ptr) : 0);
3166
+ }
3167
+
3168
+ /*
3169
+ * @param mrb The mruby state.
3170
+ * @param str The mruby string to append to (modified in place).
3171
+ * @param str2 The mruby string to append.
3172
+ * @return The modified mruby string `str`.
3173
+ *
3174
+ * Appends an mruby string (`str2`) to another mruby string (`str`).
3175
+ * The mruby string `str` is modified in place. Handles self-appendage.
3176
+ */
3177
+ MRB_API mrb_value
3178
+ mrb_str_cat_str(mrb_state *mrb, mrb_value str, mrb_value str2)
3179
+ {
3180
+ if (mrb_str_ptr(str) == mrb_str_ptr(str2)) {
3181
+ mrb_str_modify(mrb, mrb_str_ptr(str));
3182
+ }
3183
+ return mrb_str_cat(mrb, str, RSTRING_PTR(str2), RSTRING_LEN(str2));
3184
+ }
3185
+
3186
+ /*
3187
+ * @param mrb The mruby state.
3188
+ * @param str1 The mruby string to append to (modified in place).
3189
+ * @param str2 The mruby value to append (will be converted to a string if not already one).
3190
+ * @return The modified mruby string `str1`.
3191
+ *
3192
+ * Appends an mruby value (`str2`) to an mruby string (`str1`).
3193
+ * `str2` is first ensured to be a string (converted if necessary).
3194
+ * Then, `str1` is modified in place. This is similar to `mrb_str_concat`
3195
+ * but `mrb_str_concat` takes `self` and `other` as parameters.
3196
+ */
3197
+ MRB_API mrb_value
3198
+ mrb_str_append(mrb_state *mrb, mrb_value str1, mrb_value str2)
3199
+ {
3200
+ mrb_ensure_string_type(mrb, str2);
3201
+ return mrb_str_cat_str(mrb, str1, str2);
3202
+ }
3203
+
3204
+ /*
3205
+ * call-seq:
3206
+ * str.inspect -> string
3207
+ *
3208
+ * Returns a printable version of _str_, surrounded by quote marks,
3209
+ * with special characters escaped.
3210
+ *
3211
+ * str = "hello"
3212
+ * str[3] = "\b"
3213
+ * str.inspect #=> "\"hel\\bo\""
3214
+ */
3215
+ /*
3216
+ * @param mrb The mruby state.
3217
+ * @param str The mruby string to inspect.
3218
+ * @return A new mruby string that is the inspect-representation of `str`.
3219
+ *
3220
+ * Returns a human-readable, printable version of the string, typically
3221
+ * surrounded by quotes and with special characters escaped.
3222
+ * UTF-8 characters are preserved if `MRB_UTF8_STRING` is defined and `inspect` is true.
3223
+ */
3224
+ mrb_value
3225
+ mrb_str_inspect(mrb_state *mrb, mrb_value str)
3226
+ {
3227
+ return str_escape(mrb, str, TRUE);
3228
+ }
3229
+
3230
+ /*
3231
+ * call-seq:
3232
+ * str.bytes -> array of int
3233
+ *
3234
+ * Returns an array of bytes in _str_.
3235
+ *
3236
+ * str = "hello"
3237
+ * str.bytes #=> [104, 101, 108, 108, 111]
3238
+ */
3239
+ static mrb_value
3240
+ mrb_str_bytes(mrb_state *mrb, mrb_value str)
3241
+ {
3242
+ struct RString *s = mrb_str_ptr(str);
3243
+ mrb_value a = mrb_ary_new_capa(mrb, RSTR_LEN(s));
3244
+ unsigned char *p = (unsigned char*)(RSTR_PTR(s)), *pend = p + RSTR_LEN(s);
3245
+
3246
+ while (p < pend) {
3247
+ mrb_ary_push(mrb, a, mrb_fixnum_value(p[0]));
3248
+ p++;
3249
+ }
3250
+ return a;
3251
+ }
3252
+
3253
+ /*
3254
+ * call-seq:
3255
+ * str.getbyte(index) -> 0 .. 255
3256
+ *
3257
+ * returns the *index*th byte as an integer.
3258
+ */
3259
+ static mrb_value
3260
+ mrb_str_getbyte(mrb_state *mrb, mrb_value str)
3261
+ {
3262
+ mrb_int pos;
3263
+ mrb_get_args(mrb, "i", &pos);
3264
+
3265
+ if (pos < 0)
3266
+ pos += RSTRING_LEN(str);
3267
+ if (pos < 0 || RSTRING_LEN(str) <= pos)
3268
+ return mrb_nil_value();
3269
+
3270
+ return mrb_fixnum_value((unsigned char)RSTRING_PTR(str)[pos]);
3271
+ }
3272
+
3273
+ /*
3274
+ * call-seq:
3275
+ * str.setbyte(index, integer) -> integer
3276
+ *
3277
+ * modifies the *index*th byte as *integer*.
3278
+ */
3279
+ static mrb_value
3280
+ mrb_str_setbyte(mrb_state *mrb, mrb_value str)
3281
+ {
3282
+ mrb_int pos, byte;
3283
+
3284
+ mrb_get_args(mrb, "ii", &pos, &byte);
3285
+
3286
+ mrb_int len = RSTRING_LEN(str);
3287
+ if (pos < -len || len <= pos)
3288
+ mrb_raisef(mrb, E_INDEX_ERROR, "index %i out of string", pos);
3289
+ if (pos < 0)
3290
+ pos += len;
3291
+
3292
+ mrb_str_modify(mrb, mrb_str_ptr(str));
3293
+ byte &= 0xff;
3294
+ RSTRING_PTR(str)[pos] = (unsigned char)byte;
3295
+ return mrb_fixnum_value((unsigned char)byte);
3296
+ }
3297
+
3298
+ /*
3299
+ * call-seq:
3300
+ * str.byteslice(integer) -> new_str or nil
3301
+ * str.byteslice(integer, integer) -> new_str or nil
3302
+ * str.byteslice(range) -> new_str or nil
3303
+ *
3304
+ * Byte Reference---If passed a single Integer, returns a
3305
+ * substring of one byte at that position. If passed two Integer
3306
+ * objects, returns a substring starting at the offset given by the first, and
3307
+ * a length given by the second. If given a Range, a substring containing
3308
+ * bytes at offsets given by the range is returned. In all three cases, if
3309
+ * an offset is negative, it is counted from the end of *str*. Returns
3310
+ * `nil` if the initial offset falls outside the string, the length
3311
+ * is negative, or the beginning of the range is greater than the end.
3312
+ * The encoding of the resulted string keeps original encoding.
3313
+ *
3314
+ * "hello".byteslice(1) #=> "e"
3315
+ * "hello".byteslice(-1) #=> "o"
3316
+ * "hello".byteslice(1, 2) #=> "el"
3317
+ * "\x80\u3042".byteslice(1, 3) #=> "\u3042"
3318
+ * "\x03\u3042\xff".byteslice(1..3) #=> "\u3042"
3319
+ */
3320
+ static mrb_value
3321
+ mrb_str_byteslice(mrb_state *mrb, mrb_value str)
3322
+ {
3323
+ mrb_value a1;
3324
+ mrb_int str_len, beg, len;
3325
+ mrb_bool empty = TRUE;
3326
+
3327
+ len = mrb_get_argc(mrb);
3328
+ switch (len) {
3329
+ case 2:
3330
+ mrb_get_args(mrb, "ii", &beg, &len);
3331
+ str_len = RSTRING_LEN(str);
3332
+ break;
3333
+ case 1:
3334
+ a1 = mrb_get_arg1(mrb);
3335
+ str_len = RSTRING_LEN(str);
3336
+ if (mrb_range_p(a1)) {
3337
+ if (mrb_range_beg_len(mrb, a1, &beg, &len, str_len, TRUE) != MRB_RANGE_OK) {
3338
+ return mrb_nil_value();
3339
+ }
3340
+ }
3341
+ else {
3342
+ beg = mrb_as_int(mrb, a1);
3343
+ len = 1;
3344
+ empty = FALSE;
3345
+ }
3346
+ break;
3347
+ default:
3348
+ mrb_argnum_error(mrb, len, 1, 2);
3349
+ break;
3350
+ }
3351
+ if (mrb_str_beg_len(str_len, &beg, &len) && (empty || len != 0)) {
3352
+ return mrb_str_byte_subseq(mrb, str, beg, len);
3353
+ }
3354
+ else {
3355
+ return mrb_nil_value();
3356
+ }
3357
+ }
3358
+
3359
+ static mrb_value
3360
+ sub_replace(mrb_state *mrb, mrb_value self)
3361
+ {
3362
+ char *p, *match;
3363
+ mrb_int plen, mlen;
3364
+ mrb_int found, offset;
3365
+
3366
+ mrb_get_args(mrb, "ssi", &p, &plen, &match, &mlen, &found);
3367
+ if (found < 0 || RSTRING_LEN(self) < found) {
3368
+ mrb_raise(mrb, E_RUNTIME_ERROR, "argument out of range");
3369
+ }
3370
+ mrb_value result = mrb_str_new(mrb, 0, 0);
3371
+ for (mrb_int i=0; i<plen; i++) {
3372
+ if (p[i] != '\\' || i+1==plen) {
3373
+ mrb_str_cat(mrb, result, p+i, 1);
3374
+ continue;
3375
+ }
3376
+ i++;
3377
+ switch (p[i]) {
3378
+ case '\\':
3379
+ mrb_str_cat(mrb, result, "\\", 1);
3380
+ break;
3381
+ case '`':
3382
+ mrb_str_cat(mrb, result, RSTRING_PTR(self), found);
3383
+ break;
3384
+ case '&': case '0':
3385
+ mrb_str_cat(mrb, result, match, mlen);
3386
+ break;
3387
+ case '\'':
3388
+ offset = found + mlen;
3389
+ if (RSTRING_LEN(self) > offset) {
3390
+ mrb_str_cat(mrb, result, RSTRING_PTR(self)+offset, RSTRING_LEN(self)-offset);
3391
+ }
3392
+ break;
3393
+ case '1': case '2': case '3':
3394
+ case '4': case '5': case '6':
3395
+ case '7': case '8': case '9':
3396
+ /* ignore sub-group match (no Regexp supported) */
3397
+ break;
3398
+ default:
3399
+ mrb_str_cat(mrb, result, &p[i-1], 2);
3400
+ break;
3401
+ }
3402
+ }
3403
+ return result;
3404
+ }
3405
+
3406
+
3407
+ static mrb_value
3408
+ str_bytesplice(mrb_state *mrb, mrb_value str, mrb_int idx1, mrb_int len1, mrb_value replace, mrb_int idx2, mrb_int len2)
3409
+ {
3410
+ struct RString *s = RSTRING(str);
3411
+ if (idx1 < 0) {
3412
+ idx1 += RSTR_LEN(s);
3413
+ }
3414
+ if (idx2 < 0) {
3415
+ idx2 += RSTRING_LEN(replace);
3416
+ }
3417
+ if (RSTR_LEN(s) < idx1 || idx1 < 0 || RSTRING_LEN(replace) < idx2 || idx2 < 0) {
3418
+ mrb_raise(mrb, E_INDEX_ERROR, "index out of string");
3419
+ }
3420
+ if (len1 < 0 || len2 < 0) {
3421
+ mrb_raise(mrb, E_INDEX_ERROR, "negative length");
3422
+ }
3423
+ mrb_int n;
3424
+ if (mrb_int_add_overflow(idx1, len1, &n) || RSTR_LEN(s) < n) {
3425
+ len1 = RSTR_LEN(s) - idx1;
3426
+ }
3427
+ if (mrb_int_add_overflow(idx2, len2, &n) || RSTRING_LEN(replace) < n) {
3428
+ len2 = RSTRING_LEN(replace) - idx2;
3429
+ }
3430
+ mrb_str_modify(mrb, s);
3431
+ if (len1 >= len2) {
3432
+ memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);
3433
+ if (len1 > len2) {
3434
+ memmove(RSTR_PTR(s)+idx1+len2, RSTR_PTR(s)+idx1+len1, RSTR_LEN(s)-(idx1+len1));
3435
+ RSTR_SET_LEN(s, RSTR_LEN(s)-(len1-len2));
3436
+ }
3437
+ }
3438
+ else { /* len1 < len2 */
3439
+ mrb_int slen = RSTR_LEN(s);
3440
+ mrb_str_resize(mrb, str, slen+len2-len1);
3441
+ memmove(RSTR_PTR(s)+idx1+len2, RSTR_PTR(s)+idx1+len1, slen-(idx1+len1));
3442
+ memmove(RSTR_PTR(s)+idx1, RSTRING_PTR(replace)+idx2, len2);
3443
+ }
3444
+ return str;
3445
+ }
3446
+
3447
+ /*
3448
+ * call-seq:
3449
+ * bytesplice(index, length, str) -> string
3450
+ * bytesplice(index, length, str, str_index, str_length) -> string
3451
+ * bytesplice(range, str) -> string
3452
+ * bytesplice(range, str, str_range) -> string
3453
+ *
3454
+ * Replaces some or all of the content of `self` with `str`, and returns `self`.
3455
+ * The portion of the string affected is determined using
3456
+ * the same criteria as String#byteslice, except that `length` cannot be omitted.
3457
+ * If the replacement string is not the same length as the text it is replacing,
3458
+ * the string will be adjusted accordingly.
3459
+ *
3460
+ * If `str_index` and `str_length`, or `str_range` are given, the content of `self`
3461
+ * is replaced by str.byteslice(str_index, str_length) or str.byteslice(str_range);
3462
+ * however the substring of `str` is not allocated as a new string.
3463
+ *
3464
+ * The form that take an Integer will raise an IndexError if the value is out
3465
+ * of range; the Range form will raise a RangeError.
3466
+ * If the beginning or ending offset does not land on character (codepoint)
3467
+ * boundary, an IndexError will be raised.
3468
+ */
3469
+ static mrb_value
3470
+ mrb_str_bytesplice(mrb_state *mrb, mrb_value str)
3471
+ {
3472
+ mrb_int idx1, len1, idx2, len2;
3473
+ mrb_value range1, range2, replace;
3474
+ switch (mrb_get_argc(mrb)) {
3475
+ case 3:
3476
+ mrb_get_args(mrb, "ooo", &range1, &replace, &range2);
3477
+ if (mrb_integer_p(range1)) {
3478
+ mrb_get_args(mrb, "iiS", &idx1, &len1, &replace);
3479
+ return str_bytesplice(mrb, str, idx1, len1, replace, 0, RSTRING_LEN(replace));
3480
+ }
3481
+ mrb_ensure_string_type(mrb, replace);
3482
+ if (mrb_range_beg_len(mrb, range1, &idx1, &len1, RSTRING_LEN(str), FALSE) != MRB_RANGE_OK) break;
3483
+ if (mrb_range_beg_len(mrb, range2, &idx2, &len2, RSTRING_LEN(replace), FALSE) != MRB_RANGE_OK) break;
3484
+ return str_bytesplice(mrb, str, idx1, len1, replace, idx2, len2);
3485
+ case 5:
3486
+ mrb_get_args(mrb, "iiSii", &idx1, &len1, &replace, &idx2, &len2);
3487
+ return str_bytesplice(mrb, str, idx1, len1, replace, idx2, len2);
3488
+ case 2:
3489
+ mrb_get_args(mrb, "oS", &range1, &replace);
3490
+ if (mrb_range_beg_len(mrb, range1, &idx1, &len1, RSTRING_LEN(str), FALSE) == MRB_RANGE_OK) {
3491
+ return str_bytesplice(mrb, str, idx1, len1, replace, 0, RSTRING_LEN(replace));
3492
+ }
3493
+ default:
3494
+ break;
3495
+ }
3496
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong number of arumgnts");
3497
+ }
3498
+
3499
+ static mrb_value
3500
+ mrb_encoding(mrb_state *mrb, mrb_value self)
3501
+ {
3502
+ mrb_get_args(mrb, "");
3503
+ #ifdef MRB_UTF8_STRING
3504
+ return mrb_str_new_lit(mrb, "UTF-8");
3505
+ #else
3506
+ return mrb_str_new_lit(mrb, "ASCII-8BIT");
3507
+ #endif
3508
+ }
3509
+
3510
+ /* ---------------------------*/
3511
+ static const mrb_mt_entry string_rom_entries[] = {
3512
+ MRB_MT_ENTRY(mrb_str_bytesize, MRB_SYM(bytesize), MRB_ARGS_NONE()),
3513
+ MRB_MT_ENTRY(mrb_str_cmp_m, MRB_OPSYM(cmp), MRB_ARGS_REQ(1)), /* 15.2.10.5.1 */
3514
+ MRB_MT_ENTRY(mrb_str_equal_m, MRB_OPSYM(eq), MRB_ARGS_REQ(1)), /* 15.2.10.5.2 */
3515
+ MRB_MT_ENTRY(mrb_str_plus_m, MRB_OPSYM(add), MRB_ARGS_REQ(1)), /* 15.2.10.5.4 */
3516
+ MRB_MT_ENTRY(mrb_str_times, MRB_OPSYM(mul), MRB_ARGS_REQ(1)), /* 15.2.10.5.5 */
3517
+ MRB_MT_ENTRY(mrb_str_aref_m, MRB_OPSYM(aref), MRB_ARGS_ANY()), /* 15.2.10.5.6 */
3518
+ MRB_MT_ENTRY(mrb_str_aset_m, MRB_OPSYM(aset), MRB_ARGS_ANY()),
3519
+ MRB_MT_ENTRY(mrb_str_capitalize, MRB_SYM(capitalize), MRB_ARGS_NONE()), /* 15.2.10.5.7 */
3520
+ MRB_MT_ENTRY(mrb_str_capitalize_bang, MRB_SYM_B(capitalize), MRB_ARGS_NONE()), /* 15.2.10.5.8 */
3521
+ MRB_MT_ENTRY(mrb_str_chomp, MRB_SYM(chomp), MRB_ARGS_ANY()), /* 15.2.10.5.9 */
3522
+ MRB_MT_ENTRY(mrb_str_chomp_bang, MRB_SYM_B(chomp), MRB_ARGS_ANY()), /* 15.2.10.5.10 */
3523
+ MRB_MT_ENTRY(mrb_str_chop, MRB_SYM(chop), MRB_ARGS_NONE()), /* 15.2.10.5.11 */
3524
+ MRB_MT_ENTRY(mrb_str_chop_bang, MRB_SYM_B(chop), MRB_ARGS_NONE()), /* 15.2.10.5.12 */
3525
+ MRB_MT_ENTRY(mrb_str_downcase, MRB_SYM(downcase), MRB_ARGS_NONE()), /* 15.2.10.5.13 */
3526
+ MRB_MT_ENTRY(mrb_str_downcase_bang, MRB_SYM_B(downcase), MRB_ARGS_NONE()), /* 15.2.10.5.14 */
3527
+ MRB_MT_ENTRY(mrb_str_empty_p, MRB_SYM_Q(empty), MRB_ARGS_NONE()), /* 15.2.10.5.16 */
3528
+ MRB_MT_ENTRY(mrb_str_eql, MRB_SYM_Q(eql), MRB_ARGS_REQ(1)), /* 15.2.10.5.17 */
3529
+ MRB_MT_ENTRY(mrb_str_hash_m, MRB_SYM(hash), MRB_ARGS_NONE()), /* 15.2.10.5.20 */
3530
+ MRB_MT_ENTRY(mrb_str_include, MRB_SYM_Q(include), MRB_ARGS_REQ(1)), /* 15.2.10.5.21 */
3531
+ MRB_MT_ENTRY(mrb_str_index_m, MRB_SYM(index), MRB_ARGS_ARG(1,1)), /* 15.2.10.5.22 */
3532
+ MRB_MT_ENTRY(mrb_str_init, MRB_SYM(initialize), MRB_ARGS_OPT(1) | MRB_MT_PRIVATE), /* 15.2.10.5.23 */
3533
+ MRB_MT_ENTRY(mrb_str_replace, MRB_SYM(initialize_copy), MRB_ARGS_REQ(1) | MRB_MT_PRIVATE), /* 15.2.10.5.24 */
3534
+ MRB_MT_ENTRY(mrb_str_intern, MRB_SYM(intern), MRB_ARGS_NONE()), /* 15.2.10.5.25 */
3535
+ MRB_MT_ENTRY(mrb_str_size, MRB_SYM(length), MRB_ARGS_NONE()), /* 15.2.10.5.26 */
3536
+ MRB_MT_ENTRY(mrb_str_replace, MRB_SYM(replace), MRB_ARGS_REQ(1)), /* 15.2.10.5.28 */
3537
+ MRB_MT_ENTRY(mrb_str_reverse, MRB_SYM(reverse), MRB_ARGS_NONE()), /* 15.2.10.5.29 */
3538
+ MRB_MT_ENTRY(mrb_str_reverse_bang, MRB_SYM_B(reverse), MRB_ARGS_NONE()), /* 15.2.10.5.30 */
3539
+ MRB_MT_ENTRY(mrb_str_rindex_m, MRB_SYM(rindex), MRB_ARGS_ANY()), /* 15.2.10.5.31 */
3540
+ MRB_MT_ENTRY(mrb_str_size, MRB_SYM(size), MRB_ARGS_NONE()), /* 15.2.10.5.33 */
3541
+ MRB_MT_ENTRY(mrb_str_aref_m, MRB_SYM(slice), MRB_ARGS_ANY()), /* 15.2.10.5.34 */
3542
+ MRB_MT_ENTRY(mrb_str_split_m, MRB_SYM(split), MRB_ARGS_ANY()), /* 15.2.10.5.35 */
3543
+ MRB_MT_ENTRY(mrb_str_to_i, MRB_SYM(to_i), MRB_ARGS_ANY()), /* 15.2.10.5.39 */
3544
+ MRB_MT_ENTRY(mrb_str_to_s, MRB_SYM(to_s), MRB_ARGS_NONE()), /* 15.2.10.5.40 */
3545
+ MRB_MT_ENTRY(mrb_str_to_s, MRB_SYM(to_str), MRB_ARGS_NONE()),
3546
+ MRB_MT_ENTRY(mrb_str_intern, MRB_SYM(to_sym), MRB_ARGS_NONE()), /* 15.2.10.5.41 */
3547
+ MRB_MT_ENTRY(mrb_str_upcase, MRB_SYM(upcase), MRB_ARGS_NONE()), /* 15.2.10.5.42 */
3548
+ MRB_MT_ENTRY(mrb_str_upcase_bang, MRB_SYM_B(upcase), MRB_ARGS_NONE()), /* 15.2.10.5.43 */
3549
+ MRB_MT_ENTRY(mrb_str_inspect, MRB_SYM(inspect), MRB_ARGS_NONE()), /* 15.2.10.5.46(x) */
3550
+ MRB_MT_ENTRY(mrb_str_bytes, MRB_SYM(bytes), MRB_ARGS_NONE()),
3551
+ MRB_MT_ENTRY(mrb_str_getbyte, MRB_SYM(getbyte), MRB_ARGS_REQ(1)),
3552
+ MRB_MT_ENTRY(mrb_str_setbyte, MRB_SYM(setbyte), MRB_ARGS_REQ(2)),
3553
+ MRB_MT_ENTRY(mrb_str_byteindex_m, MRB_SYM(byteindex), MRB_ARGS_ARG(1,1)),
3554
+ MRB_MT_ENTRY(mrb_str_byterindex_m, MRB_SYM(byterindex), MRB_ARGS_ARG(1,1)),
3555
+ MRB_MT_ENTRY(mrb_str_byteslice, MRB_SYM(byteslice), MRB_ARGS_ARG(1,1)),
3556
+ MRB_MT_ENTRY(mrb_str_bytesplice, MRB_SYM(bytesplice), MRB_ARGS_ANY()),
3557
+ MRB_MT_ENTRY(sub_replace, MRB_SYM(__sub_replace), MRB_ARGS_REQ(3)), /* internal */
3558
+ #ifndef MRB_NO_FLOAT
3559
+ MRB_MT_ENTRY(mrb_str_to_f, MRB_SYM(to_f), MRB_ARGS_NONE()), /* 15.2.10.5.38 */
3560
+ #endif
3561
+ };
3562
+
3563
+ void
3564
+ mrb_init_string(mrb_state *mrb)
3565
+ {
3566
+ struct RClass *s;
3567
+
3568
+ mrb_static_assert(RSTRING_EMBED_LEN_MAX < (1 << MRB_STR_EMBED_LEN_BITS),
3569
+ "pointer size too big for embedded string");
3570
+
3571
+ mrb->string_class = s = mrb_define_class_id(mrb, MRB_SYM(String), mrb->object_class); /* 15.2.10 */
3572
+ MRB_SET_INSTANCE_TT(s, MRB_TT_STRING);
3573
+
3574
+ MRB_MT_INIT_ROM(mrb, s, string_rom_entries);
3575
+
3576
+ mrb_define_method_id(mrb, mrb->kernel_module, MRB_SYM(__ENCODING__), mrb_encoding, MRB_ARGS_NONE());
3577
+ }