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.
- checksums.yaml +7 -0
- data/README.md +182 -0
- data/Rakefile +30 -0
- data/ext/enclave/enclave.c +390 -0
- data/ext/enclave/extconf.rb +33 -0
- data/ext/enclave/mruby/Makefile +63 -0
- data/ext/enclave/mruby/Rakefile +102 -0
- data/ext/enclave/mruby/benchmark/bm_ao_render.rb +309 -0
- data/ext/enclave/mruby/benchmark/bm_app_lc_fizzbuzz.rb +51 -0
- data/ext/enclave/mruby/benchmark/bm_fib.rb +6 -0
- data/ext/enclave/mruby/benchmark/bm_mandel_term.rb +34 -0
- data/ext/enclave/mruby/benchmark/bm_so_lists.rb +49 -0
- data/ext/enclave/mruby/benchmark/bm_so_mandelbrot.rb +65 -0
- data/ext/enclave/mruby/benchmark/vm_dispatch_bench.c +197 -0
- data/ext/enclave/mruby/benchmark/vm_optimization_bench.rb +513 -0
- data/ext/enclave/mruby/build/host/include/mrbconf.h +230 -0
- data/ext/enclave/mruby/build/host/include/mruby/array.h +303 -0
- data/ext/enclave/mruby/build/host/include/mruby/boxing_nan.h +169 -0
- data/ext/enclave/mruby/build/host/include/mruby/boxing_no.h +59 -0
- data/ext/enclave/mruby/build/host/include/mruby/boxing_word.h +248 -0
- data/ext/enclave/mruby/build/host/include/mruby/class.h +157 -0
- data/ext/enclave/mruby/build/host/include/mruby/common.h +127 -0
- data/ext/enclave/mruby/build/host/include/mruby/compile.h +187 -0
- data/ext/enclave/mruby/build/host/include/mruby/data.h +76 -0
- data/ext/enclave/mruby/build/host/include/mruby/debug.h +75 -0
- data/ext/enclave/mruby/build/host/include/mruby/dump.h +159 -0
- data/ext/enclave/mruby/build/host/include/mruby/endian.h +44 -0
- data/ext/enclave/mruby/build/host/include/mruby/error.h +168 -0
- data/ext/enclave/mruby/build/host/include/mruby/gc.h +77 -0
- data/ext/enclave/mruby/build/host/include/mruby/hash.h +234 -0
- data/ext/enclave/mruby/build/host/include/mruby/internal.h +278 -0
- data/ext/enclave/mruby/build/host/include/mruby/irep.h +142 -0
- data/ext/enclave/mruby/build/host/include/mruby/istruct.h +50 -0
- data/ext/enclave/mruby/build/host/include/mruby/khash.h +455 -0
- data/ext/enclave/mruby/build/host/include/mruby/mempool.h +19 -0
- data/ext/enclave/mruby/build/host/include/mruby/numeric.h +174 -0
- data/ext/enclave/mruby/build/host/include/mruby/object.h +44 -0
- data/ext/enclave/mruby/build/host/include/mruby/opcode.h +73 -0
- data/ext/enclave/mruby/build/host/include/mruby/ops.h +133 -0
- data/ext/enclave/mruby/build/host/include/mruby/presym/id.h +895 -0
- data/ext/enclave/mruby/build/host/include/mruby/presym/scanning.h +82 -0
- data/ext/enclave/mruby/build/host/include/mruby/presym/table.h +1787 -0
- data/ext/enclave/mruby/build/host/include/mruby/presym.h +65 -0
- data/ext/enclave/mruby/build/host/include/mruby/proc.h +184 -0
- data/ext/enclave/mruby/build/host/include/mruby/range.h +77 -0
- data/ext/enclave/mruby/build/host/include/mruby/re.h +16 -0
- data/ext/enclave/mruby/build/host/include/mruby/string.h +428 -0
- data/ext/enclave/mruby/build/host/include/mruby/throw.h +81 -0
- data/ext/enclave/mruby/build/host/include/mruby/value.h +471 -0
- data/ext/enclave/mruby/build/host/include/mruby/variable.h +108 -0
- data/ext/enclave/mruby/build/host/include/mruby/version.h +143 -0
- data/ext/enclave/mruby/build/host/include/mruby.h +1632 -0
- data/ext/enclave/mruby/build/host/mrbc/include/mruby/presym/id.h +281 -0
- data/ext/enclave/mruby/build/host/mrbc/include/mruby/presym/table.h +559 -0
- data/ext/enclave/mruby/build/host/mrbgems/gem_init.c +164 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-array-ext/gem_init.c +650 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-binding/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-catch/gem_init.c +86 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-class-ext/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-compar-ext/gem_init.c +99 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-complex/gem_init.c +362 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-data/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-chain/gem_init.c +229 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-ext/gem_init.c +1420 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-enum-lazy/gem_init.c +602 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-enumerator/gem_init.c +822 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-eval/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-fiber/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-hash-ext/gem_init.c +591 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-kernel-ext/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-math/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-metaprog/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-method/gem_init.c +153 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-numeric-ext/gem_init.c +211 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-object-ext/gem_init.c +94 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-objectspace/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-pack/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-proc-binding/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-proc-ext/gem_init.c +237 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-random/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-range-ext/gem_init.c +205 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-rational/gem_init.c +147 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-set/gem_init.c +487 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-sprintf/gem_init.c +83 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-string-ext/gem_init.c +220 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-struct/gem_init.c +175 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-symbol-ext/gem_init.c +153 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-time/gem_init.c +21 -0
- data/ext/enclave/mruby/build/host/mrbgems/mruby-toplevel-ext/gem_init.c +78 -0
- data/ext/enclave/mruby/build/host/mrblib/mrblib.c +1758 -0
- data/ext/enclave/mruby/build_config/ArduinoDue.rb +72 -0
- data/ext/enclave/mruby/build_config/IntelEdison.rb +69 -0
- data/ext/enclave/mruby/build_config/IntelGalileo.rb +88 -0
- data/ext/enclave/mruby/build_config/RX630.rb +63 -0
- data/ext/enclave/mruby/build_config/android_arm64_v8a.rb +11 -0
- data/ext/enclave/mruby/build_config/android_armeabi_v7a_neon_hard.rb +13 -0
- data/ext/enclave/mruby/build_config/bench.rb +11 -0
- data/ext/enclave/mruby/build_config/boxing.rb +19 -0
- data/ext/enclave/mruby/build_config/chipKITMax32.rb +68 -0
- data/ext/enclave/mruby/build_config/ci/gcc-clang.rb +40 -0
- data/ext/enclave/mruby/build_config/ci/msvc.rb +20 -0
- data/ext/enclave/mruby/build_config/clang-asan.rb +11 -0
- data/ext/enclave/mruby/build_config/cosmopolitan.rb +86 -0
- data/ext/enclave/mruby/build_config/cross-32bit.rb +14 -0
- data/ext/enclave/mruby/build_config/cross-mingw-winetest.rb +90 -0
- data/ext/enclave/mruby/build_config/cross-mingw.rb +14 -0
- data/ext/enclave/mruby/build_config/default.rb +83 -0
- data/ext/enclave/mruby/build_config/dreamcast_shelf.rb +81 -0
- data/ext/enclave/mruby/build_config/emscripten-cxx.rb +12 -0
- data/ext/enclave/mruby/build_config/emscripten.rb +10 -0
- data/ext/enclave/mruby/build_config/gameboyadvance.rb +72 -0
- data/ext/enclave/mruby/build_config/helpers/wine_runner.rb +71 -0
- data/ext/enclave/mruby/build_config/host-cxx.rb +12 -0
- data/ext/enclave/mruby/build_config/host-debug.rb +20 -0
- data/ext/enclave/mruby/build_config/host-f32.rb +14 -0
- data/ext/enclave/mruby/build_config/host-gprof.rb +14 -0
- data/ext/enclave/mruby/build_config/host-m32.rb +15 -0
- data/ext/enclave/mruby/build_config/host-nofloat.rb +22 -0
- data/ext/enclave/mruby/build_config/host-shared.rb +36 -0
- data/ext/enclave/mruby/build_config/i586-pc-msdosdjgpp.rb +76 -0
- data/ext/enclave/mruby/build_config/luckfox_pico.rb +106 -0
- data/ext/enclave/mruby/build_config/milkv_duo.rb +106 -0
- data/ext/enclave/mruby/build_config/minimal.rb +4 -0
- data/ext/enclave/mruby/build_config/mrbc.rb +10 -0
- data/ext/enclave/mruby/build_config/nintendo_switch.rb +73 -0
- data/ext/enclave/mruby/build_config/nintendo_wii.rb +95 -0
- data/ext/enclave/mruby/build_config/no-float.rb +17 -0
- data/ext/enclave/mruby/build_config/playstationportable.rb +78 -0
- data/ext/enclave/mruby/build_config/serenity.rb +26 -0
- data/ext/enclave/mruby/build_config.rb +9 -0
- data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/mrblib/example.rb +5 -0
- data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/src/example.c +23 -0
- data/ext/enclave/mruby/examples/mrbgems/c_and_ruby_extension_example/test/example.rb +7 -0
- data/ext/enclave/mruby/examples/mrbgems/c_extension_example/src/example.c +23 -0
- data/ext/enclave/mruby/examples/mrbgems/c_extension_example/test/example.c +7 -0
- data/ext/enclave/mruby/examples/mrbgems/c_extension_example/test/example.rb +3 -0
- data/ext/enclave/mruby/examples/mrbgems/cdata_extension_example/src/example.c +77 -0
- data/ext/enclave/mruby/examples/mrbgems/cdata_extension_example/test/example.c +7 -0
- data/ext/enclave/mruby/examples/mrbgems/mruby-YOUR-bigint/core/bigint.c +70 -0
- data/ext/enclave/mruby/examples/mrbgems/ruby_extension_example/mrblib/example.rb +5 -0
- data/ext/enclave/mruby/examples/mrbgems/ruby_extension_example/test/example.rb +3 -0
- data/ext/enclave/mruby/include/mrbconf.h +230 -0
- data/ext/enclave/mruby/include/mruby/array.h +303 -0
- data/ext/enclave/mruby/include/mruby/boxing_nan.h +169 -0
- data/ext/enclave/mruby/include/mruby/boxing_no.h +59 -0
- data/ext/enclave/mruby/include/mruby/boxing_word.h +248 -0
- data/ext/enclave/mruby/include/mruby/class.h +157 -0
- data/ext/enclave/mruby/include/mruby/common.h +127 -0
- data/ext/enclave/mruby/include/mruby/compile.h +187 -0
- data/ext/enclave/mruby/include/mruby/data.h +76 -0
- data/ext/enclave/mruby/include/mruby/debug.h +75 -0
- data/ext/enclave/mruby/include/mruby/dump.h +159 -0
- data/ext/enclave/mruby/include/mruby/endian.h +44 -0
- data/ext/enclave/mruby/include/mruby/error.h +168 -0
- data/ext/enclave/mruby/include/mruby/gc.h +77 -0
- data/ext/enclave/mruby/include/mruby/hash.h +234 -0
- data/ext/enclave/mruby/include/mruby/internal.h +278 -0
- data/ext/enclave/mruby/include/mruby/irep.h +142 -0
- data/ext/enclave/mruby/include/mruby/istruct.h +50 -0
- data/ext/enclave/mruby/include/mruby/khash.h +455 -0
- data/ext/enclave/mruby/include/mruby/mempool.h +19 -0
- data/ext/enclave/mruby/include/mruby/numeric.h +174 -0
- data/ext/enclave/mruby/include/mruby/object.h +44 -0
- data/ext/enclave/mruby/include/mruby/opcode.h +73 -0
- data/ext/enclave/mruby/include/mruby/ops.h +133 -0
- data/ext/enclave/mruby/include/mruby/presym/scanning.h +82 -0
- data/ext/enclave/mruby/include/mruby/presym.h +65 -0
- data/ext/enclave/mruby/include/mruby/proc.h +184 -0
- data/ext/enclave/mruby/include/mruby/range.h +77 -0
- data/ext/enclave/mruby/include/mruby/re.h +16 -0
- data/ext/enclave/mruby/include/mruby/string.h +428 -0
- data/ext/enclave/mruby/include/mruby/throw.h +81 -0
- data/ext/enclave/mruby/include/mruby/value.h +471 -0
- data/ext/enclave/mruby/include/mruby/variable.h +108 -0
- data/ext/enclave/mruby/include/mruby/version.h +143 -0
- data/ext/enclave/mruby/include/mruby.h +1632 -0
- data/ext/enclave/mruby/lib/mruby/amalgam.rb +568 -0
- data/ext/enclave/mruby/lib/mruby/build/command.rb +383 -0
- data/ext/enclave/mruby/lib/mruby/build/load_gems.rb +383 -0
- data/ext/enclave/mruby/lib/mruby/build.rb +616 -0
- data/ext/enclave/mruby/lib/mruby/core_ext.rb +61 -0
- data/ext/enclave/mruby/lib/mruby/doc.rb +51 -0
- data/ext/enclave/mruby/lib/mruby/gem.rb +585 -0
- data/ext/enclave/mruby/lib/mruby/lockfile.rb +81 -0
- data/ext/enclave/mruby/lib/mruby/presym.rb +167 -0
- data/ext/enclave/mruby/lib/mruby/source.rb +32 -0
- data/ext/enclave/mruby/mrbgems/default-no-fpu.gembox +3 -0
- data/ext/enclave/mruby/mrbgems/default-no-stdio.gembox +4 -0
- data/ext/enclave/mruby/mrbgems/default.gembox +25 -0
- data/ext/enclave/mruby/mrbgems/full-core.gembox +6 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-dir/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-dir/src/dir_hal.c +193 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-io/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-io/src/io_hal.c +602 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-socket/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-socket/src/socket_hal.c +158 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-task/README.md +102 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-task/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/hal-posix-task/src/task_hal.c +252 -0
- data/ext/enclave/mruby/mrbgems/hal-win-dir/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/hal-win-dir/src/dir_hal.c +249 -0
- data/ext/enclave/mruby/mrbgems/hal-win-io/mrbgem.rake +11 -0
- data/ext/enclave/mruby/mrbgems/hal-win-io/src/io_hal.c +646 -0
- data/ext/enclave/mruby/mrbgems/hal-win-socket/mrbgem.rake +12 -0
- data/ext/enclave/mruby/mrbgems/hal-win-socket/src/socket_hal.c +177 -0
- data/ext/enclave/mruby/mrbgems/hal-win-task/README.md +109 -0
- data/ext/enclave/mruby/mrbgems/hal-win-task/mrbgem.rake +11 -0
- data/ext/enclave/mruby/mrbgems/hal-win-task/src/task_hal.c +187 -0
- data/ext/enclave/mruby/mrbgems/math.gembox +12 -0
- data/ext/enclave/mruby/mrbgems/metaprog.gembox +21 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/README.md +87 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/mrblib/array.rb +784 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/src/array.c +1583 -0
- data/ext/enclave/mruby/mrbgems/mruby-array-ext/test/array.rb +849 -0
- data/ext/enclave/mruby/mrbgems/mruby-benchmark/README.md +257 -0
- data/ext/enclave/mruby/mrbgems/mruby-benchmark/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-benchmark/mrblib/benchmark.rb +131 -0
- data/ext/enclave/mruby/mrbgems/mruby-benchmark/test/benchmark.rb +244 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/README-fgmp.md +154 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/README.md +44 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/core/bigint.c +6335 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/core/bigint.h +117 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-bigint/test/bigint.rb +157 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-config/README.md +46 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-config/mrbgem.rake +49 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-config/mruby-config +46 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-config/mruby-config.bat +92 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/README.md +63 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/bintest/mrdb.rb +283 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/bintest/print.rb +703 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c +523 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.h +26 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.c +238 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apilist.h +14 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.c +88 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apiprint.h +13 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apistring.c +34 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/apistring.h +14 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdbreak.c +436 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdmisc.c +509 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdprint.c +71 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/cmdrun.c +64 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +768 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.h +159 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdberror.h +19 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/README.md +94 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/bintest/mirb.rb +58 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +808 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_buffer.c +1035 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_buffer.h +185 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.c +797 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_completion.h +132 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.c +1118 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_editor.h +153 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_highlight.c +516 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_highlight.h +95 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_history.c +185 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_history.h +76 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_term.c +491 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb_term.h +137 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/README.md +58 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/bintest/mrbc.rb +30 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/mrbgem.rake +15 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c +362 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/stub.c +104 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/README.md +47 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/bintest/mruby.rb +178 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +380 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-strip/README.md +38 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-strip/bintest/mruby_strip.rb +73 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-strip/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby_strip.c +139 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/README.md +256 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/src/binding.c +518 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/test/binding.c +14 -0
- data/ext/enclave/mruby/mrbgems/mruby-binding/test/binding.rb +64 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/README.md +94 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/mrblib/catch.rb +29 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/src/catch.c +149 -0
- data/ext/enclave/mruby/mrbgems/mruby-catch/test/catch.rb +86 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/README.md +81 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/src/class.c +377 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/test/class.rb +46 -0
- data/ext/enclave/mruby/mrbgems/mruby-class-ext/test/module.rb +109 -0
- data/ext/enclave/mruby/mrbgems/mruby-cmath/README.md +45 -0
- data/ext/enclave/mruby/mrbgems/mruby-cmath/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/mruby-cmath/src/cmath.c +426 -0
- data/ext/enclave/mruby/mrbgems/mruby-cmath/test/cmath.rb +41 -0
- data/ext/enclave/mruby/mrbgems/mruby-compar-ext/README.md +65 -0
- data/ext/enclave/mruby/mrbgems/mruby-compar-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-compar-ext/mrblib/compar.rb +75 -0
- data/ext/enclave/mruby/mrbgems/mruby-compar-ext/test/compar.rb +21 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/README.md +28 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/codegen.c +7316 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/keywords +52 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/lex.def +207 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/node.h +784 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/parse.y +8977 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/core/y.tab.c +16136 -0
- data/ext/enclave/mruby/mrbgems/mruby-compiler/mrbgem.rake +42 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/README.md +55 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/mrblib/complex.rb +259 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/src/complex.c +597 -0
- data/ext/enclave/mruby/mrbgems/mruby-complex/test/complex.rb +174 -0
- data/ext/enclave/mruby/mrbgems/mruby-data/README.md +126 -0
- data/ext/enclave/mruby/mrbgems/mruby-data/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-data/src/data.c +550 -0
- data/ext/enclave/mruby/mrbgems/mruby-data/test/data.rb +76 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/README.md +53 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/include/dir_hal.h +79 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/mrbgem.rake +35 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/mrblib/dir.rb +124 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/src/dir.c +493 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/test/dir.rb +138 -0
- data/ext/enclave/mruby/mrbgems/mruby-dir/test/dirtest.c +125 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/README.md +96 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/mrbgem.rake +8 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/src/encoding.c +128 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/test/numeric.rb +27 -0
- data/ext/enclave/mruby/mrbgems/mruby-encoding/test/string.rb +30 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-chain/README.md +80 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-chain/mrbgem.rake +6 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-chain/mrblib/chain.rb +149 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-chain/test/enum_chain.rb +108 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-ext/README.md +487 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-ext/mrblib/enum.rb +938 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-ext/test/enum.rb +223 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/README.md +91 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/mrblib/lazy.rb +363 -0
- data/ext/enclave/mruby/mrbgems/mruby-enum-lazy/test/lazy.rb +59 -0
- data/ext/enclave/mruby/mrbgems/mruby-enumerator/README.md +89 -0
- data/ext/enclave/mruby/mrbgems/mruby-enumerator/mrbgem.rake +6 -0
- data/ext/enclave/mruby/mrbgems/mruby-enumerator/mrblib/enumerator.rb +861 -0
- data/ext/enclave/mruby/mrbgems/mruby-enumerator/test/enumerator.rb +664 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/README.md +83 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/mrblib/errno.rb +50 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/src/errno.c +335 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/src/gen.rb +18 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/src/known_errors.def +156 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/src/known_errors_def.cstub +780 -0
- data/ext/enclave/mruby/mrbgems/mruby-errno/test/errno.rb +57 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/README.md +103 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/src/exception.c +143 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/test/exception.c +60 -0
- data/ext/enclave/mruby/mrbgems/mruby-error/test/exception.rb +55 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/README.md +26 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/src/eval.c +437 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/test/binding.rb +81 -0
- data/ext/enclave/mruby/mrbgems/mruby-eval/test/eval.rb +185 -0
- data/ext/enclave/mruby/mrbgems/mruby-exit/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-exit/src/mruby_exit.c +83 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/src/fiber.c +575 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fiber.rb +210 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fiber2.rb +155 -0
- data/ext/enclave/mruby/mrbgems/mruby-fiber/test/fibertest.c +87 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/README.md +392 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/mrbgem.rake +6 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/mrblib/hash.rb +408 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/src/hash_ext.c +392 -0
- data/ext/enclave/mruby/mrbgems/mruby-hash-ext/test/hash.rb +317 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/README.md +198 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/include/io_hal.h +451 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/include/mruby/io.h +76 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrbgem.rake +34 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/file.rb +109 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/file_constants.rb +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/io.rb +303 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/mrblib/kernel.rb +175 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/src/file.c +1192 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/src/file_test.c +403 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/src/io.c +2260 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/src/mruby_io_gem.c +21 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/test/file.rb +415 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/test/file_test.rb +112 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/test/io.rb +668 -0
- data/ext/enclave/mruby/mrbgems/mruby-io/test/mruby_io_test.c +293 -0
- data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/README.md +165 -0
- data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/src/kernel.c +316 -0
- data/ext/enclave/mruby/mrbgems/mruby-kernel-ext/test/kernel.rb +134 -0
- data/ext/enclave/mruby/mrbgems/mruby-math/README.md +77 -0
- data/ext/enclave/mruby/mrbgems/mruby-math/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-math/src/math.c +753 -0
- data/ext/enclave/mruby/mrbgems/mruby-math/test/math.rb +201 -0
- data/ext/enclave/mruby/mrbgems/mruby-metaprog/README.md +123 -0
- data/ext/enclave/mruby/mrbgems/mruby-metaprog/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-metaprog/src/metaprog.c +739 -0
- data/ext/enclave/mruby/mrbgems/mruby-metaprog/test/metaprog.rb +465 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/README.md +66 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/mrblib/method.rb +73 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/src/method.c +890 -0
- data/ext/enclave/mruby/mrbgems/mruby-method/test/method.rb +514 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/README.md +78 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb +125 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/src/numeric_ext.c +527 -0
- data/ext/enclave/mruby/mrbgems/mruby-numeric-ext/test/numeric.rb +137 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/README.md +144 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/mrblib/object.rb +33 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/src/object.c +128 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/nil.rb +16 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/object.rb +67 -0
- data/ext/enclave/mruby/mrbgems/mruby-object-ext/test/object_ext.c +17 -0
- data/ext/enclave/mruby/mrbgems/mruby-objectspace/README.md +59 -0
- data/ext/enclave/mruby/mrbgems/mruby-objectspace/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c +188 -0
- data/ext/enclave/mruby/mrbgems/mruby-objectspace/test/objectspace.rb +60 -0
- data/ext/enclave/mruby/mrbgems/mruby-os-memsize/README.md +75 -0
- data/ext/enclave/mruby/mrbgems/mruby-os-memsize/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-os-memsize/src/memsize.c +271 -0
- data/ext/enclave/mruby/mrbgems/mruby-os-memsize/test/memsize.rb +63 -0
- data/ext/enclave/mruby/mrbgems/mruby-pack/README.md +140 -0
- data/ext/enclave/mruby/mrbgems/mruby-pack/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-pack/src/pack.c +2129 -0
- data/ext/enclave/mruby/mrbgems/mruby-pack/test/pack.rb +202 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/README.md +140 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/mrbgem.rake +10 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/src/proc_binding.c +76 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/test/proc_binding.c +14 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-binding/test/proc_binding.rb +22 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/README.md +107 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/mrblib/proc.rb +130 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/src/proc.c +267 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/test/proc.c +62 -0
- data/ext/enclave/mruby/mrbgems/mruby-proc-ext/test/proc.rb +130 -0
- data/ext/enclave/mruby/mrbgems/mruby-random/README.md +272 -0
- data/ext/enclave/mruby/mrbgems/mruby-random/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-random/src/random.c +608 -0
- data/ext/enclave/mruby/mrbgems/mruby-random/test/random.rb +151 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/README.md +93 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/mrblib/range.rb +155 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/src/range.c +236 -0
- data/ext/enclave/mruby/mrbgems/mruby-range-ext/test/range.rb +211 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/README.md +61 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/mrblib/rational.rb +66 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/src/rational.c +1269 -0
- data/ext/enclave/mruby/mrbgems/mruby-rational/test/rational.rb +316 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/LICENSE +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/README.md +260 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/mrbgem.rake +9 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/mrblib/set.rb +325 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/mruby-set.gem +6 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/src/set.c +1535 -0
- data/ext/enclave/mruby/mrbgems/mruby-set/test/set.rb +764 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/README.md +29 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/example/sleep.rb +2 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/src/sleep.c +187 -0
- data/ext/enclave/mruby/mrbgems/mruby-sleep/test/sleep_test.rb +29 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/README.md +56 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/include/socket_hal.h +83 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/mrbgem.rake +37 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/mrblib/socket.rb +1131 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/src/const.cstub +480 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/src/const.def +172 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/src/gen.rb +17 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/src/socket.c +1374 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/addrinfo.rb +91 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/basicsocket.rb +17 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/ipsocket.rb +44 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/socket.rb +38 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/sockettest.c +84 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/tcpsocket.rb +4 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/udpsocket.rb +16 -0
- data/ext/enclave/mruby/mrbgems/mruby-socket/test/unix.rb +130 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/README.md +235 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/mrblib/string.rb +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/src/sprintf.c +1195 -0
- data/ext/enclave/mruby/mrbgems/mruby-sprintf/test/sprintf.rb +92 -0
- data/ext/enclave/mruby/mrbgems/mruby-strftime/README.md +140 -0
- data/ext/enclave/mruby/mrbgems/mruby-strftime/mrbgem.rake +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-strftime/src/strftime.c +119 -0
- data/ext/enclave/mruby/mrbgems/mruby-strftime/test/strftime.rb +152 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/README.md +886 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/mrblib/string.rb +166 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/src/string.c +2290 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/numeric.rb +27 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/range.rb +26 -0
- data/ext/enclave/mruby/mrbgems/mruby-string-ext/test/string.rb +765 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/README.md +105 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/mrblib/struct.rb +69 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/src/struct.c +812 -0
- data/ext/enclave/mruby/mrbgems/mruby-struct/test/struct.rb +303 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/README.md +50 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb +72 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/src/symbol.c +79 -0
- data/ext/enclave/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb +55 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/README.md +770 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/inspection.rb +65 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/priority.rb +41 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/producer_consumer.rb +58 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/simple.rb +27 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/statistics.rb +59 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/suspend_resume.rb +47 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/examples/task_pass.rb +21 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/include/task.h +143 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/include/task_hal.h +162 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/mrbgem.rake +36 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/src/task.c +1573 -0
- data/ext/enclave/mruby/mrbgems/mruby-task/test/task.rb +185 -0
- data/ext/enclave/mruby/mrbgems/mruby-test/README.md +7 -0
- data/ext/enclave/mruby/mrbgems/mruby-test/driver.c +315 -0
- data/ext/enclave/mruby/mrbgems/mruby-test/mrbgem.rake +173 -0
- data/ext/enclave/mruby/mrbgems/mruby-test/vformat.c +151 -0
- data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/test/inline.c +92 -0
- data/ext/enclave/mruby/mrbgems/mruby-test-inline-struct/test/inline.rb +118 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/README.md +102 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/include/mruby/time.h +27 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/src/time.c +1739 -0
- data/ext/enclave/mruby/mrbgems/mruby-time/test/time.rb +313 -0
- data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/README.md +32 -0
- data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/mrbgem.rake +5 -0
- data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/mrblib/toplevel.rb +24 -0
- data/ext/enclave/mruby/mrbgems/mruby-toplevel-ext/test/toplevel.rb +23 -0
- data/ext/enclave/mruby/mrbgems/stdlib-ext.gembox +21 -0
- data/ext/enclave/mruby/mrbgems/stdlib-io.gembox +15 -0
- data/ext/enclave/mruby/mrbgems/stdlib.gembox +63 -0
- data/ext/enclave/mruby/mrblib/10error.rb +23 -0
- data/ext/enclave/mruby/mrblib/array.rb +102 -0
- data/ext/enclave/mruby/mrblib/compar.rb +102 -0
- data/ext/enclave/mruby/mrblib/enum.rb +358 -0
- data/ext/enclave/mruby/mrblib/hash.rb +276 -0
- data/ext/enclave/mruby/mrblib/kernel.rb +45 -0
- data/ext/enclave/mruby/mrblib/numeric.rb +160 -0
- data/ext/enclave/mruby/mrblib/range.rb +98 -0
- data/ext/enclave/mruby/mrblib/string.rb +173 -0
- data/ext/enclave/mruby/mrblib/symbol.rb +8 -0
- data/ext/enclave/mruby/oss-fuzz/mruby_fuzzer.c +18 -0
- data/ext/enclave/mruby/oss-fuzz/proto_to_ruby.h +55 -0
- data/ext/enclave/mruby/src/allocf.c +37 -0
- data/ext/enclave/mruby/src/array.c +2302 -0
- data/ext/enclave/mruby/src/backtrace.c +294 -0
- data/ext/enclave/mruby/src/cdump.c +498 -0
- data/ext/enclave/mruby/src/class.c +4394 -0
- data/ext/enclave/mruby/src/codedump.c +693 -0
- data/ext/enclave/mruby/src/debug.c +290 -0
- data/ext/enclave/mruby/src/dump.c +998 -0
- data/ext/enclave/mruby/src/enum.c +30 -0
- data/ext/enclave/mruby/src/error.c +937 -0
- data/ext/enclave/mruby/src/etc.c +421 -0
- data/ext/enclave/mruby/src/fmt_fp.c +372 -0
- data/ext/enclave/mruby/src/gc.c +1610 -0
- data/ext/enclave/mruby/src/hash.c +2355 -0
- data/ext/enclave/mruby/src/init.c +50 -0
- data/ext/enclave/mruby/src/kernel.c +718 -0
- data/ext/enclave/mruby/src/load.c +760 -0
- data/ext/enclave/mruby/src/mempool.c +225 -0
- data/ext/enclave/mruby/src/numeric.c +2420 -0
- data/ext/enclave/mruby/src/numops.c +112 -0
- data/ext/enclave/mruby/src/object.c +883 -0
- data/ext/enclave/mruby/src/print.c +136 -0
- data/ext/enclave/mruby/src/proc.c +572 -0
- data/ext/enclave/mruby/src/range.c +597 -0
- data/ext/enclave/mruby/src/readfloat.c +228 -0
- data/ext/enclave/mruby/src/readint.c +27 -0
- data/ext/enclave/mruby/src/readnum.c +43 -0
- data/ext/enclave/mruby/src/state.c +247 -0
- data/ext/enclave/mruby/src/string.c +3577 -0
- data/ext/enclave/mruby/src/symbol.c +1023 -0
- data/ext/enclave/mruby/src/value_array.h +28 -0
- data/ext/enclave/mruby/src/variable.c +1475 -0
- data/ext/enclave/mruby/src/version.c +17 -0
- data/ext/enclave/mruby/src/vm.c +3696 -0
- data/ext/enclave/mruby/tasks/amalgam.rake +34 -0
- data/ext/enclave/mruby/tasks/benchmark.rake +93 -0
- data/ext/enclave/mruby/tasks/bin.rake +23 -0
- data/ext/enclave/mruby/tasks/core.rake +12 -0
- data/ext/enclave/mruby/tasks/doc.rake +118 -0
- data/ext/enclave/mruby/tasks/install.rake +40 -0
- data/ext/enclave/mruby/tasks/libmruby.rake +90 -0
- data/ext/enclave/mruby/tasks/mrbgems.rake +152 -0
- data/ext/enclave/mruby/tasks/mrblib.rake +29 -0
- data/ext/enclave/mruby/tasks/presym.rake +57 -0
- data/ext/enclave/mruby/tasks/test.rake +84 -0
- data/ext/enclave/mruby/tasks/toolchains/android.rake +228 -0
- data/ext/enclave/mruby/tasks/toolchains/clang.rake +8 -0
- data/ext/enclave/mruby/tasks/toolchains/emscripten.rake +57 -0
- data/ext/enclave/mruby/tasks/toolchains/gcc.rake +74 -0
- data/ext/enclave/mruby/tasks/toolchains/openwrt.rake +32 -0
- data/ext/enclave/mruby/tasks/toolchains/visualcpp.rake +48 -0
- data/ext/enclave/mruby/test/assert.rb +404 -0
- data/ext/enclave/mruby/test/bintest.rb +55 -0
- data/ext/enclave/mruby/test/t/argumenterror.rb +37 -0
- data/ext/enclave/mruby/test/t/array.rb +478 -0
- data/ext/enclave/mruby/test/t/basicobject.rb +10 -0
- data/ext/enclave/mruby/test/t/bs_block.rb +621 -0
- data/ext/enclave/mruby/test/t/bs_literal.rb +38 -0
- data/ext/enclave/mruby/test/t/class.rb +505 -0
- data/ext/enclave/mruby/test/t/codegen.rb +196 -0
- data/ext/enclave/mruby/test/t/comparable.rb +79 -0
- data/ext/enclave/mruby/test/t/ensure.rb +36 -0
- data/ext/enclave/mruby/test/t/enumerable.rb +134 -0
- data/ext/enclave/mruby/test/t/exception.rb +425 -0
- data/ext/enclave/mruby/test/t/false.rb +31 -0
- data/ext/enclave/mruby/test/t/float.rb +296 -0
- data/ext/enclave/mruby/test/t/gc.rb +45 -0
- data/ext/enclave/mruby/test/t/hash.rb +976 -0
- data/ext/enclave/mruby/test/t/indexerror.rb +6 -0
- data/ext/enclave/mruby/test/t/integer.rb +247 -0
- data/ext/enclave/mruby/test/t/iterations.rb +61 -0
- data/ext/enclave/mruby/test/t/kernel.rb +462 -0
- data/ext/enclave/mruby/test/t/lang.rb +74 -0
- data/ext/enclave/mruby/test/t/literals.rb +386 -0
- data/ext/enclave/mruby/test/t/localjumperror.rb +13 -0
- data/ext/enclave/mruby/test/t/methods.rb +138 -0
- data/ext/enclave/mruby/test/t/module.rb +931 -0
- data/ext/enclave/mruby/test/t/nameerror.rb +28 -0
- data/ext/enclave/mruby/test/t/nil.rb +39 -0
- data/ext/enclave/mruby/test/t/nomethoderror.rb +22 -0
- data/ext/enclave/mruby/test/t/numeric.rb +114 -0
- data/ext/enclave/mruby/test/t/object.rb +10 -0
- data/ext/enclave/mruby/test/t/proc.rb +198 -0
- data/ext/enclave/mruby/test/t/range.rb +194 -0
- data/ext/enclave/mruby/test/t/rangeerror.rb +6 -0
- data/ext/enclave/mruby/test/t/regexperror.rb +4 -0
- data/ext/enclave/mruby/test/t/runtimeerror.rb +6 -0
- data/ext/enclave/mruby/test/t/standarderror.rb +6 -0
- data/ext/enclave/mruby/test/t/string.rb +981 -0
- data/ext/enclave/mruby/test/t/superclass.rb +46 -0
- data/ext/enclave/mruby/test/t/symbol.rb +30 -0
- data/ext/enclave/mruby/test/t/syntax.rb +1296 -0
- data/ext/enclave/mruby/test/t/true.rb +31 -0
- data/ext/enclave/mruby/test/t/typeerror.rb +6 -0
- data/ext/enclave/mruby/test/t/unicode.rb +39 -0
- data/ext/enclave/mruby/test/t/vformat.rb +57 -0
- data/ext/enclave/mruby/tools/lrama/LEGAL.md +12 -0
- data/ext/enclave/mruby/tools/lrama/MIT +21 -0
- data/ext/enclave/mruby/tools/lrama/NEWS.md +696 -0
- data/ext/enclave/mruby/tools/lrama/exe/lrama +7 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/bitmap.rb +34 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/command.rb +68 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/context.rb +499 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/derivation.rb +66 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/example.rb +129 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/path.rb +29 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/production_path.rb +19 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/start_path.rb +23 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/state_item.rb +8 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/transition_path.rb +19 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples/triple.rb +23 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/counterexamples.rb +298 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/diagnostics.rb +36 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/digraph.rb +83 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/auxiliary.rb +9 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/binding.rb +67 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/destructor_code.rb +42 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/initial_action_code.rb +36 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/no_reference_code.rb +30 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/printer_code.rb +42 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code/rule_action.rb +92 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/code.rb +53 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/counter.rb +17 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/destructor.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/error_token.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/resolver.rb +62 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/rhs.rb +40 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule/rule.rb +24 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/parameterizing_rule.rb +5 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/percent_code.rb +14 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/precedence.rb +13 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/printer.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/reference.rb +16 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/rule.rb +75 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/rule_builder.rb +255 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/stdlib.y +122 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbol.rb +105 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbols/resolver.rb +301 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/symbols.rb +3 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/type.rb +20 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar/union.rb +12 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar.rb +407 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/grammar_validator.rb +37 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/grammar_file.rb +40 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/location.rb +115 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/char.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/ident.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/instantiate_rule.rb +30 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/tag.rb +16 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token/user_code.rb +83 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer/token.rb +70 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/lexer.rb +191 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/logger.rb +21 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/option_parser.rb +169 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/options.rb +28 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/output.rb +459 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/parser.rb +2144 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/report/duration.rb +27 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/report/profile.rb +16 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/report.rb +4 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/reduce.rb +37 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/reduce_reduce_conflict.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/resolved_conflict.rb +31 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/shift.rb +15 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state/shift_reduce_conflict.rb +11 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/state.rb +433 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/states/item.rb +91 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/states.rb +595 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/states_reporter.rb +362 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/trace_reporter.rb +45 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama/version.rb +5 -0
- data/ext/enclave/mruby/tools/lrama/lib/lrama.rb +22 -0
- data/ext/enclave/mruby/tools/lrama/template/bison/_yacc.h +71 -0
- data/ext/enclave/mruby/tools/lrama/template/bison/yacc.c +2068 -0
- data/ext/enclave/mruby/tools/lrama/template/bison/yacc.h +40 -0
- data/ext/enclave/sandbox_build_config.rb +15 -0
- data/ext/enclave/sandbox_core.c +722 -0
- data/ext/enclave/sandbox_core.h +87 -0
- data/lib/enclave/result.rb +29 -0
- data/lib/enclave/tool.rb +38 -0
- data/lib/enclave/version.rb +3 -0
- data/lib/enclave.rb +73 -0
- 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", ×);
|
|
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
|
+
}
|