14#include "ruby/internal/config.h"
24#include "debug_counter.h"
28#include "internal/array.h"
29#include "internal/bits.h"
30#include "internal/compar.h"
31#include "internal/compilers.h"
32#include "internal/concurrent_set.h"
33#include "internal/encoding.h"
34#include "internal/error.h"
35#include "internal/gc.h"
36#include "internal/hash.h"
37#include "internal/numeric.h"
38#include "internal/object.h"
39#include "internal/proc.h"
40#include "internal/re.h"
41#include "internal/sanitizers.h"
42#include "internal/simd.h"
43#include "internal/string.h"
44#include "internal/transcode.h"
51#include "ruby_assert.h"
58#if defined HAVE_CRYPT_R
59# if defined HAVE_CRYPT_H
62#elif !defined HAVE_CRYPT
63# include "missing/crypt.h"
64# define HAVE_CRYPT_R 1
68#undef rb_usascii_str_new
72#undef rb_usascii_str_new_cstr
73#undef rb_utf8_str_new_cstr
74#undef rb_enc_str_new_cstr
75#undef rb_external_str_new_cstr
76#undef rb_locale_str_new_cstr
77#undef rb_str_dup_frozen
78#undef rb_str_buf_new_cstr
129#define RUBY_MAX_CHAR_LEN 16
130#define STR_PRECOMPUTED_HASH FL_USER4
131#define STR_SHARED_ROOT FL_USER5
132#define STR_BORROWED FL_USER6
133#define STR_TMPLOCK FL_USER7
134#define STR_NOFREE FL_USER18
136#define STR_SET_NOEMBED(str) do {\
137 FL_SET((str), STR_NOEMBED);\
138 FL_UNSET((str), STR_SHARED | STR_SHARED_ROOT | STR_BORROWED);\
140#define STR_SET_EMBED(str) FL_UNSET((str), STR_NOEMBED | STR_SHARED | STR_NOFREE)
142#define STR_SET_LEN(str, n) do { \
143 RSTRING(str)->len = (n); \
146#define TERM_LEN(str) (rb_str_enc_fastpath(str) ? 1 : rb_enc_mbminlen(rb_enc_from_index(ENCODING_GET(str))))
147#define TERM_FILL(ptr, termlen) do {\
148 char *const term_fill_ptr = (ptr);\
149 const int term_fill_len = (termlen);\
150 *term_fill_ptr = '\0';\
151 if (UNLIKELY(term_fill_len > 1))\
152 memset(term_fill_ptr, 0, term_fill_len);\
155#define RESIZE_CAPA(str,capacity) do {\
156 const int termlen = TERM_LEN(str);\
157 RESIZE_CAPA_TERM(str,capacity,termlen);\
159#define RESIZE_CAPA_TERM(str,capacity,termlen) do {\
160 if (STR_EMBED_P(str)) {\
161 if (str_embed_capa(str) < capacity + termlen) {\
162 char *const tmp = ALLOC_N(char, (size_t)(capacity) + (termlen));\
163 const long tlen = RSTRING_LEN(str);\
164 memcpy(tmp, RSTRING_PTR(str), str_embed_capa(str));\
165 RSTRING(str)->as.heap.ptr = tmp;\
166 RSTRING(str)->len = tlen;\
167 STR_SET_NOEMBED(str);\
168 RSTRING(str)->as.heap.aux.capa = (capacity);\
172 RUBY_ASSERT(!FL_TEST((str), STR_SHARED)); \
173 SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char, \
174 (size_t)(capacity) + (termlen), STR_HEAP_SIZE(str)); \
175 RSTRING(str)->as.heap.aux.capa = (capacity);\
179#define STR_SET_SHARED(str, shared_str) do { \
180 if (!FL_TEST(str, STR_FAKESTR)) { \
181 RUBY_ASSERT(RSTRING_PTR(shared_str) <= RSTRING_PTR(str)); \
182 RUBY_ASSERT(RSTRING_PTR(str) <= RSTRING_PTR(shared_str) + RSTRING_LEN(shared_str)); \
183 RB_OBJ_WRITE((str), &RSTRING(str)->as.heap.aux.shared, (shared_str)); \
184 FL_SET((str), STR_SHARED); \
185 rb_gc_register_pinning_obj(str); \
186 FL_SET((shared_str), STR_SHARED_ROOT); \
187 if (RBASIC_CLASS((shared_str)) == 0) \
188 FL_SET_RAW((shared_str), STR_BORROWED); \
192#define STR_HEAP_PTR(str) (RSTRING(str)->as.heap.ptr)
193#define STR_HEAP_SIZE(str) ((size_t)RSTRING(str)->as.heap.aux.capa + TERM_LEN(str))
196#define STR_ENC_GET(str) get_encoding(str)
199zero_filled(
const char *s,
int n)
202 if (*s++)
return false;
207#if !defined SHARABLE_MIDDLE_SUBSTRING
208# define SHARABLE_MIDDLE_SUBSTRING 0
212SHARABLE_SUBSTRING_P(
VALUE str,
long beg,
long len)
214#if SHARABLE_MIDDLE_SUBSTRING
217 long end = beg +
len;
218 long source_len = RSTRING_LEN(str);
219 return end == source_len || zero_filled(RSTRING_PTR(str) + end, TERM_LEN(str));
224str_embed_capa(
VALUE str)
226 return rb_obj_shape_slot_size(str) - offsetof(
struct RString, as.
embed.ary);
230rb_str_reembeddable_p(
VALUE str)
232 return !
FL_TEST(str, STR_NOFREE|STR_SHARED_ROOT|STR_SHARED);
238rb_str_embedded_shared_root_p(
VALUE str)
240 return STR_EMBED_P(str) &&
FL_TEST(str, STR_SHARED_ROOT);
244rb_str_embed_size(
long capa,
long termlen)
252rb_str_size_as_embedded(
VALUE str)
255 if (STR_EMBED_P(str)) {
257 if (
FL_TEST_RAW(str, STR_PRECOMPUTED_HASH))
capa +=
sizeof(st_index_t);
259 real_size = rb_str_embed_size(
capa, TERM_LEN(str));
263 else if (rb_str_reembeddable_p(str)) {
265 if (
FL_TEST_RAW(str, STR_PRECOMPUTED_HASH))
capa +=
sizeof(st_index_t);
267 real_size = rb_str_embed_size(
capa, TERM_LEN(str));
270 real_size =
sizeof(
struct RString);
277STR_EMBEDDABLE_P(
long len,
long termlen)
279 return rb_gc_size_allocatable_p(rb_str_embed_size(
len, termlen));
286#define STR_COPY_MAX_EMBED_SIZE 256
290static VALUE str_new_frozen_buffer(
VALUE klass,
VALUE orig,
int copy_encoding);
291static VALUE str_new_static(
VALUE klass,
const char *
ptr,
long len,
int encindex);
293static void str_make_independent_expand(
VALUE str,
long len,
long expand,
const int termlen);
294static inline void str_modifiable(
VALUE str);
299str_make_independent(
VALUE str)
301 long len = RSTRING_LEN(str);
302 int termlen = TERM_LEN(str);
303 str_make_independent_expand((str),
len, 0L, termlen);
306static inline int str_dependent_p(
VALUE str);
309rb_str_make_independent(
VALUE str)
311 if (str_dependent_p(str)) {
312 str_make_independent(str);
317rb_str_make_embedded(
VALUE str)
322 int termlen = TERM_LEN(str);
323 char *buf =
RSTRING(str)->as.heap.ptr;
324 long old_capa =
RSTRING(str)->as.heap.aux.capa + termlen;
328 STR_SET_LEN(str,
len);
331 memcpy(RSTRING_PTR(str), buf,
len);
332 SIZED_FREE_N(buf, old_capa);
339rb_debug_rstring_null_ptr(
const char *func)
341 fprintf(stderr,
"%s is returning NULL!! "
342 "SIGSEGV is highly expected to follow immediately.\n"
343 "If you could reproduce, attach your debugger here, "
344 "and look at the passed string.\n",
349static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
352get_encoding(
VALUE str)
358mustnot_broken(
VALUE str)
360 if (is_broken_string(str)) {
361 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str)));
366mustnot_wchar(
VALUE str)
369 if (rb_enc_mbminlen(enc) > 1) {
370 rb_raise(rb_eArgError,
"wide char encoding: %s", rb_enc_name(enc));
374static VALUE register_fstring(
VALUE str,
bool copy,
bool force_precompute_hash);
376#if SIZEOF_LONG == SIZEOF_VOIDP
377#define PRECOMPUTED_FAKESTR_HASH 1
382BARE_STRING_P(
VALUE str)
387static inline st_index_t
388str_do_hash(
VALUE str)
390 st_index_t h =
rb_memhash((
const void *)RSTRING_PTR(str), RSTRING_LEN(str));
392 if (e && !is_ascii_string(str)) {
399str_store_precomputed_hash(
VALUE str, st_index_t hash)
405 size_t used_bytes = (RSTRING_LEN(str) + TERM_LEN(str));
406 size_t free_bytes = str_embed_capa(str) - used_bytes;
410 memcpy(
RSTRING_END(str) + TERM_LEN(str), &hash,
sizeof(hash));
412 FL_SET(str, STR_PRECOMPUTED_HASH);
425 if (
FL_TEST(str, RSTRING_FSTR))
428 bare = BARE_STRING_P(str);
430 if (STR_EMBED_P(str)) {
435 if (
FL_TEST_RAW(str, STR_SHARED_ROOT | STR_SHARED) == STR_SHARED_ROOT) {
442 rb_str_resize(str, RSTRING_LEN(str));
444 fstr = register_fstring(str,
false,
false);
447 str_replace_shared_without_enc(str, fstr);
454static VALUE fstring_table_obj;
457fstring_concurrent_set_hash(
VALUE str)
459#ifdef PRECOMPUTED_FAKESTR_HASH
463 h = (st_index_t)
RSTRING(str)->as.heap.aux.capa;
480 const char *aptr, *bptr;
487 return (alen == blen &&
489 memcmp(aptr, bptr, alen) == 0);
494 bool force_precompute_hash;
498fstring_concurrent_set_create(
VALUE str,
void *data)
508 long len = RSTRING_LEN(str);
509 long capa =
len +
sizeof(st_index_t);
510 int term_len = TERM_LEN(str);
512 if (arg->force_precompute_hash && STR_EMBEDDABLE_P(
capa, term_len)) {
514 memcpy(RSTRING_PTR(new_str), RSTRING_PTR(str),
len);
515 STR_SET_LEN(new_str, RSTRING_LEN(str));
517 rb_enc_copy(new_str, str);
518 str_store_precomputed_hash(new_str, str_do_hash(str));
522 rb_enc_copy(new_str, str);
523#ifdef PRECOMPUTED_FAKESTR_HASH
524 if (
rb_str_capacity(new_str) >= RSTRING_LEN(str) + term_len +
sizeof(st_index_t)) {
525 str_store_precomputed_hash(new_str, (st_index_t)
RSTRING(str)->as.heap.aux.capa);
539 if (!
OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
542 if (STR_SHARED_P(str)) {
544 str_make_independent(str);
547 if (!BARE_STRING_P(str)) {
553 RBASIC(str)->flags |= RSTRING_FSTR;
555 RB_OBJ_SET_SHAREABLE(str);
569 .hash = fstring_concurrent_set_hash,
570 .cmp = fstring_concurrent_set_cmp,
571 .create = fstring_concurrent_set_create,
576Init_fstring_table(
void)
578 fstring_table_obj = rb_concurrent_set_new(&fstring_concurrent_set_funcs, 8192);
579 rb_gc_register_address(&fstring_table_obj);
583register_fstring(
VALUE str,
bool copy,
bool force_precompute_hash)
587 .force_precompute_hash = force_precompute_hash
590#if SIZEOF_VOIDP == SIZEOF_LONG
594 RSTRING(str)->as.heap.aux.capa = (long)str_do_hash(str);
598 VALUE result = rb_concurrent_set_find_or_insert(&fstring_table_obj, str, &args);
600 RUBY_ASSERT(!rb_objspace_garbage_object_p(result));
612rb_obj_is_fstring_table(
VALUE obj)
616 return obj == fstring_table_obj;
620rb_gc_free_fstring(
VALUE obj)
622 ASSERT_vm_locking_with_barrier();
628 rb_concurrent_set_delete_by_identity(fstring_table_obj, obj);
630 RB_DEBUG_COUNTER_INC(obj_str_fstr);
636rb_fstring_foreach_with_replace(
int (*callback)(
VALUE *str,
void *data),
void *data)
638 if (fstring_table_obj) {
639 rb_concurrent_set_foreach_with_replace(fstring_table_obj, callback, data);
644setup_fake_str(
struct RString *fake_str,
const char *name,
long len,
int encidx)
647 RBASIC_SET_FULL_SHAPE_ID((
VALUE)fake_str, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER);
660 return (
VALUE)fake_str;
669 return setup_fake_str(fake_str, name,
len, rb_enc_to_index(enc));
678rb_fstring_new(
const char *ptr,
long len)
680 struct RString fake_str = {RBASIC_INIT};
681 return register_fstring(setup_fake_str(&fake_str,
ptr,
len, ENCINDEX_US_ASCII),
false,
false);
687 struct RString fake_str = {RBASIC_INIT};
688 return register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
false,
false);
692rb_fstring_cstr(
const char *
ptr)
694 return rb_fstring_new(
ptr, strlen(
ptr));
698single_byte_optimizable(
VALUE str)
702 case ENCINDEX_ASCII_8BIT:
703 case ENCINDEX_US_ASCII:
725static inline const char *
726search_nonascii(
const char *p,
const char *e)
734#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
735# if SIZEOF_UINTPTR_T == 8
736# define NONASCII_MASK UINT64_C(0x8080808080808080)
737# elif SIZEOF_UINTPTR_T == 4
738# define NONASCII_MASK UINT32_C(0x80808080)
740# error "don't know what to do."
743# if SIZEOF_UINTPTR_T == 8
744# define NONASCII_MASK ((uintptr_t)0x80808080UL << 32 | (uintptr_t)0x80808080UL)
745# elif SIZEOF_UINTPTR_T == 4
746# define NONASCII_MASK 0x80808080UL
748# error "don't know what to do."
752 if (UNALIGNED_WORD_ACCESS || e - p >= SIZEOF_VOIDP) {
753#if !UNALIGNED_WORD_ACCESS
754 if ((uintptr_t)p % SIZEOF_VOIDP) {
755 int l = SIZEOF_VOIDP - (uintptr_t)p % SIZEOF_VOIDP;
760 case 7:
if (p[-7]&0x80)
return p-7;
761 case 6:
if (p[-6]&0x80)
return p-6;
762 case 5:
if (p[-5]&0x80)
return p-5;
763 case 4:
if (p[-4]&0x80)
return p-4;
765 case 3:
if (p[-3]&0x80)
return p-3;
766 case 2:
if (p[-2]&0x80)
return p-2;
767 case 1:
if (p[-1]&0x80)
return p-1;
772#if defined(HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED) &&! UNALIGNED_WORD_ACCESS
773#define aligned_ptr(value) \
774 __builtin_assume_aligned((value), sizeof(uintptr_t))
776#define aligned_ptr(value) (value)
779 t = (e - (SIZEOF_VOIDP-1));
781 for (;s < t; s +=
sizeof(uintptr_t)) {
783 memcpy(&word, s,
sizeof(word));
784 if (word & NONASCII_MASK) {
785#ifdef WORDS_BIGENDIAN
786 return (
const char *)s + (nlz_intptr(word&NONASCII_MASK)>>3);
788 return (
const char *)s + (ntz_intptr(word&NONASCII_MASK)>>3);
798 case 7:
if (e[-7]&0x80)
return e-7;
799 case 6:
if (e[-6]&0x80)
return e-6;
800 case 5:
if (e[-5]&0x80)
return e-5;
801 case 4:
if (e[-4]&0x80)
return e-4;
803 case 3:
if (e[-3]&0x80)
return e-3;
804 case 2:
if (e[-2]&0x80)
return e-2;
805 case 1:
if (e[-1]&0x80)
return e-1;
813 const char *e = p +
len;
815 if (rb_enc_to_index(enc) == rb_ascii8bit_encindex()) {
817 p = search_nonascii(p, e);
821 if (rb_enc_asciicompat(enc)) {
822 p = search_nonascii(p, e);
825 int ret = rb_enc_precise_mbclen(p, e, enc);
829 p = search_nonascii(p, e);
835 int ret = rb_enc_precise_mbclen(p, e, enc);
851 if (rb_enc_to_index(enc) == rb_ascii8bit_encindex()) {
854 p = search_nonascii(p, e);
858 else if (rb_enc_asciicompat(enc)) {
859 p = search_nonascii(p, e);
865 int ret = rb_enc_precise_mbclen(p, e, enc);
872 p = search_nonascii(p, e);
878 int ret = rb_enc_precise_mbclen(p, e, enc);
903 rb_enc_set_index(str1, rb_enc_get_index(str2));
911rb_enc_cr_str_copy_for_substr(
VALUE dest,
VALUE src)
916 str_enc_copy(dest, src);
917 if (RSTRING_LEN(dest) == 0) {
918 if (!rb_enc_asciicompat(STR_ENC_GET(src)))
929 if (!rb_enc_asciicompat(STR_ENC_GET(src)) ||
930 search_nonascii(RSTRING_PTR(dest),
RSTRING_END(dest)))
941rb_enc_cr_str_exact_copy(
VALUE dest,
VALUE src)
943 str_enc_copy(dest, src);
950 return coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc);
956 return enc_coderange_scan(str, enc);
960rbimpl_enc_str_coderange_scan(
VALUE str)
962 int cr = enc_coderange_scan(str, get_encoding(str));
967#undef rb_enc_str_coderange
974 cr = rbimpl_enc_str_coderange_scan(str);
978#define rb_enc_str_coderange rb_enc_str_coderange_inline
981rb_enc_str_asciicompat(
VALUE str)
984 return rb_str_encindex_fastpath(encindex) || rb_enc_asciicompat(rb_enc_get_from_index(encindex));
992 return rb_enc_str_asciicompat(str) && is_ascii_string(str);
1001str_mod_check(
VALUE s,
const char *p,
long len)
1003 if (RSTRING_PTR(s) != p || RSTRING_LEN(s) !=
len){
1009str_capacity(
VALUE str,
const int termlen)
1011 if (STR_EMBED_P(str)) {
1012 return str_embed_capa(str) - termlen;
1014 else if (
FL_ANY_RAW(str, STR_SHARED|STR_NOFREE)) {
1018 return RSTRING(str)->as.heap.aux.capa;
1025 return str_capacity(str, TERM_LEN(str));
1029must_not_null(
const char *
ptr)
1032 rb_raise(rb_eArgError,
"NULL pointer given");
1037str_alloc_embed(
VALUE klass,
size_t capa)
1039 size_t size = rb_str_embed_size(
capa, 0);
1046 str->as.embed.ary[0] = 0;
1052str_alloc_heap(
VALUE klass)
1057 str->as.heap.aux.capa = 0;
1058 str->as.heap.ptr = NULL;
1064empty_str_alloc(
VALUE klass)
1066 RUBY_DTRACE_CREATE_HOOK(STRING, 0);
1067 VALUE str = str_alloc_embed(klass, 0);
1068 memset(
RSTRING(str)->
as.embed.ary, 0, str_embed_capa(str));
1079 rb_raise(rb_eArgError,
"negative string size (or size too big)");
1083 enc = rb_ascii8bit_encoding();
1086 RUBY_DTRACE_CREATE_HOOK(STRING,
len);
1088 int termlen = rb_enc_mbminlen(enc);
1090 if (STR_EMBEDDABLE_P(
len, termlen)) {
1091 str = str_alloc_embed(klass,
len + termlen);
1097 str = str_alloc_heap(klass);
1103 rb_xmalloc_mul_add_mul(
sizeof(
char),
len,
sizeof(
char), termlen);
1106 rb_enc_raw_set(str, enc);
1109 memcpy(RSTRING_PTR(str),
ptr,
len);
1112 memset(RSTRING_PTR(str), 0,
len);
1115 STR_SET_LEN(str,
len);
1116 TERM_FILL(RSTRING_PTR(str) +
len, termlen);
1123 return str_enc_new(klass,
ptr,
len, rb_ascii8bit_encoding());
1158 __msan_unpoison_string(
ptr);
1178 if (rb_enc_mbminlen(enc) != 1) {
1179 rb_raise(rb_eArgError,
"wchar encoding given");
1181 return rb_enc_str_new(
ptr, strlen(
ptr), enc);
1185str_new_static(
VALUE klass,
const char *
ptr,
long len,
int encindex)
1190 rb_raise(rb_eArgError,
"negative string size (or size too big)");
1194 str = str_enc_new(klass,
ptr,
len, rb_enc_from_index(encindex));
1197 RUBY_DTRACE_CREATE_HOOK(STRING,
len);
1198 str = str_alloc_heap(klass);
1202 RBASIC(str)->flags |= STR_NOFREE;
1203 rb_enc_associate_index(str, encindex);
1218rb_str_new_owned(
char *
ptr,
long len,
long capa,
int encindex)
1220 RUBY_DTRACE_CREATE_HOOK(STRING,
len);
1227 rb_enc_associate_index(str, encindex);
1249static VALUE str_cat_conv_enc_opts(
VALUE newstr,
long ofs,
const char *
ptr,
long len,
1251 int ecflags,
VALUE ecopts);
1256 int encidx = rb_enc_to_index(enc);
1257 if (rb_enc_get_index(str) == encidx)
1258 return is_ascii_string(str);
1269 if (!to)
return str;
1270 if (!from) from = rb_enc_get(str);
1271 if (from == to)
return str;
1272 if ((rb_enc_asciicompat(to) && is_enc_ascii_string(str, from)) ||
1273 rb_is_ascii8bit_enc(to)) {
1274 if (STR_ENC_GET(str) != to) {
1276 rb_enc_associate(str, to);
1283 from, to, ecflags, ecopts);
1284 if (
NIL_P(newstr)) {
1292rb_str_cat_conv_enc_opts(
VALUE newstr,
long ofs,
const char *
ptr,
long len,
1297 olen = RSTRING_LEN(newstr);
1298 if (ofs < -olen || olen < ofs)
1300 if (ofs < 0) ofs += olen;
1302 STR_SET_LEN(newstr, ofs);
1306 rb_str_modify(newstr);
1307 return str_cat_conv_enc_opts(newstr, ofs,
ptr,
len, from,
1315 STR_SET_LEN(str, 0);
1316 rb_enc_associate(str, enc);
1322str_cat_conv_enc_opts(
VALUE newstr,
long ofs,
const char *
ptr,
long len,
1324 int ecflags,
VALUE ecopts)
1329 VALUE econv_wrapper;
1330 const unsigned char *start, *sp;
1331 unsigned char *dest, *dp;
1332 size_t converted_output = (size_t)ofs;
1337 RBASIC_CLEAR_CLASS(econv_wrapper);
1339 if (!ec)
return Qnil;
1342 sp = (
unsigned char*)
ptr;
1344 while ((dest = (
unsigned char*)RSTRING_PTR(newstr)),
1345 (dp = dest + converted_output),
1349 size_t converted_input = sp - start;
1350 size_t rest =
len - converted_input;
1351 converted_output = dp - dest;
1353 if (converted_input && converted_output &&
1354 rest < (LONG_MAX / converted_output)) {
1355 rest = (rest * converted_output) / converted_input;
1360 olen += rest < 2 ? 2 : rest;
1361 rb_str_resize(newstr, olen);
1368 len = dp - (
unsigned char*)RSTRING_PTR(newstr);
1370 rb_enc_associate(newstr, to);
1389 const int eidx = rb_enc_to_index(eenc);
1392 return rb_enc_str_new(
ptr,
len, eenc);
1396 if ((eidx == rb_ascii8bit_encindex()) ||
1397 (eidx == rb_usascii_encindex() && search_nonascii(
ptr,
ptr +
len))) {
1401 ienc = rb_default_internal_encoding();
1402 if (!ienc || eenc == ienc) {
1403 return rb_enc_str_new(
ptr,
len, eenc);
1407 if ((eidx == rb_ascii8bit_encindex()) ||
1408 (eidx == rb_usascii_encindex()) ||
1409 (rb_enc_asciicompat(eenc) && !search_nonascii(
ptr,
ptr +
len))) {
1410 return rb_enc_str_new(
ptr,
len, ienc);
1413 str = rb_enc_str_new(NULL, 0, ienc);
1416 if (
NIL_P(rb_str_cat_conv_enc_opts(str, 0,
ptr,
len, eenc, 0,
Qnil))) {
1417 rb_str_initialize(str,
ptr,
len, eenc);
1425 int eidx = rb_enc_to_index(eenc);
1426 if (eidx == rb_usascii_encindex() &&
1427 !is_ascii_string(str)) {
1428 rb_enc_associate_index(str, rb_ascii8bit_encindex());
1431 rb_enc_associate_index(str, eidx);
1490str_replace_shared_without_enc(
VALUE str2,
VALUE str)
1492 const int termlen = TERM_LEN(str);
1497 if (str_embed_capa(str2) >=
len + termlen) {
1498 char *ptr2 =
RSTRING(str2)->as.embed.ary;
1499 STR_SET_EMBED(str2);
1500 memcpy(ptr2, RSTRING_PTR(str),
len);
1501 TERM_FILL(ptr2+
len, termlen);
1505 if (STR_SHARED_P(str)) {
1506 root =
RSTRING(str)->as.heap.aux.shared;
1515 if (!STR_EMBED_P(str2) && !
FL_TEST_RAW(str2, STR_SHARED|STR_NOFREE)) {
1517 rb_fatal(
"about to free a possible shared root");
1519 char *ptr2 = STR_HEAP_PTR(str2);
1521 SIZED_FREE_N(ptr2, STR_HEAP_SIZE(str2));
1524 FL_SET(str2, STR_NOEMBED);
1526 STR_SET_SHARED(str2, root);
1529 STR_SET_LEN(str2,
len);
1537 str_replace_shared_without_enc(str2, str);
1538 rb_enc_cr_str_exact_copy(str2, str);
1545 return str_replace_shared(str_alloc_heap(klass), str);
1562rb_str_new_frozen_String(
VALUE orig)
1570rb_str_frozen_bare_string(
VALUE orig)
1572 if (RB_LIKELY(BARE_STRING_P(orig) &&
OBJ_FROZEN_RAW(orig)))
return orig;
1577rb_str_tmp_frozen_acquire(
VALUE orig)
1580 return str_new_frozen_buffer(0, orig, FALSE);
1584rb_str_tmp_frozen_no_embed_acquire(
VALUE orig)
1586 if (
OBJ_FROZEN_RAW(orig) && !STR_EMBED_P(orig) && !rb_str_reembeddable_p(orig))
return orig;
1587 if (STR_SHARED_P(orig) && !STR_EMBED_P(
RSTRING(orig)->
as.heap.aux.shared))
return rb_str_tmp_frozen_acquire(orig);
1589 VALUE str = str_alloc_heap(0);
1592 FL_SET(str, STR_SHARED_ROOT);
1594 size_t capa = str_capacity(orig, TERM_LEN(orig));
1600 if (STR_EMBED_P(orig) ||
FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT | RSTRING_FSTR)) {
1601 RSTRING(str)->as.heap.ptr = rb_xmalloc_mul_add_mul(
sizeof(
char),
capa,
sizeof(
char), TERM_LEN(orig));
1608 RBASIC(str)->flags |=
RBASIC(orig)->flags & STR_NOFREE;
1609 RBASIC(orig)->flags &= ~STR_NOFREE;
1610 STR_SET_SHARED(orig, str);
1612 RB_OBJ_SET_SHAREABLE(str);
1618 RSTRING(str)->as.heap.aux.capa =
capa + (TERM_LEN(orig) - TERM_LEN(str));
1624rb_str_tmp_frozen_release(
VALUE orig,
VALUE tmp)
1629 if (STR_EMBED_P(tmp)) {
1632 else if (
FL_TEST_RAW(orig, STR_SHARED | STR_TMPLOCK) == STR_TMPLOCK &&
1638 RUBY_ASSERT(RSTRING_LEN(orig) == RSTRING_LEN(tmp));
1642 RSTRING(orig)->as.heap.aux.capa =
RSTRING(tmp)->as.heap.aux.capa;
1643 RBASIC(orig)->flags |=
RBASIC(tmp)->flags & STR_NOFREE;
1648 STR_SET_LEN(tmp, 0);
1656 return str_new_frozen_buffer(klass, orig, TRUE);
1666 VALUE str = str_alloc_heap(klass);
1667 STR_SET_LEN(str, RSTRING_LEN(orig));
1668 RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig);
1669 RSTRING(str)->as.heap.aux.capa =
RSTRING(orig)->as.heap.aux.capa;
1670 RBASIC(str)->flags |=
RBASIC(orig)->flags & STR_NOFREE;
1671 RBASIC(orig)->flags &= ~STR_NOFREE;
1672 STR_SET_SHARED(orig, str);
1679str_new_frozen_buffer(
VALUE klass,
VALUE orig,
int copy_encoding)
1683 long len = RSTRING_LEN(orig);
1684 rb_encoding *enc = copy_encoding ? STR_ENC_GET(orig) : rb_ascii8bit_encoding();
1685 int termlen = copy_encoding ? TERM_LEN(orig) : 1;
1687 if (STR_EMBED_P(orig) || STR_EMBEDDABLE_P(
len, termlen)) {
1688 str = str_enc_new(klass, RSTRING_PTR(orig),
len, enc);
1694 long ofs =
RSTRING(orig)->as.heap.ptr - RSTRING_PTR(
shared);
1695 long rest = RSTRING_LEN(
shared) - ofs - RSTRING_LEN(orig);
1701 if ((ofs > 0) || (rest > 0) ||
1704 str = str_new_shared(klass,
shared);
1706 RSTRING(str)->as.heap.ptr += ofs;
1707 STR_SET_LEN(str, RSTRING_LEN(str) - (ofs + rest));
1715 else if (STR_EMBEDDABLE_P(RSTRING_LEN(orig), TERM_LEN(orig))) {
1716 str = str_alloc_embed(klass, RSTRING_LEN(orig) + TERM_LEN(orig));
1718 memcpy(RSTRING_PTR(str), RSTRING_PTR(orig), RSTRING_LEN(orig));
1719 STR_SET_LEN(str, RSTRING_LEN(orig));
1725 str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig));
1728 str = heap_str_make_shared(klass, orig);
1733 if (copy_encoding) rb_enc_cr_str_exact_copy(str, orig);
1745str_new_empty_String(
VALUE str)
1748 rb_enc_copy(v, str);
1752#define STR_BUF_MIN_SIZE 63
1757 if (STR_EMBEDDABLE_P(
capa, 1)) {
1765 RSTRING(str)->as.heap.ptr[0] =
'\0';
1785 return str_new(0, 0,
len);
1791 if (STR_EMBED_P(str)) {
1792 RB_DEBUG_COUNTER_INC(obj_str_embed);
1794 else if (
FL_TEST(str, STR_SHARED | STR_NOFREE)) {
1795 (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared,
FL_TEST(str, STR_SHARED));
1796 (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared,
FL_TEST(str, STR_NOFREE));
1799 RB_DEBUG_COUNTER_INC(obj_str_ptr);
1800 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
1805rb_str_memsize(
VALUE str)
1807 if (
FL_TEST(str, STR_NOEMBED|STR_SHARED|STR_NOFREE) == STR_NOEMBED) {
1808 return STR_HEAP_SIZE(str);
1818 return rb_convert_type_with_id(str,
T_STRING,
"String", idTo_str);
1821static inline void str_discard(
VALUE str);
1822static void str_shared_replace(
VALUE str,
VALUE str2);
1827 if (str != str2) str_shared_replace(str, str2);
1838 enc = STR_ENC_GET(str2);
1841 termlen = rb_enc_mbminlen(enc);
1843 STR_SET_LEN(str, RSTRING_LEN(str2));
1845 if (str_embed_capa(str) >= RSTRING_LEN(str2) + termlen) {
1847 memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), (
size_t)RSTRING_LEN(str2) + termlen);
1848 rb_enc_associate(str, enc);
1852 if (STR_EMBED_P(str2)) {
1854 long len = RSTRING_LEN(str2);
1857 char *new_ptr =
ALLOC_N(
char,
len + termlen);
1858 memcpy(new_ptr,
RSTRING(str2)->
as.embed.ary,
len + termlen);
1859 RSTRING(str2)->as.heap.ptr = new_ptr;
1860 STR_SET_LEN(str2,
len);
1862 STR_SET_NOEMBED(str2);
1865 STR_SET_NOEMBED(str);
1867 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
1869 if (
FL_TEST(str2, STR_SHARED)) {
1871 STR_SET_SHARED(str,
shared);
1874 RSTRING(str)->as.heap.aux.capa =
RSTRING(str2)->as.heap.aux.capa;
1878 STR_SET_EMBED(str2);
1879 RSTRING_PTR(str2)[0] = 0;
1880 STR_SET_LEN(str2, 0);
1881 rb_enc_associate(str, enc);
1895 return rb_obj_as_string_result(str, obj);
1911 len = RSTRING_LEN(str2);
1912 if (STR_SHARED_P(str2)) {
1915 STR_SET_NOEMBED(str);
1916 STR_SET_LEN(str,
len);
1917 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
1918 STR_SET_SHARED(str,
shared);
1919 rb_enc_cr_str_exact_copy(str, str2);
1922 str_replace_shared(str, str2);
1931 size_t size = rb_str_embed_size(
capa, 0);
1947 str->as.heap.aux.capa = 0;
1948 str->as.heap.ptr = NULL;
1958 encidx = rb_enc_get_index(str);
1959 flags &= ~ENCODING_MASK;
1962 if (encidx) rb_enc_associate_index(dup, encidx);
1971 long len = RSTRING_LEN(str);
1976 STR_SET_LEN(dup, RSTRING_LEN(str));
1977 str_duplicate_setup_encoding(str, dup, flags);
1986 root =
RSTRING(str)->as.heap.aux.shared;
1989 root = str = str_new_frozen(klass, str);
1995 RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str);
1997 STR_SET_SHARED(dup, root);
1998 flags |= RSTRING_NOEMBED | STR_SHARED;
2000 STR_SET_LEN(dup, RSTRING_LEN(str));
2001 str_duplicate_setup_encoding(str, dup, flags);
2008 if (STR_EMBED_P(str) && rb_str_embed_size(RSTRING_LEN(str), 1) <= STR_COPY_MAX_EMBED_SIZE) {
2009 dup = str_alloc_embed(klass, RSTRING_LEN(str) + TERM_LEN(str));
2011 str_duplicate_setup_embed(klass, str, dup);
2014 dup = str_alloc_heap(klass);
2016 str_duplicate_setup_heap(klass, str, dup);
2030rb_str_dup_m(
VALUE str)
2032 if (LIKELY(BARE_STRING_P(str))) {
2043 RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
2050 RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
2054 new_str = ec_str_alloc_embed(ec, klass, RSTRING_LEN(str) + TERM_LEN(str));
2055 str_duplicate_setup_embed(klass, str, new_str);
2058 new_str = ec_str_alloc_heap(ec, klass);
2059 str_duplicate_setup_heap(klass, str, new_str);
2069rb_zjit_str_resurrect_fastpath(
VALUE str,
bool chilled,
size_t *size_out,
2071 long *len_out,
size_t *byte_size_out)
2075 if (!STR_EMBED_P(str))
return false;
2077 long len = RSTRING_LEN(str);
2078 long termlen = TERM_LEN(str);
2079 size_t size = rb_str_embed_size(
len + termlen, 0);
2080 if (!rb_gc_size_allocatable_p(size))
return false;
2088 flags &= ~FL_FREEZE;
2090 if (chilled) flags |= STR_CHILLED;
2095 *byte_size_out = (size_t)(
len + termlen);
2101rb_str_with_debug_created_info(
VALUE str,
VALUE path,
int line)
2103 VALUE debug_info = rb_ary_new_from_args(2, path,
INT2FIX(line));
2127 static ID keyword_ids[2];
2128 VALUE orig, opt, venc, vcapa;
2133 if (!keyword_ids[0]) {
2134 keyword_ids[0] = rb_id_encoding();
2135 CONST_ID(keyword_ids[1],
"capacity");
2143 if (!UNDEF_P(venc) && !
NIL_P(venc)) {
2144 enc = rb_to_encoding(venc);
2146 if (!UNDEF_P(vcapa) && !
NIL_P(vcapa)) {
2149 int termlen = enc ? rb_enc_mbminlen(enc) : 1;
2151 if (
capa < STR_BUF_MIN_SIZE) {
2152 capa = STR_BUF_MIN_SIZE;
2156 len = RSTRING_LEN(orig);
2160 if (orig == str) n = 0;
2162 str_modifiable(str);
2163 if (STR_EMBED_P(str) ||
FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2165 const size_t size = (size_t)
capa + termlen;
2166 const char *
const old_ptr = RSTRING_PTR(str);
2167 const size_t osize = RSTRING_LEN(str) + TERM_LEN(str);
2168 char *new_ptr =
ALLOC_N(
char, size);
2169 if (STR_EMBED_P(str))
RUBY_ASSERT((
long)osize <= str_embed_capa(str));
2170 memcpy(new_ptr, old_ptr, osize < size ? osize : size);
2172 RSTRING(str)->as.heap.ptr = new_ptr;
2174 else if (STR_HEAP_SIZE(str) != (
size_t)
capa + termlen) {
2175 SIZED_REALLOC_N(
RSTRING(str)->
as.heap.ptr,
char,
2176 (
size_t)
capa + termlen, STR_HEAP_SIZE(str));
2178 STR_SET_LEN(str,
len);
2181 memcpy(
RSTRING(str)->
as.heap.ptr, RSTRING_PTR(orig),
len);
2182 rb_enc_cr_str_exact_copy(str, orig);
2184 FL_SET(str, STR_NOEMBED);
2191 rb_enc_associate(str, enc);
2203rb_str_s_new(
int argc,
VALUE *argv,
VALUE klass)
2209 static ID keyword_ids[2];
2219 keyword_ids[0] = rb_id_encoding();
2220 CONST_ID(keyword_ids[1],
"capacity");
2222 encoding = kwargs[0];
2223 capacity = kwargs[1];
2232 if (UNDEF_P(encoding)) {
2234 encoding = rb_obj_encoding(orig);
2238 if (!UNDEF_P(encoding)) {
2239 enc = rb_to_encoding(encoding);
2243 if (UNDEF_P(capacity)) {
2245 VALUE empty_str = str_new(klass,
"", 0);
2247 rb_enc_associate(empty_str, enc);
2251 VALUE copy = str_duplicate(klass, orig);
2252 rb_enc_associate(copy, enc);
2265 if (orig_capa >
capa) {
2270 VALUE str = str_enc_new(klass, NULL,
capa, enc);
2271 STR_SET_LEN(str, 0);
2282#define is_utf8_lead_byte(c) (((c)&0xC0) != 0x80)
2297static inline uintptr_t
2298count_utf8_lead_bytes_with_word(
const uintptr_t *s)
2303 d = (d>>6) | (~d>>7);
2304 d &= NONASCII_MASK >> 7;
2307#if defined(HAVE_BUILTIN___BUILTIN_POPCOUNT) && defined(__POPCNT__)
2309 return rb_popcount_intptr(d);
2313# if SIZEOF_VOIDP == 8
2322enc_strlen(
const char *p,
const char *e,
rb_encoding *enc,
int cr)
2328 long diff = (long)(e - p);
2329 return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
2334 if ((
int)
sizeof(uintptr_t) * 2 < e - p) {
2335 const uintptr_t *s, *t;
2336 const uintptr_t lowbits =
sizeof(uintptr_t) - 1;
2337 s = (
const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
2338 t = (
const uintptr_t*)(~lowbits & (uintptr_t)e);
2339 while (p < (
const char *)s) {
2340 if (is_utf8_lead_byte(*p))
len++;
2344 len += count_utf8_lead_bytes_with_word(s);
2347 p = (
const char *)s;
2350 if (is_utf8_lead_byte(*p))
len++;
2356 else if (rb_enc_asciicompat(enc)) {
2360 q = search_nonascii(p, e);
2365 p += rb_enc_fast_mbclen(p, e, enc);
2371 q = search_nonascii(p, e);
2376 p += rb_enc_mbclen(p, e, enc);
2383 for (c=0; p<e; c++) {
2384 p += rb_enc_mbclen(p, e, enc);
2399rb_enc_strlen_cr(
const char *p,
const char *e,
rb_encoding *enc,
int *cr)
2407 long diff = (long)(e - p);
2408 return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
2410 else if (rb_enc_asciicompat(enc)) {
2413 q = search_nonascii(p, e);
2420 ret = rb_enc_precise_mbclen(p, e, enc);
2435 for (c=0; p<e; c++) {
2436 ret = rb_enc_precise_mbclen(p, e, enc);
2443 if (p + rb_enc_mbminlen(enc) <= e)
2444 p += rb_enc_mbminlen(enc);
2460 if (single_byte_optimizable(str))
return RSTRING_LEN(str);
2461 if (!enc) enc = STR_ENC_GET(str);
2462 p = RSTRING_PTR(str);
2467 long n = rb_enc_strlen_cr(p, e, enc, &cr);
2472 return enc_strlen(p, e, enc, cr);
2479 return str_strlen(str, NULL);
2493 return LONG2NUM(str_strlen(str, NULL));
2505rb_str_bytesize(
VALUE str)
2524rb_str_empty(
VALUE str)
2526 return RBOOL(RSTRING_LEN(str) == 0);
2545 const char *ptr1, *ptr2;
2551 enc = rb_enc_check_str(str1, str2);
2554 termlen = rb_enc_mbminlen(enc);
2555 if (len1 > LONG_MAX - len2) {
2556 rb_raise(rb_eArgError,
"string size too big");
2558 str3 = str_enc_new(
rb_cString, 0, len1+len2, enc);
2559 ptr3 = RSTRING_PTR(str3);
2560 memcpy(ptr3, ptr1, len1);
2561 memcpy(ptr3+len1, ptr2, len2);
2562 TERM_FILL(&ptr3[len1+len2], termlen);
2578 MAYBE_UNUSED(
char) *ptr1, *ptr2;
2581 int enc1 = rb_enc_get_index(str1);
2582 int enc2 = rb_enc_get_index(str2);
2587 else if (enc2 < 0) {
2590 else if (enc1 != enc2) {
2593 else if (len1 > LONG_MAX - len2) {
2627 rb_enc_copy(str2, str);
2632 rb_raise(rb_eArgError,
"negative argument");
2634 if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
2635 if (STR_EMBEDDABLE_P(
len, 1)) {
2637 memset(RSTRING_PTR(str2), 0,
len + 1);
2644 STR_SET_LEN(str2,
len);
2645 rb_enc_copy(str2, str);
2648 if (
len && LONG_MAX/
len < RSTRING_LEN(str)) {
2649 rb_raise(rb_eArgError,
"argument too big");
2652 len *= RSTRING_LEN(str);
2653 termlen = TERM_LEN(str);
2655 ptr2 = RSTRING_PTR(str2);
2657 n = RSTRING_LEN(str);
2658 memcpy(ptr2, RSTRING_PTR(str), n);
2659 while (n <=
len/2) {
2660 memcpy(ptr2 + n, ptr2, n);
2663 memcpy(ptr2 + n, ptr2,
len-n);
2665 STR_SET_LEN(str2,
len);
2666 TERM_FILL(&ptr2[
len], termlen);
2667 rb_enc_cr_str_copy_for_substr(str2, str);
2706rb_check_lockedtmp(
VALUE str)
2708 if (
FL_TEST(str, STR_TMPLOCK)) {
2715#define STR_UNMODIFIABLE_MASK (FL_FREEZE | STR_TMPLOCK | STR_CHILLED)
2717str_modifiable(
VALUE str)
2721 if (RB_UNLIKELY(
FL_ANY_RAW(str, STR_UNMODIFIABLE_MASK))) {
2722 if (CHILLED_STRING_P(str)) {
2723 CHILLED_STRING_MUTATED(str);
2725 rb_check_lockedtmp(str);
2726 rb_check_frozen(str);
2731str_dependent_p(
VALUE str)
2733 if (STR_EMBED_P(str) || !
FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2743#define STR_DEPENDANT_MASK (STR_UNMODIFIABLE_MASK | STR_SHARED | STR_NOFREE)
2745str_independent(
VALUE str)
2749 if (RB_UNLIKELY(
FL_ANY_RAW(str, STR_DEPENDANT_MASK))) {
2750 str_modifiable(str);
2751 return !str_dependent_p(str);
2757str_make_independent_expand(
VALUE str,
long len,
long expand,
const int termlen)
2767 if (!STR_EMBED_P(str) && str_embed_capa(str) >=
capa + termlen) {
2772 STR_SET_LEN(str,
len);
2777 oldptr = RSTRING_PTR(str);
2779 memcpy(
ptr, oldptr,
len);
2781 if (
FL_TEST_RAW(str, STR_NOEMBED|STR_NOFREE|STR_SHARED) == STR_NOEMBED) {
2782 SIZED_FREE_N(oldptr, STR_HEAP_SIZE(str));
2784 STR_SET_NOEMBED(str);
2785 FL_UNSET(str, STR_SHARED|STR_NOFREE);
2786 TERM_FILL(
ptr +
len, termlen);
2788 STR_SET_LEN(str,
len);
2795 if (!str_independent(str))
2796 str_make_independent(str);
2805 int termlen = TERM_LEN(str);
2806 long len = RSTRING_LEN(str);
2809 rb_raise(rb_eArgError,
"negative expanding string size");
2811 if (expand >= LONG_MAX -
len) {
2812 rb_raise(rb_eArgError,
"string size too big");
2815 if (!str_independent(str)) {
2816 str_make_independent_expand(str,
len, expand, termlen);
2818 else if (expand > 0) {
2819 RESIZE_CAPA_TERM(str,
len + expand, termlen);
2826str_modify_keep_cr(
VALUE str)
2828 if (!str_independent(str))
2829 str_make_independent(str);
2836str_discard(
VALUE str)
2838 str_modifiable(str);
2839 if (!STR_EMBED_P(str) && !
FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2840 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
2841 RSTRING(str)->as.heap.ptr = 0;
2842 STR_SET_LEN(str, 0);
2849 int encindex = rb_enc_get_index(str);
2851 if (RB_UNLIKELY(encindex == -1)) {
2855 if (RB_LIKELY(rb_str_encindex_fastpath(encindex))) {
2860 if (!rb_enc_asciicompat(enc)) {
2882 return RSTRING_PTR(str);
2886str_null_char(
const char *s,
long len,
const int minlen,
rb_encoding *enc)
2888 const char *e = s +
len;
2890 for (; s + minlen <= e; s += rb_enc_mbclen(s, e, enc)) {
2891 if (zero_filled(s, minlen))
return s;
2897str_fill_term(
VALUE str,
char *s,
long len,
int termlen)
2902 if (str_dependent_p(str)) {
2903 if (!zero_filled(s +
len, termlen))
2904 str_make_independent_expand(str,
len, 0L, termlen);
2907 TERM_FILL(s +
len, termlen);
2910 return RSTRING_PTR(str);
2914rb_str_change_terminator_length(
VALUE str,
const int oldtermlen,
const int termlen)
2916 long capa = str_capacity(str, oldtermlen) + oldtermlen;
2917 long len = RSTRING_LEN(str);
2921 rb_check_lockedtmp(str);
2922 str_make_independent_expand(str,
len, 0L, termlen);
2924 else if (str_dependent_p(str)) {
2925 if (termlen > oldtermlen)
2926 str_make_independent_expand(str,
len, 0L, termlen);
2929 if (!STR_EMBED_P(str)) {
2934 if (termlen > oldtermlen) {
2935 TERM_FILL(RSTRING_PTR(str) +
len, termlen);
2943str_null_check(
VALUE str,
int *w)
2945 char *s = RSTRING_PTR(str);
2946 long len = RSTRING_LEN(str);
2949 if (RB_UNLIKELY(!rb_str_enc_fastpath(str))) {
2951 minlen = rb_enc_mbminlen(enc);
2955 if (str_null_char(s,
len, minlen, enc)) {
2958 return str_fill_term(str, s,
len, minlen);
2963 if (!s || memchr(s, 0,
len)) {
2967 s = str_fill_term(str, s,
len, minlen);
2972static char *str_to_cstr(
VALUE str);
2975rb_str_null_check(
VALUE str)
2983 if (RB_LIKELY(rb_str_enc_fastpath(str))) {
2984 if (!s || memchr(s, 0,
len)) {
2985 rb_raise(rb_eArgError,
"string contains null byte");
2996rb_str_to_cstr(
VALUE str)
2999 return str_null_check(str, &w);
3006 return str_to_cstr(str);
3010str_to_cstr(
VALUE str)
3013 char *s = str_null_check(str, &w);
3016 rb_raise(rb_eArgError,
"string contains null char");
3018 rb_raise(rb_eArgError,
"string contains null byte");
3024rb_str_fill_terminator(
VALUE str,
const int newminlen)
3026 char *s = RSTRING_PTR(str);
3027 long len = RSTRING_LEN(str);
3028 return str_fill_term(str, s,
len, newminlen);
3034 str = rb_check_convert_type_with_id(str,
T_STRING,
"String", idTo_str);
3060str_nth_len(
const char *p,
const char *e,
long *nthp,
rb_encoding *enc)
3069 else if (rb_enc_asciicompat(enc)) {
3070 const char *p2, *e2;
3073 while (p < e && 0 < nth) {
3079 p2 = search_nonascii(p, e2);
3087 n = rb_enc_mbclen(p, e, enc);
3098 while (p < e && nth--) {
3099 p += rb_enc_mbclen(p, e, enc);
3110 return str_nth_len(p, e, &nth, enc);
3114str_nth(
const char *p,
const char *e,
long nth,
rb_encoding *enc,
int singlebyte)
3119 p = str_nth_len(p, e, &nth, enc);
3128str_offset(
const char *p,
const char *e,
long nth,
rb_encoding *enc,
int singlebyte)
3130 const char *pp = str_nth(p, e, nth, enc, singlebyte);
3131 if (!pp)
return e - p;
3138 return str_offset(RSTRING_PTR(str),
RSTRING_END(str), pos,
3139 STR_ENC_GET(str), single_byte_optimizable(str));
3144str_utf8_nth(
const char *p,
const char *e,
long *nthp)
3147 if ((
int)SIZEOF_VOIDP * 2 < e - p && (
int)SIZEOF_VOIDP * 2 < nth) {
3148 const uintptr_t *s, *t;
3149 const uintptr_t lowbits = SIZEOF_VOIDP - 1;
3150 s = (
const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
3151 t = (
const uintptr_t*)(~lowbits & (uintptr_t)e);
3152 while (p < (
const char *)s) {
3153 if (is_utf8_lead_byte(*p)) nth--;
3157 nth -= count_utf8_lead_bytes_with_word(s);
3159 }
while (s < t && (
int)SIZEOF_VOIDP <= nth);
3163 if (is_utf8_lead_byte(*p)) {
3164 if (nth == 0)
break;
3174str_utf8_offset(
const char *p,
const char *e,
long nth)
3176 const char *pp = str_utf8_nth(p, e, &nth);
3185 if (single_byte_optimizable(str) || pos < 0)
3188 const char *p = RSTRING_PTR(str);
3189 return enc_strlen(p, p + pos, STR_ENC_GET(str),
ENC_CODERANGE(str));
3194str_subseq(
VALUE str,
long beg,
long len)
3202 const int termlen = TERM_LEN(str);
3203 if (!SHARABLE_SUBSTRING_P(str, beg,
len)) {
3204 str2 = rb_enc_str_new(RSTRING_PTR(str) + beg,
len, rb_str_enc_get(str));
3214 const bool root_available = STR_SHARED_P(str) ||
3216 const size_t max_embed_size = root_available ?
3217 rb_gc_size_slot_size(
sizeof(
struct RString)) : STR_COPY_MAX_EMBED_SIZE;
3218 const size_t embed_size = rb_str_embed_size(
len, termlen);
3220 if (embed_size <= max_embed_size && rb_gc_size_allocatable_p(embed_size)) {
3222 char *ptr2 =
RSTRING(str2)->as.embed.ary;
3223 memcpy(ptr2, RSTRING_PTR(str) + beg,
len);
3224 TERM_FILL(ptr2 +
len, termlen);
3226 STR_SET_LEN(str2,
len);
3235 str_replace_shared(str2, str);
3241 RSTRING(str2)->as.heap.ptr += beg;
3242 if (RSTRING_LEN(str2) >
len) {
3243 STR_SET_LEN(str2,
len);
3253 VALUE str2 = str_subseq(str, beg,
len);
3254 rb_enc_cr_str_copy_for_substr(str2, str);
3263 const long blen = RSTRING_LEN(str);
3265 const char *p, *s = RSTRING_PTR(str), *e = s + blen;
3267 if (
len < 0)
return 0;
3268 if (beg < 0 && -beg < 0)
return 0;
3272 if (single_byte_optimizable(str)) {
3273 if (beg > blen)
return 0;
3276 if (beg < 0)
return 0;
3278 if (
len > blen - beg)
3280 if (
len < 0)
return 0;
3285 if (
len > -beg)
len = -beg;
3289 while (beg-- >
len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
3292 while (
len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0);
3298 slen = str_strlen(str, enc);
3300 if (beg < 0)
return 0;
3302 if (
len == 0)
goto end;
3305 else if (beg > 0 && beg > blen) {
3309 if (beg > str_strlen(str, enc))
return 0;
3314 enc == rb_utf8_encoding()) {
3315 p = str_utf8_nth(s, e, &beg);
3316 if (beg > 0)
return 0;
3317 len = str_utf8_offset(p, e,
len);
3323 p = s + beg * char_sz;
3327 else if (
len * char_sz > e - p)
3332 else if ((p = str_nth_len(s, e, &beg, enc)) == e) {
3333 if (beg > 0)
return 0;
3337 len = str_offset(p, e,
len, enc, 0);
3345static VALUE str_substr(
VALUE str,
long beg,
long len,
int empty);
3350 return str_substr(str, beg,
len, TRUE);
3360str_substr(
VALUE str,
long beg,
long len,
int empty)
3364 if (!p)
return Qnil;
3365 if (!
len && !empty)
return Qnil;
3367 beg = p - RSTRING_PTR(str);
3369 VALUE str2 = str_subseq(str, beg,
len);
3370 rb_enc_cr_str_copy_for_substr(str2, str);
3378 if (CHILLED_STRING_P(str)) {
3383 rb_str_resize(str, RSTRING_LEN(str));
3401 if (
OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
3444str_uminus(
VALUE str)
3449 return rb_fstring(str);
3453#define rb_str_dup_frozen rb_str_new_frozen
3458 rb_check_frozen(str);
3459 if (
FL_TEST(str, STR_TMPLOCK)) {
3462 FL_SET(str, STR_TMPLOCK);
3469 rb_check_frozen(str);
3470 if (!
FL_TEST(str, STR_TMPLOCK)) {
3490 const int termlen = TERM_LEN(str);
3492 str_modifiable(str);
3493 if (STR_SHARED_P(str)) {
3496 if (
len > (
capa = (
long)str_capacity(str, termlen)) ||
len < 0) {
3497 rb_bug(
"probable buffer overflow: %ld for %ld",
len,
capa);
3508 else if (
len > RSTRING_LEN(str)) {
3512 const char *
const new_end = RSTRING_PTR(str) +
len;
3522 else if (
len < RSTRING_LEN(str)) {
3530 STR_SET_LEN(str,
len);
3531 TERM_FILL(&RSTRING_PTR(str)[
len], termlen);
3538 rb_raise(rb_eArgError,
"negative string size (or size too big)");
3541 int independent = str_independent(str);
3542 long slen = RSTRING_LEN(str);
3543 const int termlen = TERM_LEN(str);
3545 if (slen >
len || (termlen != 1 && slen <
len)) {
3551 if (STR_EMBED_P(str)) {
3552 if (
len == slen)
return str;
3553 if (str_embed_capa(str) >=
len + termlen) {
3554 STR_SET_LEN(str,
len);
3558 str_make_independent_expand(str, slen,
len - slen, termlen);
3560 else if (str_embed_capa(str) >=
len + termlen) {
3562 char *
ptr = STR_HEAP_PTR(str);
3564 if (slen >
len) slen =
len;
3567 STR_SET_LEN(str,
len);
3569 SIZED_FREE_N(
ptr,
capa + termlen);
3573 else if (!independent) {
3574 if (
len == slen)
return str;
3575 str_make_independent_expand(str, slen,
len - slen, termlen);
3579 SIZED_REALLOC_N(
RSTRING(str)->
as.heap.ptr,
char,
3580 (
size_t)
len + termlen, STR_HEAP_SIZE(str));
3583 else if (
len == slen)
return str;
3584 STR_SET_LEN(str,
len);
3591str_ensure_available_capa(
VALUE str,
long len)
3593 str_modify_keep_cr(str);
3595 const int termlen = TERM_LEN(str);
3596 long olen = RSTRING_LEN(str);
3598 if (RB_UNLIKELY(olen > LONG_MAX -
len)) {
3599 rb_raise(rb_eArgError,
"string sizes too big");
3602 long total = olen +
len;
3603 long capa = str_capacity(str, termlen);
3606 if (total >= LONG_MAX / 2) {
3609 while (total >
capa) {
3612 RESIZE_CAPA_TERM(str,
capa, termlen);
3617str_buf_cat4(
VALUE str,
const char *
ptr,
long len,
bool keep_cr)
3620 str_modify_keep_cr(str);
3625 if (
len == 0)
return 0;
3627 long total, olen,
off = -1;
3629 const int termlen = TERM_LEN(str);
3632 if (
ptr >= sptr &&
ptr <= sptr + olen) {
3636 long capa = str_capacity(str, termlen);
3638 if (olen > LONG_MAX -
len) {
3639 rb_raise(rb_eArgError,
"string sizes too big");
3643 if (total >= LONG_MAX / 2) {
3646 while (total >
capa) {
3649 RESIZE_CAPA_TERM(str,
capa, termlen);
3650 sptr = RSTRING_PTR(str);
3655 memcpy(sptr + olen,
ptr,
len);
3656 STR_SET_LEN(str, total);
3657 TERM_FILL(sptr + total, termlen);
3662#define str_buf_cat(str, ptr, len) str_buf_cat4((str), (ptr), len, false)
3663#define str_buf_cat2(str, ptr) str_buf_cat4((str), (ptr), rb_strlen_lit(ptr), false)
3668 if (
len == 0)
return str;
3670 rb_raise(rb_eArgError,
"negative string size (or size too big)");
3672 return str_buf_cat(str,
ptr,
len);
3683rb_str_buf_cat_byte(
VALUE str,
unsigned char byte)
3688 if (UNLIKELY(!str_independent(str))) {
3689 str_make_independent(str);
3692 long string_length = -1;
3693 const int null_terminator_length = 1;
3698 if (UNLIKELY(string_length > LONG_MAX - 1)) {
3699 rb_raise(rb_eArgError,
"string sizes too big");
3702 long string_capacity = str_capacity(str, null_terminator_length);
3708 if (LIKELY(string_capacity >= string_length + 1)) {
3710 sptr[string_length] = byte;
3711 STR_SET_LEN(str, string_length + 1);
3712 TERM_FILL(sptr + string_length + 1, null_terminator_length);
3716 str_buf_cat(str, (
char *)&
byte, 1);
3732 rb_enc_associate_index(str, ENCINDEX_ASCII_8BIT);
3743rb_enc_cr_str_buf_cat(
VALUE str,
const char *
ptr,
long len,
3744 int ptr_encindex,
int ptr_cr,
int *ptr_cr_ret)
3753 if (str_encindex == ptr_encindex) {
3755 ptr_cr = coderange_scan(
ptr,
len, rb_enc_from_index(ptr_encindex));
3759 str_enc = rb_enc_from_index(str_encindex);
3760 ptr_enc = rb_enc_from_index(ptr_encindex);
3761 if (!rb_enc_asciicompat(str_enc) || !rb_enc_asciicompat(ptr_enc)) {
3764 if (RSTRING_LEN(str) == 0) {
3767 rb_str_change_terminator_length(str, rb_enc_mbminlen(str_enc), rb_enc_mbminlen(ptr_enc));
3773 ptr_cr = coderange_scan(
ptr,
len, ptr_enc);
3777 str_cr = rb_enc_str_coderange(str);
3782 *ptr_cr_ret = ptr_cr;
3784 if (str_encindex != ptr_encindex &&
3787 str_enc = rb_enc_from_index(str_encindex);
3788 ptr_enc = rb_enc_from_index(ptr_encindex);
3793 res_encindex = str_encindex;
3798 res_encindex = str_encindex;
3802 res_encindex = ptr_encindex;
3807 res_encindex = str_encindex;
3814 res_encindex = str_encindex;
3820 rb_raise(rb_eArgError,
"negative string size (or size too big)");
3822 str_buf_cat(str,
ptr,
len);
3828 rb_enc_inspect_name(str_enc), rb_enc_inspect_name(ptr_enc));
3835 return rb_enc_cr_str_buf_cat(str,
ptr,
len,
3845 if (rb_enc_asciicompat(enc)) {
3846 return rb_enc_cr_str_buf_cat(str,
ptr, strlen(
ptr),
3852 unsigned int c = (
unsigned char)*
ptr;
3853 int len = rb_enc_codelen(c, enc);
3854 rb_enc_mbcput(c, buf, enc);
3855 rb_enc_cr_str_buf_cat(str, buf,
len,
3866 int str2_cr = rb_enc_str_coderange(str2);
3868 if (rb_str_enc_fastpath(str)) {
3872 str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
true);
3878 str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
true);
3889 rb_enc_cr_str_buf_cat(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
3905rb_str_concat_literals(
size_t num,
const VALUE *strary)
3909 unsigned long len = 1;
3914 for (i = 0; i < num; ++i) {
len += RSTRING_LEN(strary[i]); }
3916 str_enc_copy_direct(str, strary[0]);
3918 for (i = s; i < num; ++i) {
3919 const VALUE v = strary[i];
3923 if (encidx != ENCINDEX_US_ASCII) {
3925 rb_enc_set_index(str, encidx);
3938rb_str_concat_multi(
int argc,
VALUE *argv,
VALUE str)
3940 str_modifiable(str);
3945 else if (argc > 1) {
3948 rb_enc_copy(arg_str, str);
3949 for (i = 0; i < argc; i++) {
3984rb_str_append_as_bytes(
int argc,
VALUE *argv,
VALUE str)
3986 long needed_capacity = 0;
3990 for (
int index = 0; index < argc; index++) {
3991 VALUE obj = argv[index];
3999 needed_capacity += RSTRING_LEN(obj);
4004 "wrong argument type %"PRIsVALUE
" (expected String or Integer)",
4011 str_ensure_available_capa(str, needed_capacity);
4014 for (
int index = 0; index < argc; index++) {
4015 VALUE obj = argv[index];
4020 argv[index] = obj = rb_int_and(obj,
INT2FIX(0xff));
4021 char byte = (char)(
NUM2INT(obj) & 0xFF);
4035 rb_bug(
"append_as_bytes arguments should have been validated");
4039 STR_SET_LEN(str, RSTRING_LEN(str) + needed_capacity);
4040 TERM_FILL(sptr, TERM_LEN(str));
4045 for (
int index = 0; index < argc; index++) {
4046 VALUE obj = argv[index];
4063 rb_bug(
"append_as_bytes arguments should have been validated");
4142 if (rb_num_to_uint(str2, &code) == 0) {
4155 encidx = rb_ascii8bit_appendable_encoding_index(enc, code);
4158 rb_str_buf_cat_byte(str1, (
unsigned char)code);
4161 long pos = RSTRING_LEN(str1);
4166 switch (
len = rb_enc_codelen(code, enc)) {
4167 case ONIGERR_INVALID_CODE_POINT_VALUE:
4168 rb_raise(
rb_eRangeError,
"invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
4170 case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
4176 rb_enc_mbcput(code, buf, enc);
4177 if (rb_enc_precise_mbclen(buf, buf +
len + 1, enc) !=
len) {
4178 rb_raise(
rb_eRangeError,
"invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
4180 rb_str_resize(str1, pos+
len);
4181 memcpy(RSTRING_PTR(str1) + pos, buf,
len);
4194rb_ascii8bit_appendable_encoding_index(
rb_encoding *enc,
unsigned int code)
4196 int encidx = rb_enc_to_index(enc);
4198 if (encidx == ENCINDEX_ASCII_8BIT || encidx == ENCINDEX_US_ASCII) {
4203 if (encidx == ENCINDEX_US_ASCII && code > 127) {
4204 return ENCINDEX_ASCII_8BIT;
4226rb_str_prepend_multi(
int argc,
VALUE *argv,
VALUE str)
4228 str_modifiable(str);
4233 else if (argc > 1) {
4236 rb_enc_copy(arg_str, str);
4237 for (i = 0; i < argc; i++) {
4250 st_index_t precomputed_hash;
4251 memcpy(&precomputed_hash,
RSTRING_END(str) + TERM_LEN(str),
sizeof(precomputed_hash));
4253 RUBY_ASSERT(precomputed_hash == str_do_hash(str));
4254 return precomputed_hash;
4257 return str_do_hash(str);
4264 const char *ptr1, *ptr2;
4267 return (len1 != len2 ||
4269 memcmp(ptr1, ptr2, len1) != 0);
4281rb_str_hash_m(
VALUE str)
4287#define lesser(a,b) (((a)>(b))?(b):(a))
4295 if (RSTRING_LEN(str1) == 0)
return TRUE;
4296 if (RSTRING_LEN(str2) == 0)
return TRUE;
4299 if (idx1 == idx2)
return TRUE;
4300 rc1 = rb_enc_str_coderange(str1);
4301 rc2 = rb_enc_str_coderange(str2);
4304 if (rb_enc_asciicompat(rb_enc_from_index(idx2)))
4308 if (rb_enc_asciicompat(rb_enc_from_index(idx1)))
4318 const char *ptr1, *ptr2;
4321 if (str1 == str2)
return 0;
4324 if (ptr1 == ptr2 || (retval = memcmp(ptr1, ptr2, lesser(len1, len2))) == 0) {
4333 if (len1 > len2)
return 1;
4336 if (retval > 0)
return 1;
4370 if (str1 == str2)
return Qtrue;
4377 return rb_str_eql_internal(str1, str2);
4391 if (str1 == str2)
return Qtrue;
4393 return rb_str_eql_internal(str1, str2);
4431 return rb_invcmp(str1, str2);
4473 return str_casecmp(str1, s);
4481 const char *p1, *p1end, *p2, *p2end;
4483 enc = rb_enc_compatible(str1, str2);
4488 p1 = RSTRING_PTR(str1); p1end =
RSTRING_END(str1);
4489 p2 = RSTRING_PTR(str2); p2end =
RSTRING_END(str2);
4490 if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
4491 while (p1 < p1end && p2 < p2end) {
4493 unsigned int c1 =
TOLOWER(*p1 & 0xff);
4494 unsigned int c2 =
TOLOWER(*p2 & 0xff);
4496 return INT2FIX(c1 < c2 ? -1 : 1);
4503 while (p1 < p1end && p2 < p2end) {
4504 int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
4505 int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);
4507 if (0 <= c1 && 0 <= c2) {
4511 return INT2FIX(c1 < c2 ? -1 : 1);
4515 l1 = rb_enc_mbclen(p1, p1end, enc);
4516 l2 = rb_enc_mbclen(p2, p2end, enc);
4517 len = l1 < l2 ? l1 : l2;
4518 r = memcmp(p1, p2,
len);
4520 return INT2FIX(r < 0 ? -1 : 1);
4522 return INT2FIX(l1 < l2 ? -1 : 1);
4528 if (p1 == p1end && p2 == p2end)
return INT2FIX(0);
4529 if (p1 == p1end)
return INT2FIX(-1);
4562 return str_casecmp_p(str1, s);
4569 VALUE folded_str1, folded_str2;
4570 VALUE fold_opt = sym_fold;
4572 enc = rb_enc_compatible(str1, str2);
4577 if (is_ascii_string(str1) && is_ascii_string(str2)) {
4578 if (RSTRING_LEN(str1) != RSTRING_LEN(str2))
return Qfalse;
4579 const char *p1 = RSTRING_PTR(str1), *p1end =
RSTRING_END(str1);
4580 const char *p2 = RSTRING_PTR(str2);
4581 while (p1 < p1end) {
4582 if (*p1 != *p2 &&
TOLOWER((
unsigned char)*p1) !=
TOLOWER((
unsigned char)*p2)) {
4591 folded_str1 = rb_str_downcase(1, &fold_opt, str1);
4592 folded_str2 = rb_str_downcase(1, &fold_opt, str2);
4594 return rb_str_eql(folded_str1, folded_str2);
4598strseq_core(
const char *str_ptr,
const char *str_ptr_end,
long str_len,
4599 const char *sub_ptr,
long sub_len,
long offset,
rb_encoding *enc)
4601 const char *search_start = str_ptr;
4602 long pos, search_len = str_len - offset;
4606 pos =
rb_memsearch(sub_ptr, sub_len, search_start, search_len, enc);
4607 if (pos < 0)
return pos;
4609 if (t == search_start + pos)
break;
4610 search_len -= t - search_start;
4611 if (search_len <= 0)
return -1;
4612 offset += t - search_start;
4615 return pos + offset;
4619#define rb_str_index(str, sub, offset) rb_strseq_index(str, sub, offset, 0)
4620#define rb_str_byteindex(str, sub, offset) rb_strseq_index(str, sub, offset, 1)
4623rb_strseq_index(
VALUE str,
VALUE sub,
long offset,
int in_byte)
4625 const char *str_ptr, *str_ptr_end, *sub_ptr;
4626 long str_len, sub_len;
4629 enc = rb_enc_check(str, sub);
4630 if (is_broken_string(sub))
return -1;
4632 str_ptr = RSTRING_PTR(str);
4634 str_len = RSTRING_LEN(str);
4635 sub_ptr = RSTRING_PTR(sub);
4636 sub_len = RSTRING_LEN(sub);
4638 if (str_len < sub_len)
return -1;
4641 long str_len_char, sub_len_char;
4642 int single_byte = single_byte_optimizable(str);
4643 str_len_char = (in_byte || single_byte) ? str_len : str_strlen(str, enc);
4644 sub_len_char = in_byte ? sub_len : str_strlen(sub, enc);
4646 offset += str_len_char;
4647 if (offset < 0)
return -1;
4649 if (str_len_char - offset < sub_len_char)
return -1;
4650 if (!in_byte) offset = str_offset(str_ptr, str_ptr_end, offset, enc, single_byte);
4653 if (sub_len == 0)
return offset;
4656 return strseq_core(str_ptr, str_ptr_end, str_len, sub_ptr, sub_len, offset, enc);
4669rb_str_index_m(
int argc,
VALUE *argv,
VALUE str)
4676 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4677 long slen = str_strlen(str, enc);
4679 if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
4691 pos = str_offset(RSTRING_PTR(str),
RSTRING_END(str), pos,
4692 enc, single_byte_optimizable(str));
4702 pos = rb_str_index(str, sub, pos);
4716str_ensure_byte_pos(
VALUE str,
long pos)
4718 if (!single_byte_optimizable(str)) {
4719 const char *s = RSTRING_PTR(str);
4721 const char *p = s + pos;
4722 if (!at_char_boundary(s, p, e, rb_enc_get(str))) {
4724 "offset %ld does not land on character boundary", pos);
4797rb_str_byteindex_m(
int argc,
VALUE *argv,
VALUE str)
4803 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4804 long slen = RSTRING_LEN(str);
4806 if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
4817 str_ensure_byte_pos(str, pos);
4822 pos = RMATCH_BEG(match, 0);
4828 pos = rb_str_byteindex(str, sub, pos);
4829 if (pos >= 0)
return LONG2NUM(pos);
4837 const char *hit, *adjusted, *sbeg, *e, *t;
4839 long slen, searchlen;
4841 sbeg = RSTRING_PTR(str);
4842 slen = RSTRING_LEN(sub);
4843 if (slen == 0)
return s - sbeg;
4845 t = RSTRING_PTR(sub);
4847 searchlen = s - sbeg + 1;
4849 if (memcmp(s, t, slen) == 0) {
4854 hit = memrchr(sbeg, c, searchlen);
4857 if (hit != adjusted) {
4858 searchlen = adjusted - sbeg;
4861 if (memcmp(hit, t, slen) == 0)
4863 searchlen = adjusted - sbeg;
4864 }
while (searchlen > 0);
4874 const char *sbeg, *s;
4878 enc = rb_enc_check(str, sub);
4879 if (is_broken_string(sub))
return -1;
4880 singlebyte = single_byte_optimizable(str);
4881 len = singlebyte ? RSTRING_LEN(str) : str_strlen(str, enc);
4882 slen = str_strlen(sub, enc);
4885 if (
len < slen)
return -1;
4886 if (
len - pos < slen) pos =
len - slen;
4887 if (
len == 0)
return pos;
4889 sbeg = RSTRING_PTR(str);
4892 if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
4898 s = str_nth(sbeg,
RSTRING_END(str), pos, enc, singlebyte);
4899 return str_rindex(str, sub, s, enc);
4911rb_str_rindex_m(
int argc,
VALUE *argv,
VALUE str)
4916 long pos,
len = str_strlen(str, enc);
4918 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4920 if (pos < 0 && (pos +=
len) < 0) {
4926 if (pos >
len) pos =
len;
4934 pos = str_offset(RSTRING_PTR(str),
RSTRING_END(str), pos,
4935 enc, single_byte_optimizable(str));
4945 pos = rb_str_rindex(str, sub, pos);
4955rb_str_byterindex(
VALUE str,
VALUE sub,
long pos)
4958 const char *sbeg, *s;
4961 enc = rb_enc_check(str, sub);
4962 if (is_broken_string(sub))
return -1;
4963 len = RSTRING_LEN(str);
4964 slen = RSTRING_LEN(sub);
4967 if (
len < slen)
return -1;
4968 if (
len - pos < slen) pos =
len - slen;
4969 if (
len == 0)
return pos;
4971 sbeg = RSTRING_PTR(str);
4974 if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
4981 return str_rindex(str, sub, s, enc);
5071rb_str_byterindex_m(
int argc,
VALUE *argv,
VALUE str)
5075 long pos,
len = RSTRING_LEN(str);
5077 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
5079 if (pos < 0 && (pos +=
len) < 0) {
5085 if (pos >
len) pos =
len;
5091 str_ensure_byte_pos(str, pos);
5096 pos = RMATCH_BEG(match, 0);
5102 pos = rb_str_byterindex(str, sub, pos);
5103 if (pos >= 0)
return LONG2NUM(pos);
5145 switch (OBJ_BUILTIN_TYPE(y)) {
5197rb_str_match_m(
int argc,
VALUE *argv,
VALUE str)
5204 result =
rb_funcallv(get_pat(re), rb_intern(
"match"), argc, argv);
5235rb_str_match_m_p(
int argc,
VALUE *argv,
VALUE str)
5239 re = get_pat(argv[0]);
5240 return rb_reg_match_p(re, str, argc > 1 ?
NUM2LONG(argv[1]) : 0);
5249static enum neighbor_char
5255 if (rb_enc_mbminlen(enc) > 1) {
5257 int r = rb_enc_precise_mbclen(p, p +
len, enc), c;
5259 return NEIGHBOR_NOT_CHAR;
5261 c = rb_enc_mbc_to_codepoint(p, p +
len, enc) + 1;
5263 if (!l)
return NEIGHBOR_NOT_CHAR;
5264 if (l !=
len)
return NEIGHBOR_WRAPPED;
5265 rb_enc_mbcput(c, p, enc);
5266 r = rb_enc_precise_mbclen(p, p +
len, enc);
5268 return NEIGHBOR_NOT_CHAR;
5270 return NEIGHBOR_FOUND;
5273 for (i =
len-1; 0 <= i && (
unsigned char)p[i] == 0xff; i--)
5276 return NEIGHBOR_WRAPPED;
5277 ++((
unsigned char*)p)[i];
5278 l = rb_enc_precise_mbclen(p, p+
len, enc);
5282 return NEIGHBOR_FOUND;
5285 memset(p+l, 0xff,
len-l);
5291 for (len2 =
len-1; 0 < len2; len2--) {
5292 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5296 memset(p+len2+1, 0xff,
len-(len2+1));
5301static enum neighbor_char
5306 if (rb_enc_mbminlen(enc) > 1) {
5308 int r = rb_enc_precise_mbclen(p, p +
len, enc), c;
5310 return NEIGHBOR_NOT_CHAR;
5312 c = rb_enc_mbc_to_codepoint(p, p +
len, enc);
5313 if (!c)
return NEIGHBOR_NOT_CHAR;
5316 if (!l)
return NEIGHBOR_NOT_CHAR;
5317 if (l !=
len)
return NEIGHBOR_WRAPPED;
5318 rb_enc_mbcput(c, p, enc);
5319 r = rb_enc_precise_mbclen(p, p +
len, enc);
5321 return NEIGHBOR_NOT_CHAR;
5323 return NEIGHBOR_FOUND;
5326 for (i =
len-1; 0 <= i && (
unsigned char)p[i] == 0; i--)
5329 return NEIGHBOR_WRAPPED;
5330 --((
unsigned char*)p)[i];
5331 l = rb_enc_precise_mbclen(p, p+
len, enc);
5335 return NEIGHBOR_FOUND;
5338 memset(p+l, 0,
len-l);
5344 for (len2 =
len-1; 0 < len2; len2--) {
5345 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5349 memset(p+len2+1, 0,
len-(len2+1));
5363static enum neighbor_char
5364enc_succ_alnum_char(
char *p,
long len,
rb_encoding *enc,
char *carry)
5366 enum neighbor_char ret;
5370 char save[ONIGENC_CODE_TO_MBC_MAXLEN];
5374 const int max_gaps = 1;
5376 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5378 ctype = ONIGENC_CTYPE_DIGIT;
5380 ctype = ONIGENC_CTYPE_ALPHA;
5382 return NEIGHBOR_NOT_CHAR;
5385 for (
try = 0;
try <= max_gaps; ++
try) {
5386 ret = enc_succ_char(p,
len, enc);
5387 if (ret == NEIGHBOR_FOUND) {
5388 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5390 return NEIGHBOR_FOUND;
5397 ret = enc_pred_char(p,
len, enc);
5398 if (ret == NEIGHBOR_FOUND) {
5399 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5412 return NEIGHBOR_NOT_CHAR;
5415 if (ctype != ONIGENC_CTYPE_DIGIT) {
5417 return NEIGHBOR_WRAPPED;
5421 enc_succ_char(carry,
len, enc);
5422 return NEIGHBOR_WRAPPED;
5440 str =
rb_str_new(RSTRING_PTR(orig), RSTRING_LEN(orig));
5441 rb_enc_cr_str_copy_for_substr(str, orig);
5442 return str_succ(str);
5449 char *sbeg, *s, *e, *last_alnum = 0;
5450 int found_alnum = 0;
5452 char carry[ONIGENC_CODE_TO_MBC_MAXLEN] =
"\1";
5453 long carry_pos = 0, carry_len = 1;
5454 enum neighbor_char neighbor = NEIGHBOR_FOUND;
5456 slen = RSTRING_LEN(str);
5457 if (slen == 0)
return str;
5459 enc = STR_ENC_GET(str);
5460 sbeg = RSTRING_PTR(str);
5461 s = e = sbeg + slen;
5463 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5464 if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
5470 l = rb_enc_precise_mbclen(s, e, enc);
5471 if (!ONIGENC_MBCLEN_CHARFOUND_P(l))
continue;
5472 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5473 neighbor = enc_succ_alnum_char(s, l, enc, carry);
5475 case NEIGHBOR_NOT_CHAR:
5477 case NEIGHBOR_FOUND:
5479 case NEIGHBOR_WRAPPED:
5484 carry_pos = s - sbeg;
5489 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5490 enum neighbor_char neighbor;
5491 char tmp[ONIGENC_CODE_TO_MBC_MAXLEN];
5492 l = rb_enc_precise_mbclen(s, e, enc);
5493 if (!ONIGENC_MBCLEN_CHARFOUND_P(l))
continue;
5494 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5496 neighbor = enc_succ_char(tmp, l, enc);
5498 case NEIGHBOR_FOUND:
5502 case NEIGHBOR_WRAPPED:
5505 case NEIGHBOR_NOT_CHAR:
5508 if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
5510 enc_succ_char(s, l, enc);
5512 if (!rb_enc_asciicompat(enc)) {
5513 MEMCPY(carry, s,
char, l);
5516 carry_pos = s - sbeg;
5520 RESIZE_CAPA(str, slen + carry_len);
5521 sbeg = RSTRING_PTR(str);
5522 s = sbeg + carry_pos;
5523 memmove(s + carry_len, s, slen - carry_pos);
5524 memmove(s, carry, carry_len);
5526 STR_SET_LEN(str, slen);
5527 TERM_FILL(&sbeg[slen], rb_enc_mbminlen(enc));
5528 rb_enc_str_coderange(str);
5543rb_str_succ_bang(
VALUE str)
5551all_digits_p(
const char *s,
long len)
5579 VALUE end, exclusive;
5583 return rb_str_upto_each(beg, end,
RTEST(exclusive), str_upto_i,
Qnil);
5589 VALUE current, after_end;
5596 enc = rb_enc_check(beg, end);
5597 ascii = (is_ascii_string(beg) && is_ascii_string(end));
5599 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && ascii) {
5600 char c = RSTRING_PTR(beg)[0];
5601 char e = RSTRING_PTR(end)[0];
5603 if (c > e || (excl && c == e))
return beg;
5605 VALUE str = rb_enc_str_new(&c, 1, enc);
5607 if ((*each)(str, arg))
break;
5608 if (!excl && c == e)
break;
5610 if (excl && c == e)
break;
5615 if (ascii &&
ISDIGIT(RSTRING_PTR(beg)[0]) &&
ISDIGIT(RSTRING_PTR(end)[0]) &&
5616 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) &&
5617 all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) {
5622 b = rb_str_to_inum(beg, 10, FALSE);
5623 e = rb_str_to_inum(end, 10, FALSE);
5630 if (excl && bi == ei)
break;
5631 if ((*each)(
rb_enc_sprintf(usascii,
"%.*ld", width, bi), arg))
break;
5636 ID op = excl ?
'<' : idLE;
5637 VALUE args[2], fmt = rb_fstring_lit(
"%.*d");
5642 if ((*each)(
rb_str_format(numberof(args), args, fmt), arg))
break;
5650 if (n > 0 || (excl && n == 0))
return beg;
5658 if ((*each)(current, arg))
break;
5659 if (
NIL_P(next))
break;
5663 if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
5678 if (is_ascii_string(beg) &&
ISDIGIT(RSTRING_PTR(beg)[0]) &&
5679 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg))) {
5680 VALUE b, args[2], fmt = rb_fstring_lit(
"%.*d");
5682 b = rb_str_to_inum(beg, 10, FALSE);
5688 if ((*each)(
rb_enc_sprintf(usascii,
"%.*ld", width, bi), arg))
break;
5696 if ((*each)(
rb_str_format(numberof(args), args, fmt), arg))
break;
5704 if ((*each)(current, arg))
break;
5707 if (RSTRING_LEN(current) == 0)
5718 if (!
rb_equal(str, *argp))
return 0;
5732 if (rb_enc_asciicompat(STR_ENC_GET(beg)) &&
5733 rb_enc_asciicompat(STR_ENC_GET(end)) &&
5734 rb_enc_asciicompat(STR_ENC_GET(val))) {
5735 const char *bp = RSTRING_PTR(beg);
5736 const char *ep = RSTRING_PTR(end);
5737 const char *vp = RSTRING_PTR(val);
5738 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
5739 if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
5747 if (b <= v && v < e)
return Qtrue;
5748 return RBOOL(!
RTEST(exclusive) && v == e);
5755 all_digits_p(bp, RSTRING_LEN(beg)) &&
5756 all_digits_p(ep, RSTRING_LEN(end))) {
5761 rb_str_upto_each(beg, end,
RTEST(exclusive), include_range_i, (
VALUE)&val);
5763 return RBOOL(
NIL_P(val));
5786 return rb_str_subpat(str, indx,
INT2FIX(0));
5789 if (rb_str_index(str, indx, 0) != -1)
5795 long beg,
len = str_strlen(str, NULL);
5807 return str_substr(str, idx, 1, FALSE);
5824rb_str_aref_m(
int argc,
VALUE *argv,
VALUE str)
5828 return rb_str_subpat(str, argv[0], argv[1]);
5831 return rb_str_substr_two_fixnums(str, argv[0], argv[1], TRUE);
5835 return rb_str_aref(str, argv[0]);
5841 char *
ptr = RSTRING_PTR(str);
5842 long olen = RSTRING_LEN(str), nlen;
5844 str_modifiable(str);
5845 if (
len > olen)
len = olen;
5847 if (str_embed_capa(str) >= nlen + TERM_LEN(str)) {
5849 size_t old_capa =
RSTRING(str)->as.heap.aux.capa + TERM_LEN(str);
5850 int fl = (int)(
RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED|STR_NOFREE));
5853 memmove(
ptr, oldptr +
len, nlen);
5854 if (fl == STR_NOEMBED) {
5855 SIZED_FREE_N(oldptr, old_capa);
5859 if (!STR_SHARED_P(str)) {
5861 rb_enc_cr_str_exact_copy(
shared, str);
5866 STR_SET_LEN(str, nlen);
5868 if (!SHARABLE_MIDDLE_SUBSTRING) {
5869 TERM_FILL(
ptr + nlen, TERM_LEN(str));
5876rb_str_update_1(
VALUE str,
long beg,
long len,
VALUE val,
long vbeg,
long vlen)
5882 if (beg == 0 && vlen == 0) {
5887 str_modify_keep_cr(str);
5891 RESIZE_CAPA(str, slen + vlen -
len);
5892 sptr = RSTRING_PTR(str);
5896 cr = rb_enc_str_coderange(val);
5901 memmove(sptr + beg + vlen,
5903 slen - (beg +
len));
5905 if (vlen < beg &&
len < 0) {
5909 memmove(sptr + beg, RSTRING_PTR(val) + vbeg, vlen);
5912 STR_SET_LEN(str, slen);
5913 TERM_FILL(&sptr[slen], TERM_LEN(str));
5920 rb_str_update_1(str, beg,
len, val, 0, RSTRING_LEN(val));
5929 int singlebyte = single_byte_optimizable(str);
5935 enc = rb_enc_check(str, val);
5936 slen = str_strlen(str, enc);
5938 if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) {
5947 if (
len > slen - beg) {
5950 p = str_nth(RSTRING_PTR(str),
RSTRING_END(str), beg, enc, singlebyte);
5955 beg = p - RSTRING_PTR(str);
5957 rb_str_update_0(str, beg,
len, val);
5958 rb_enc_associate(str, enc);
5969 long start, end,
len;
5977 int num_regs = RMATCH_NREGS(match);
5978 if ((nth >= num_regs) || ((nth < 0) && (-nth >= num_regs))) {
5985 start = RMATCH_BEG(match, nth);
5989 end = RMATCH_END(match, nth);
5992 enc = rb_enc_check_str(str, val);
5993 rb_str_update_0(str, start,
len, val);
5994 rb_enc_associate(str, enc);
6002 switch (
TYPE(indx)) {
6004 rb_str_subpat_set(str, indx,
INT2FIX(0), val);
6008 beg = rb_str_index(str, indx, 0);
6047rb_str_aset_m(
int argc,
VALUE *argv,
VALUE str)
6051 rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
6059 return rb_str_aset(str, argv[0], argv[1]);
6111rb_str_slice_bang(
int argc,
VALUE *argv,
VALUE str)
6119 str_modify_keep_cr(str);
6124 int num_regs = RMATCH_NREGS(match);
6127 if ((nth += num_regs) <= 0)
return Qnil;
6129 else if (nth >= num_regs)
return Qnil;
6130 beg = RMATCH_BEG(match, nth);
6131 len = RMATCH_END(match, nth) - beg;
6134 else if (argc == 2) {
6143 beg = p - RSTRING_PTR(str);
6147 beg = rb_str_index(str, indx, 0);
6148 if (beg == -1)
return Qnil;
6149 len = RSTRING_LEN(indx);
6161 beg = p - RSTRING_PTR(str);
6170 beg = p - RSTRING_PTR(str);
6174 rb_enc_cr_str_copy_for_substr(result, str);
6182 char *sptr = RSTRING_PTR(str);
6183 long slen = RSTRING_LEN(str);
6184 if (beg +
len > slen)
6188 slen - (beg +
len));
6190 STR_SET_LEN(str, slen);
6191 TERM_FILL(&sptr[slen], TERM_LEN(str));
6202 switch (OBJ_BUILTIN_TYPE(pat)) {
6221get_pat_quoted(
VALUE pat,
int check)
6225 switch (OBJ_BUILTIN_TYPE(pat)) {
6239 if (check && is_broken_string(pat)) {
6246rb_pat_search0(
VALUE pat,
VALUE str,
long pos,
int set_backref_str,
VALUE *match)
6249 pos = rb_str_byteindex(str, pat, pos);
6250 if (set_backref_str) {
6252 str = rb_str_new_frozen_String(str);
6253 VALUE match_data = rb_backref_set_string(str, pos, RSTRING_LEN(pat));
6255 *match = match_data;
6265 return rb_reg_search0(pat, str, pos, 0, set_backref_str, match);
6270rb_pat_search(
VALUE pat,
VALUE str,
long pos,
int set_backref_str)
6272 return rb_pat_search0(pat, str, pos, set_backref_str, NULL);
6290rb_str_sub_bang(
int argc,
VALUE *argv,
VALUE str)
6305 hash = rb_check_hash_type(repl);
6312 pat = get_pat_quoted(argv[0], 1);
6314 str_modifiable(str);
6315 beg = rb_pat_search(pat, str, 0, 1);
6327 end0 = beg0 + RSTRING_LEN(pat);
6331 beg0 = RMATCH_BEG(match, 0);
6332 end0 = RMATCH_END(match, 0);
6336 if (iter || !
NIL_P(hash)) {
6337 p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
6343 repl = rb_hash_aref(hash,
rb_str_subseq(str, beg0, end0 - beg0));
6346 str_mod_check(str, p,
len);
6347 rb_check_frozen(str);
6350 repl = rb_reg_regsub_match(repl, str, match);
6353 enc = rb_enc_compatible(str, repl);
6356 p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
6360 rb_enc_inspect_name(str_enc),
6361 rb_enc_inspect_name(STR_ENC_GET(repl)));
6363 enc = STR_ENC_GET(repl);
6366 rb_enc_associate(str, enc);
6376 rlen = RSTRING_LEN(repl);
6377 len = RSTRING_LEN(str);
6379 RESIZE_CAPA(str,
len + rlen - plen);
6381 p = RSTRING_PTR(str);
6383 memmove(p + beg0 + rlen, p + beg0 + plen,
len - beg0 - plen);
6385 rp = RSTRING_PTR(repl);
6386 memmove(p + beg0, rp, rlen);
6388 STR_SET_LEN(str,
len);
6389 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
6412 rb_str_sub_bang(argc, argv, str);
6417str_gsub(
int argc,
VALUE *argv,
VALUE str,
int bang)
6420 long beg, beg0, end0;
6421 long offset, blen, slen,
len, last;
6422 enum {STR, ITER, FAST_MAP, MAP} mode = STR;
6424 int need_backref_str = -1;
6435 hash = rb_check_hash_type(repl);
6439 else if (rb_hash_default_unredefined(hash) && !
FL_TEST_RAW(hash, RHASH_PROC_DEFAULT)) {
6448 rb_error_arity(argc, 1, 2);
6451 pat = get_pat_quoted(argv[0], 1);
6452 beg = rb_pat_search0(pat, str, 0, need_backref_str, &match);
6455 if (bang)
return Qnil;
6458 if (bang) str_modify_keep_cr(str);
6461 blen = RSTRING_LEN(str) + 30;
6463 sp = RSTRING_PTR(str);
6464 slen = RSTRING_LEN(str);
6466 str_enc = STR_ENC_GET(str);
6467 rb_enc_associate(dest, str_enc);
6473 end0 = beg0 + RSTRING_LEN(pat);
6477 beg0 = RMATCH_BEG(match, 0);
6478 end0 = RMATCH_END(match, 0);
6487 struct RString fake_str = {RBASIC_INIT};
6489 if (mode == FAST_MAP) {
6498 val = rb_hash_aref(hash, key);
6501 str_mod_check(str, sp, slen);
6506 else if (need_backref_str) {
6507 val = rb_reg_regsub_match(repl, str, match);
6508 if (need_backref_str < 0) {
6509 need_backref_str = val != repl;
6516 len = beg0 - offset;
6530 if (RSTRING_LEN(str) <= end0)
break;
6531 len = rb_enc_fast_mbclen(RSTRING_PTR(str)+end0,
RSTRING_END(str), str_enc);
6533 offset = end0 +
len;
6535 cp = RSTRING_PTR(str) + offset;
6536 if (offset > RSTRING_LEN(str))
break;
6539 if (mode != FAST_MAP && mode != STR) {
6542 beg = rb_pat_search0(pat, str, offset, need_backref_str, &match);
6547 if (RSTRING_LEN(str) > offset) {
6550 rb_pat_search0(pat, str, last, 1, &match);
6552 str_shared_replace(str, dest);
6577rb_str_gsub_bang(
int argc,
VALUE *argv,
VALUE str)
6579 str_modifiable(str);
6580 return str_gsub(argc, argv, str, 1);
6630 return str_gsub(argc, argv, str, 0);
6650 str_modifiable(str);
6651 if (str == str2)
return str;
6655 return str_replace(str, str2);
6672rb_str_clear(
VALUE str)
6676 STR_SET_LEN(str, 0);
6677 RSTRING_PTR(str)[0] = 0;
6678 if (rb_enc_asciicompat(STR_ENC_GET(str)))
6694rb_str_chr(
VALUE str)
6712 pos += RSTRING_LEN(str);
6713 if (pos < 0 || RSTRING_LEN(str) <= pos)
6716 return INT2FIX((
unsigned char)RSTRING_PTR(str)[pos]);
6736 long len = RSTRING_LEN(str);
6737 char *
ptr, *head, *left = 0;
6741 if (pos < -
len ||
len <= pos)
6748 char byte = (char)(
NUM2INT(w) & 0xFF);
6750 if (!str_independent(str))
6751 str_make_independent(str);
6752 enc = STR_ENC_GET(str);
6753 head = RSTRING_PTR(str);
6755 if (!STR_EMBED_P(str)) {
6762 nlen = rb_enc_precise_mbclen(left, head+
len, enc);
6770 width = rb_enc_precise_mbclen(left, head+
len, enc);
6772 nlen = rb_enc_precise_mbclen(left, head+
len, enc);
6788str_bit_offset_out_of_range(
long byte_len, uint64_t bit_offset)
6791 return bit_offset / CHAR_BIT >= (uint64_t)byte_len;
6807str_bit_offset_from_index(
VALUE index)
6819 offset.long_value =
FIX2LONG(integer);
6820 if (offset.long_value < 0) {
6823 offset.value = (uint64_t)offset.long_value;
6824 offset.fits_long =
true;
6829 if (rb_int_negative_p(integer)) {
6832 if (rb_cmpint(rb_int_cmp(integer,
ULL2NUM(UINT64_MAX)), integer,
ULL2NUM(UINT64_MAX)) > 0) {
6833 rb_raise(rb_eArgError,
"bit index out of representable range");
6836 offset.value = (uint64_t)
NUM2ULL(integer);
6837 if (offset.value <= (uint64_t)LONG_MAX) {
6838 offset.long_value = (long)offset.value;
6839 offset.fits_long =
true;
6842 offset.long_value = 0;
6843 offset.fits_long =
false;
6849str_lsb_first(
int argc,
VALUE *argv,
VALUE *index)
6851 static ID keywords[1];
6852 VALUE opts, vlsb_first;
6860 if (vlsb_first ==
Qundef || vlsb_first ==
Qtrue) {
6863 if (vlsb_first ==
Qfalse) {
6866 rb_raise(rb_eArgError,
"lsb_first must be true or false");
6870static inline uint64_t
6871str_logical_to_physical_bit64(uint64_t logical,
bool lsb_first)
6873 return lsb_first ? logical : ((logical & ~(uint64_t)7) | (7 - (logical & 7)));
6877str_logical_to_physical_bit(
long logical,
bool lsb_first)
6879 return lsb_first ? logical : ((logical & ~7L) | (7 - (logical & 7L)));
6884 unsigned int bit_offset;
6888str_bit_location_from_offset(uint64_t logical, bool lsb_first)
6894 uint64_t physical = str_logical_to_physical_bit64(logical, lsb_first);
6896 location.byte_index = (long)(physical / CHAR_BIT);
6897 location.bit_offset = (
unsigned int)(physical % CHAR_BIT);
6902str_get_bit(
const char *ptr,
long bit_index)
6904 return (((
unsigned char)ptr[bit_index / CHAR_BIT]) >> (bit_index % CHAR_BIT)) & 1;
6910 return (((
unsigned char)ptr[location.byte_index]) >> location.bit_offset) & 1;
6917 bool lsb_first = str_lsb_first(argc, argv, &index);
6920 if (str_bit_offset_out_of_range(RSTRING_LEN(str), offset.value)) {
6924 if (offset.fits_long) {
6925 return str_get_bit(RSTRING_PTR(str), str_logical_to_physical_bit(offset.long_value, lsb_first));
6928 return str_get_bit_location(RSTRING_PTR(str), str_bit_location_from_offset(offset.value, lsb_first));
6940rb_str_bit_get(
int argc,
VALUE *argv,
VALUE str)
6942 int bit = str_bit_get(argc, argv, str);
6954rb_str_bit_set_p(
int argc,
VALUE *argv,
VALUE str)
6956 int bit = str_bit_get(argc, argv, str);
6957 return bit < 0 ?
Qnil : RBOOL(bit);
6960enum str_bit_mutation {
6967str_mutate_bit(
int argc,
VALUE *argv,
VALUE str,
enum str_bit_mutation mutation)
6970 bool lsb_first = str_lsb_first(argc, argv, &index);
6977 if (str_bit_offset_out_of_range(RSTRING_LEN(str), offset.value)) {
6982 ptr = (
unsigned char *)RSTRING_PTR(str);
6983 if (offset.fits_long) {
6984 bit_index = str_logical_to_physical_bit(offset.long_value, lsb_first);
6985 mask = (
unsigned char)(1u << (bit_index % CHAR_BIT));
6986 location.byte_index = bit_index / CHAR_BIT;
6989 location = str_bit_location_from_offset(offset.value, lsb_first);
6990 mask = (
unsigned char)(1u << location.bit_offset);
6995 ptr[location.byte_index] |= mask;
6998 ptr[location.byte_index] &= (
unsigned char)~mask;
7001 ptr[location.byte_index] ^= mask;
7016rb_str_bit_set(
int argc,
VALUE *argv,
VALUE str)
7018 return str_mutate_bit(argc, argv, str, STR_BIT_SET);
7029rb_str_bit_clear(
int argc,
VALUE *argv,
VALUE str)
7031 return str_mutate_bit(argc, argv, str, STR_BIT_CLEAR);
7042rb_str_bit_flip(
int argc,
VALUE *argv,
VALUE str)
7044 return str_mutate_bit(argc, argv, str, STR_BIT_FLIP);
7048str_count_bits(
const unsigned char *ptr,
long len)
7052 long unrolled_end =
len & ~31L;
7053 long aligned_end =
len & ~7L;
7056 for (;
off < unrolled_end;
off += 32) {
7057 uint64_t w0, w1, w2, w3;
7058 memcpy(&w0, ptr +
off, 8);
7059 memcpy(&w1, ptr +
off + 8, 8);
7060 memcpy(&w2, ptr +
off + 16, 8);
7061 memcpy(&w3, ptr +
off + 24, 8);
7062 count += rb_popcount64(w0);
7063 count += rb_popcount64(w1);
7064 count += rb_popcount64(w2);
7065 count += rb_popcount64(w3);
7069 for (;
off < aligned_end;
off += 8) {
7071 memcpy(&word, ptr +
off, 8);
7072 count += rb_popcount64(word);
7079 for (;
off <
len;
off++, shift += CHAR_BIT) {
7080 word |= (uint64_t)ptr[
off] << shift;
7082 count += rb_popcount64(word);
7096rb_str_bit_count(
VALUE str)
7098 return ULL2NUM(str_count_bits((
const unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)));
7102str_check_bitwise_length(
VALUE str,
VALUE other)
7104 if (RSTRING_LEN(str) != RSTRING_LEN(other)) {
7105 rb_raise(rb_eArgError,
"operands must have the same length (%ld vs %ld)",
7106 RSTRING_LEN(str), RSTRING_LEN(other));
7111str_bitwise_result(
VALUE str)
7113 long len = RSTRING_LEN(str);
7115 rb_str_resize(result,
len);
7116 rb_enc_associate(result, rb_ascii8bit_encoding());
7121#define STR_DEFINE_UNARY_BITWISE_KERNEL(name, expr_word, expr_byte) \
7123 name(unsigned char *dst, const unsigned char *src, long len) \
7126 long unrolled_end = len & ~31L; \
7127 long aligned_end = len & ~7L; \
7128 for (; off < unrolled_end; off += 32) { \
7129 uint64_t s0, s1, s2, s3; \
7130 memcpy(&s0, src + off, 8); \
7131 memcpy(&s1, src + off + 8, 8); \
7132 memcpy(&s2, src + off + 16, 8); \
7133 memcpy(&s3, src + off + 24, 8); \
7134 s0 = (expr_word(s0)); \
7135 s1 = (expr_word(s1)); \
7136 s2 = (expr_word(s2)); \
7137 s3 = (expr_word(s3)); \
7138 memcpy(dst + off, &s0, 8); \
7139 memcpy(dst + off + 8, &s1, 8); \
7140 memcpy(dst + off + 16, &s2, 8); \
7141 memcpy(dst + off + 24, &s3, 8); \
7143 for (; off < aligned_end; off += 8) { \
7145 memcpy(&word, src + off, 8); \
7146 word = (expr_word(word)); \
7147 memcpy(dst + off, &word, 8); \
7149 for (; off < len; off++) dst[off] = (expr_byte(src[off])); \
7152#define STR_DEFINE_BINARY_BITWISE_KERNEL(name, expr_word, expr_byte) \
7154 name(unsigned char *dst, const unsigned char *lhs, \
7155 const unsigned char *rhs, long len) \
7158 long unrolled_end = len & ~31L; \
7159 long aligned_end = len & ~7L; \
7160 for (; off < unrolled_end; off += 32) { \
7161 uint64_t l0, l1, l2, l3, r0, r1, r2, r3; \
7162 memcpy(&l0, lhs + off, 8); memcpy(&r0, rhs + off, 8); \
7163 memcpy(&l1, lhs + off + 8, 8); memcpy(&r1, rhs + off + 8, 8); \
7164 memcpy(&l2, lhs + off + 16, 8); memcpy(&r2, rhs + off + 16, 8); \
7165 memcpy(&l3, lhs + off + 24, 8); memcpy(&r3, rhs + off + 24, 8); \
7166 l0 = expr_word(l0, r0); \
7167 l1 = expr_word(l1, r1); \
7168 l2 = expr_word(l2, r2); \
7169 l3 = expr_word(l3, r3); \
7170 memcpy(dst + off, &l0, 8); \
7171 memcpy(dst + off + 8, &l1, 8); \
7172 memcpy(dst + off + 16, &l2, 8); \
7173 memcpy(dst + off + 24, &l3, 8); \
7175 for (; off < aligned_end; off += 8) { \
7176 uint64_t lhs_word, rhs_word; \
7177 memcpy(&lhs_word, lhs + off, 8); \
7178 memcpy(&rhs_word, rhs + off, 8); \
7179 lhs_word = expr_word(lhs_word, rhs_word); \
7180 memcpy(dst + off, &lhs_word, 8); \
7182 for (; off < len; off++) dst[off] = expr_byte(lhs[off], rhs[off]); \
7185#define STR_BITWISE_NOT_WORD(x) (~(x))
7186#define STR_BITWISE_NOT_BYTE(x) ((unsigned char)~(x))
7187#define STR_BITWISE_AND_WORD(x, y) ((x) & (y))
7188#define STR_BITWISE_AND_BYTE(x, y) ((unsigned char)((x) & (y)))
7189#define STR_BITWISE_OR_WORD(x, y) ((x) | (y))
7190#define STR_BITWISE_OR_BYTE(x, y) ((unsigned char)((x) | (y)))
7191#define STR_BITWISE_XOR_WORD(x, y) ((x) ^ (y))
7192#define STR_BITWISE_XOR_BYTE(x, y) ((unsigned char)((x) ^ (y)))
7194STR_DEFINE_UNARY_BITWISE_KERNEL(str_bitwise_not, STR_BITWISE_NOT_WORD, STR_BITWISE_NOT_BYTE)
7195STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_and, STR_BITWISE_AND_WORD, STR_BITWISE_AND_BYTE)
7196STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_or, STR_BITWISE_OR_WORD, STR_BITWISE_OR_BYTE)
7197STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_xor, STR_BITWISE_XOR_WORD, STR_BITWISE_XOR_BYTE)
7207rb_str_bitwise_not(
VALUE str)
7209 long len = RSTRING_LEN(str);
7210 VALUE result = str_bitwise_result(str);
7211 str_bitwise_not((
unsigned char *)RSTRING_PTR(result),
7212 (
const unsigned char *)RSTRING_PTR(str),
len);
7224rb_str_bitwise_not_bang(
VALUE str)
7230 len = RSTRING_LEN(str);
7231 ptr = (
unsigned char *)RSTRING_PTR(str);
7232 str_bitwise_not(ptr, ptr,
len);
7236#define STR_DEFINE_BINARY_BITWISE_METHOD(name) \
7238 rb_str_bitwise_##name(VALUE str, VALUE other) \
7242 StringValue(other); \
7243 str_check_bitwise_length(str, other); \
7244 len = RSTRING_LEN(str); \
7245 result = str_bitwise_result(str); \
7246 str_bitwise_##name((unsigned char *)RSTRING_PTR(result), \
7247 (const unsigned char *)RSTRING_PTR(str), \
7248 (const unsigned char *)RSTRING_PTR(other), len); \
7252 rb_str_bitwise_##name##_bang(VALUE str, VALUE other) \
7255 unsigned char *ptr; \
7256 StringValue(other); \
7257 str_check_bitwise_length(str, other); \
7258 rb_str_modify(str); \
7259 len = RSTRING_LEN(str); \
7260 ptr = (unsigned char *)RSTRING_PTR(str); \
7261 str_bitwise_##name(ptr, ptr, \
7262 (const unsigned char *)RSTRING_PTR(other), len); \
7266STR_DEFINE_BINARY_BITWISE_METHOD(and)
7267STR_DEFINE_BINARY_BITWISE_METHOD(or)
7268STR_DEFINE_BINARY_BITWISE_METHOD(xor)
7271str_byte_substr(
VALUE str,
long beg,
long len,
int empty)
7273 long n = RSTRING_LEN(str);
7275 if (beg > n ||
len < 0)
return Qnil;
7278 if (beg < 0)
return Qnil;
7283 if (!empty)
return Qnil;
7287 VALUE str2 = str_subseq(str, beg,
len);
7289 str_enc_copy_direct(str2, str);
7291 if (RSTRING_LEN(str2) == 0) {
7292 if (!rb_enc_asciicompat(STR_ENC_GET(str)))
7326 long beg,
len = RSTRING_LEN(str);
7334 return str_byte_substr(str, beg,
len, TRUE);
7339 return str_byte_substr(str, idx, 1, FALSE);
7351rb_str_byteslice(
int argc,
VALUE *argv,
VALUE str)
7356 return str_byte_substr(str, beg,
len, TRUE);
7359 return str_byte_aref(str, argv[0]);
7363str_check_beg_len(
VALUE str,
long *beg,
long *
len)
7365 long end, slen = RSTRING_LEN(str);
7368 if ((slen < *beg) || ((*beg < 0) && (*beg + slen < 0))) {
7377 if (*
len > slen - *beg) {
7381 str_ensure_byte_pos(str, *beg);
7382 str_ensure_byte_pos(str, end);
7396rb_str_bytesplice(
int argc,
VALUE *argv,
VALUE str)
7398 long beg,
len, vbeg, vlen;
7403 if (!(argc == 2 || argc == 3 || argc == 5)) {
7404 rb_raise(rb_eArgError,
"wrong number of arguments (given %d, expected 2, 3, or 5)", argc);
7408 rb_raise(
rb_eTypeError,
"wrong argument type %s (expected Range)",
7409 rb_builtin_class_name(argv[0]));
7416 vlen = RSTRING_LEN(val);
7421 rb_raise(
rb_eTypeError,
"wrong argument type %s (expected Range)",
7422 rb_builtin_class_name(argv[2]));
7434 vlen = RSTRING_LEN(val);
7442 str_check_beg_len(str, &beg, &
len);
7443 str_check_beg_len(val, &vbeg, &vlen);
7444 str_modify_keep_cr(str);
7447 rb_enc_associate(str, rb_enc_check(str, val));
7450 rb_str_update_1(str, beg,
len, val, vbeg, vlen);
7472rb_str_reverse(
VALUE str)
7479 if (RSTRING_LEN(str) <= 1)
return str_duplicate(
rb_cString, str);
7480 enc = STR_ENC_GET(str);
7486 if (RSTRING_LEN(str) > 1) {
7487 if (single_byte_optimizable(str)) {
7494 int clen = rb_enc_fast_mbclen(s, e, enc);
7502 cr = rb_enc_asciicompat(enc) ?
7505 int clen = rb_enc_mbclen(s, e, enc);
7514 STR_SET_LEN(rev, RSTRING_LEN(str));
7515 str_enc_copy_direct(rev, str);
7537rb_str_reverse_bang(
VALUE str)
7539 if (RSTRING_LEN(str) > 1) {
7540 if (single_byte_optimizable(str)) {
7543 str_modify_keep_cr(str);
7544 s = RSTRING_PTR(str);
7553 str_shared_replace(str, rb_str_reverse(str));
7557 str_modify_keep_cr(str);
7586 i = rb_str_index(str, arg, 0);
7588 return RBOOL(i != -1);
7632 rb_raise(rb_eArgError,
"invalid radix %d", base);
7634 return rb_str_to_inum(str, base, FALSE);
7659rb_str_to_f(
VALUE str)
7676rb_str_to_s(
VALUE str)
7688 char s[RUBY_MAX_CHAR_LEN];
7689 int n = rb_enc_codelen(c, enc);
7691 rb_enc_mbcput(c, s, enc);
7696#define CHAR_ESC_LEN 13
7699rb_str_buf_cat_escaped_char(
VALUE result,
unsigned int c,
int unicode_p)
7701 char buf[CHAR_ESC_LEN + 1];
7709 snprintf(buf, CHAR_ESC_LEN,
"%c", c);
7711 else if (c < 0x10000) {
7712 snprintf(buf, CHAR_ESC_LEN,
"\\u%04X", c);
7715 snprintf(buf, CHAR_ESC_LEN,
"\\u{%X}", c);
7720 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", c);
7723 snprintf(buf, CHAR_ESC_LEN,
"\\x{%X}", c);
7726 l = (int)strlen(buf);
7732ruby_escaped_char(
int c)
7735 case '\0':
return "\\0";
7736 case '\n':
return "\\n";
7737 case '\r':
return "\\r";
7738 case '\t':
return "\\t";
7739 case '\f':
return "\\f";
7740 case '\013':
return "\\v";
7741 case '\010':
return "\\b";
7742 case '\007':
return "\\a";
7743 case '\033':
return "\\e";
7744 case '\x7f':
return "\\c?";
7750rb_str_escape(
VALUE str)
7754 const char *p = RSTRING_PTR(str);
7756 const char *prev = p;
7757 char buf[CHAR_ESC_LEN + 1];
7759 int unicode_p = rb_enc_unicode_p(enc);
7760 int asciicompat = rb_enc_asciicompat(enc);
7765 int n = rb_enc_precise_mbclen(p, pend, enc);
7767 if (p > prev) str_buf_cat(result, prev, p - prev);
7768 n = rb_enc_mbminlen(enc);
7770 n = (int)(pend - p);
7772 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", *p & 0377);
7773 str_buf_cat(result, buf, strlen(buf));
7779 c = rb_enc_mbc_to_codepoint(p, pend, enc);
7781 cc = ruby_escaped_char(c);
7783 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7784 str_buf_cat(result, cc, strlen(cc));
7787 else if (asciicompat && rb_enc_isascii(c, enc) &&
ISPRINT(c)) {
7790 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7791 rb_str_buf_cat_escaped_char(result, c, unicode_p);
7795 if (p > prev) str_buf_cat(result, prev, p - prev);
7805static const bool inspect_no_escape[256] = {
7806 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7807 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7808 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7809 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7810 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7811 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
7812 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7813 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
7829 const char *p, *pend, *prev;
7830 char buf[CHAR_ESC_LEN + 1];
7832 rb_encoding *resenc = rb_default_internal_encoding();
7833 int unicode_p = rb_enc_unicode_p(enc);
7834 int asciicompat = rb_enc_asciicompat(enc);
7835 int cr = rb_enc_str_coderange(str);
7837 if (resenc == NULL) resenc = rb_default_external_encoding();
7838 if (!rb_enc_asciicompat(resenc)) resenc = rb_usascii_encoding();
7839 rb_enc_associate(result, resenc);
7840 str_buf_cat2(result,
"\"");
7853 while (p < pend && inspect_no_escape[(
unsigned char)*p]) p++;
7854 if (p >= pend)
break;
7857 n = rb_enc_precise_mbclen(p, pend, enc);
7859 if (p > prev) str_buf_cat(result, prev, p - prev);
7860 n = rb_enc_mbminlen(enc);
7862 n = (int)(pend - p);
7864 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", *p & 0377);
7865 str_buf_cat(result, buf, strlen(buf));
7871 c = rb_enc_mbc_to_codepoint(p, pend, enc);
7873 if ((asciicompat || unicode_p) &&
7874 (c ==
'"'|| c ==
'\\' ||
7879 (cc ==
'$' || cc ==
'@' || cc ==
'{'))))) {
7880 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7881 str_buf_cat2(result,
"\\");
7882 if (asciicompat || enc == resenc) {
7888 case '\n': cc =
'n';
break;
7889 case '\r': cc =
'r';
break;
7890 case '\t': cc =
't';
break;
7891 case '\f': cc =
'f';
break;
7892 case '\013': cc =
'v';
break;
7893 case '\010': cc =
'b';
break;
7894 case '\007': cc =
'a';
break;
7895 case 033: cc =
'e';
break;
7896 default: cc = 0;
break;
7899 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7902 str_buf_cat(result, buf, 2);
7915 (asciicompat && rb_enc_isascii(c, enc) &&
ISPRINT(c))) {
7919 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7920 rb_str_buf_cat_escaped_char(result, c, unicode_p);
7925 if (p > prev) str_buf_cat(result, prev, p - prev);
7926 str_buf_cat2(result,
"\"");
7931#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
7944 int encidx = rb_enc_get_index(str);
7947 const char *p, *pend;
7950 int u8 = (encidx == rb_utf8_encindex());
7951 static const char nonascii_suffix[] =
".dup.force_encoding(\"%s\")";
7954 if (!rb_enc_asciicompat(enc)) {
7956 len += strlen(enc->name);
7959 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
7962 unsigned char c = *p++;
7965 case '"':
case '\\':
7966 case '\n':
case '\r':
7967 case '\t':
case '\f':
7968 case '\013':
case '\010':
case '\007':
case '\033':
7973 clen = IS_EVSTR(p, pend) ? 2 : 1;
7981 if (u8 && c > 0x7F) {
7982 int n = rb_enc_precise_mbclen(p-1, pend, enc);
7984 unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
7987 else if (cc <= 0xFFFFF)
8000 if (clen > LONG_MAX -
len) {
8007 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
8008 q = RSTRING_PTR(result); qend = q +
len + 1;
8012 unsigned char c = *p++;
8014 if (c ==
'"' || c ==
'\\') {
8018 else if (c ==
'#') {
8019 if (IS_EVSTR(p, pend)) *q++ =
'\\';
8022 else if (c ==
'\n') {
8026 else if (c ==
'\r') {
8030 else if (c ==
'\t') {
8034 else if (c ==
'\f') {
8038 else if (c ==
'\013') {
8042 else if (c ==
'\010') {
8046 else if (c ==
'\007') {
8050 else if (c ==
'\033') {
8060 int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
8062 int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
8065 snprintf(q, qend-q,
"u%04X", cc);
8067 snprintf(q, qend-q,
"u{%X}", cc);
8072 snprintf(q, qend-q,
"x%02X", c);
8078 if (!rb_enc_asciicompat(enc)) {
8079 snprintf(q, qend-q, nonascii_suffix, enc->name);
8080 encidx = rb_ascii8bit_encindex();
8083 rb_enc_associate_index(result, encidx);
8089unescape_ascii(
unsigned int c)
8113undump_after_backslash(
VALUE undumped,
const char **ss,
const char *s_end,
rb_encoding **penc,
bool *utf8,
bool *binary)
8115 const char *s = *ss;
8119 unsigned char buf[6];
8137 *buf = unescape_ascii(*s);
8149 if (enc_utf8 == NULL) enc_utf8 = rb_utf8_encoding();
8150 if (*penc != enc_utf8) {
8152 rb_enc_associate(undumped, enc_utf8);
8169 if (hexlen == 0 || hexlen > 6) {
8175 if (0xd800 <= c && c <= 0xdfff) {
8178 codelen = rb_enc_mbcput(c, (
char *)buf, *penc);
8188 if (0xd800 <= c && c <= 0xdfff) {
8191 codelen = rb_enc_mbcput(c, (
char *)buf, *penc);
8221static VALUE rb_str_is_ascii_only_p(
VALUE str);
8233str_undump(
VALUE str)
8235 const char *s = RSTRING_PTR(str);
8238 VALUE undumped = rb_enc_str_new(s, 0L, enc);
8240 bool binary =
false;
8244 if (rb_str_is_ascii_only_p(str) ==
Qfalse) {
8247 if (!str_null_check(str, &w)) {
8250 if (RSTRING_LEN(str) < 2)
goto invalid_format;
8251 if (*s !=
'"')
goto invalid_format;
8269 static const char force_encoding_suffix[] =
".force_encoding(\"";
8270 static const char dup_suffix[] =
".dup";
8271 const char *encname;
8276 size =
sizeof(dup_suffix) - 1;
8277 if (s_end - s > size && memcmp(s, dup_suffix, size) == 0) s += size;
8279 size =
sizeof(force_encoding_suffix) - 1;
8280 if (s_end - s <= size)
goto invalid_format;
8281 if (memcmp(s, force_encoding_suffix, size) != 0)
goto invalid_format;
8285 rb_raise(
rb_eRuntimeError,
"dumped string contained Unicode escape but used force_encoding");
8289 s = memchr(s,
'"', s_end-s);
8291 if (!s)
goto invalid_format;
8292 if (s_end - s != 2)
goto invalid_format;
8293 if (s[0] !=
'"' || s[1] !=
')')
goto invalid_format;
8295 encidx = rb_enc_find_index2(encname, (
long)size);
8299 rb_enc_associate_index(undumped, encidx);
8309 undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
8320 rb_raise(
rb_eRuntimeError,
"invalid dumped string; not wrapped with '\"' nor '\"...\".force_encoding(\"...\")' form");
8326 if (rb_enc_dummy_p(enc)) {
8333str_true_enc(
VALUE str)
8336 rb_str_check_dummy_enc(enc);
8340static OnigCaseFoldType
8341check_case_options(
int argc,
VALUE *argv, OnigCaseFoldType flags)
8346 rb_raise(rb_eArgError,
"too many options");
8347 if (argv[0]==sym_turkic) {
8348 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
8350 if (argv[1]==sym_lithuanian)
8351 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
8353 rb_raise(rb_eArgError,
"invalid second option");
8356 else if (argv[0]==sym_lithuanian) {
8357 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
8359 if (argv[1]==sym_turkic)
8360 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
8362 rb_raise(rb_eArgError,
"invalid second option");
8366 rb_raise(rb_eArgError,
"too many options");
8367 else if (argv[0]==sym_ascii)
8368 flags |= ONIGENC_CASE_ASCII_ONLY;
8369 else if (argv[0]==sym_fold) {
8370 if ((flags & (ONIGENC_CASE_UPCASE|ONIGENC_CASE_DOWNCASE)) == ONIGENC_CASE_DOWNCASE)
8371 flags ^= ONIGENC_CASE_FOLD|ONIGENC_CASE_DOWNCASE;
8373 rb_raise(rb_eArgError,
"option :fold only allowed for downcasing");
8376 rb_raise(rb_eArgError,
"invalid option");
8383 if ((flags & ONIGENC_CASE_ASCII_ONLY) && (enc==rb_utf8_encoding() ||
rb_enc_mbmaxlen(enc) == 1))
8385 return !(flags & ONIGENC_CASE_FOLD_TURKISH_AZERI) &&
8390#define CASE_MAPPING_ADDITIONAL_LENGTH 20
8391#ifndef CASEMAP_DEBUG
8392# define CASEMAP_DEBUG 0
8400 OnigUChar space[FLEX_ARY_LEN];
8404mapping_buffer_free(
void *p)
8408 while (current_buffer) {
8409 previous_buffer = current_buffer;
8410 current_buffer = current_buffer->next;
8411 ruby_xfree_sized(previous_buffer, offsetof(
mapping_buffer, space) + previous_buffer->capa);
8417 {0, mapping_buffer_free,},
8418 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED
8426 const OnigUChar *source_current, *source_end;
8427 int target_length = 0;
8428 VALUE buffer_anchor;
8431 size_t buffer_count = 0;
8432 int buffer_length_or_invalid;
8434 if (RSTRING_LEN(source) == 0)
return str_duplicate(
rb_cString, source);
8436 source_current = (OnigUChar*)RSTRING_PTR(source);
8441 while (source_current < source_end) {
8443 size_t capa = (size_t)(source_end-source_current)*++buffer_count + CASE_MAPPING_ADDITIONAL_LENGTH;
8444 if (CASEMAP_DEBUG) {
8445 fprintf(stderr,
"Buffer allocation, capa is %"PRIuSIZE
"\n",
capa);
8448 *pre_buffer = current_buffer;
8449 pre_buffer = ¤t_buffer->next;
8450 current_buffer->next = NULL;
8451 current_buffer->capa =
capa;
8452 buffer_length_or_invalid = enc->case_map(flags,
8453 &source_current, source_end,
8454 current_buffer->space,
8455 current_buffer->space+current_buffer->capa,
8457 if (buffer_length_or_invalid < 0) {
8458 current_buffer =
DATA_PTR(buffer_anchor);
8460 mapping_buffer_free(current_buffer);
8461 rb_raise(rb_eArgError,
"input string invalid");
8463 target_length += current_buffer->used = buffer_length_or_invalid;
8465 if (CASEMAP_DEBUG) {
8466 fprintf(stderr,
"Buffer count is %"PRIuSIZE
"\n", buffer_count);
8469 if (buffer_count==1) {
8470 target =
rb_str_new((
const char*)current_buffer->space, target_length);
8473 char *target_current;
8476 target_current = RSTRING_PTR(target);
8477 current_buffer =
DATA_PTR(buffer_anchor);
8478 while (current_buffer) {
8479 memcpy(target_current, current_buffer->space, current_buffer->used);
8480 target_current += current_buffer->used;
8481 current_buffer = current_buffer->next;
8484 current_buffer =
DATA_PTR(buffer_anchor);
8486 mapping_buffer_free(current_buffer);
8491 str_enc_copy_direct(target, source);
8500 const OnigUChar *source_current, *source_end;
8501 OnigUChar *target_current, *target_end;
8502 long old_length = RSTRING_LEN(source);
8503 int length_or_invalid;
8505 if (old_length == 0)
return Qnil;
8507 source_current = (OnigUChar*)RSTRING_PTR(source);
8509 if (source == target) {
8510 target_current = (OnigUChar*)source_current;
8511 target_end = (OnigUChar*)source_end;
8514 target_current = (OnigUChar*)RSTRING_PTR(target);
8518 length_or_invalid = onigenc_ascii_only_case_map(flags,
8519 &source_current, source_end,
8520 target_current, target_end, enc);
8521 if (length_or_invalid < 0)
8522 rb_raise(rb_eArgError,
"input string invalid");
8523 if (CASEMAP_DEBUG && length_or_invalid != old_length) {
8524 fprintf(stderr,
"problem with rb_str_ascii_casemap"
8525 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
8526 rb_raise(rb_eArgError,
"internal problem with rb_str_ascii_casemap"
8527 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
8530 str_enc_copy(target, source);
8536upcase_single(
VALUE str)
8538 char *s = RSTRING_PTR(str), *send =
RSTRING_END(str);
8539 bool modified =
false;
8542 unsigned int c = *(
unsigned char*)s;
8544 if (
'a' <= c && c <=
'z') {
8545 *s =
'A' + (c -
'a');
8566rb_str_upcase_bang(
int argc,
VALUE *argv,
VALUE str)
8569 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
8571 flags = check_case_options(argc, argv, flags);
8572 str_modify_keep_cr(str);
8573 enc = str_true_enc(str);
8574 if (case_option_single_p(flags, enc, str)) {
8575 if (upcase_single(str))
8576 flags |= ONIGENC_CASE_MODIFIED;
8578 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8579 rb_str_ascii_casemap(str, str, &flags, enc);
8581 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8583 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8596rb_str_upcase(
int argc,
VALUE *argv,
VALUE str)
8599 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
8602 flags = check_case_options(argc, argv, flags);
8603 enc = str_true_enc(str);
8604 if (case_option_single_p(flags, enc, str)) {
8605 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8606 str_enc_copy_direct(ret, str);
8609 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8611 rb_str_ascii_casemap(str, ret, &flags, enc);
8614 ret = rb_str_casemap(str, &flags, enc);
8621downcase_single(
VALUE str)
8623 char *s = RSTRING_PTR(str), *send =
RSTRING_END(str);
8624 bool modified =
false;
8627 unsigned int c = *(
unsigned char*)s;
8629 if (
'A' <= c && c <=
'Z') {
8630 *s =
'a' + (c -
'A');
8652rb_str_downcase_bang(
int argc,
VALUE *argv,
VALUE str)
8655 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8657 flags = check_case_options(argc, argv, flags);
8658 str_modify_keep_cr(str);
8659 enc = str_true_enc(str);
8660 if (case_option_single_p(flags, enc, str)) {
8661 if (downcase_single(str))
8662 flags |= ONIGENC_CASE_MODIFIED;
8664 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8665 rb_str_ascii_casemap(str, str, &flags, enc);
8667 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8669 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8683rb_str_downcase(
int argc,
VALUE *argv,
VALUE str)
8686 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8689 flags = check_case_options(argc, argv, flags);
8690 enc = str_true_enc(str);
8691 if (case_option_single_p(flags, enc, str)) {
8692 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8693 str_enc_copy_direct(ret, str);
8694 downcase_single(ret);
8696 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8698 rb_str_ascii_casemap(str, ret, &flags, enc);
8701 ret = rb_str_casemap(str, &flags, enc);
8708capitalize_single(
VALUE str)
8710 char *s = RSTRING_PTR(str), *send =
RSTRING_END(str);
8711 bool modified =
false;
8714 unsigned int c = (
unsigned char)*s;
8716 if (
'a' <= c && c <=
'z') {
8717 *s =
'A' + (c -
'a');
8723 unsigned int c = (
unsigned char)*s;
8725 if (
'A' <= c && c <=
'Z') {
8726 *s =
'a' + (c -
'A');
8748rb_str_capitalize_bang(
int argc,
VALUE *argv,
VALUE str)
8751 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
8753 flags = check_case_options(argc, argv, flags);
8754 str_modify_keep_cr(str);
8755 enc = str_true_enc(str);
8756 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
8757 if (case_option_single_p(flags, enc, str)) {
8758 if (capitalize_single(str))
8759 flags |= ONIGENC_CASE_MODIFIED;
8761 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8762 rb_str_ascii_casemap(str, str, &flags, enc);
8764 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8766 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8780rb_str_capitalize(
int argc,
VALUE *argv,
VALUE str)
8783 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
8786 flags = check_case_options(argc, argv, flags);
8787 enc = str_true_enc(str);
8788 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return str;
8789 if (case_option_single_p(flags, enc, str)) {
8790 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8791 str_enc_copy_direct(ret, str);
8792 capitalize_single(ret);
8794 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8796 rb_str_ascii_casemap(str, ret, &flags, enc);
8799 ret = rb_str_casemap(str, &flags, enc);
8818rb_str_swapcase_bang(
int argc,
VALUE *argv,
VALUE str)
8821 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
8823 flags = check_case_options(argc, argv, flags);
8824 str_modify_keep_cr(str);
8825 enc = str_true_enc(str);
8826 if (flags&ONIGENC_CASE_ASCII_ONLY)
8827 rb_str_ascii_casemap(str, str, &flags, enc);
8829 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8831 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8845rb_str_swapcase(
int argc,
VALUE *argv,
VALUE str)
8848 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
8851 flags = check_case_options(argc, argv, flags);
8852 enc = str_true_enc(str);
8853 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return str_duplicate(
rb_cString, str);
8854 if (flags&ONIGENC_CASE_ASCII_ONLY) {
8856 rb_str_ascii_casemap(str, ret, &flags, enc);
8859 ret = rb_str_casemap(str, &flags, enc);
8864typedef unsigned char *USTR;
8868 unsigned int now, max;
8869 const char *p, *pend;
8880 if (t->p == t->pend)
return -1;
8881 if (rb_enc_ascget(t->p, t->pend, &n, enc) ==
'\\' && t->p + n < t->pend) {
8884 t->now = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
8886 if (rb_enc_ascget(t->p, t->pend, &n, enc) ==
'-' && t->p + n < t->pend) {
8888 if (t->p < t->pend) {
8889 unsigned int c = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
8892 if (t->now < 0x80 && c < 0x80) {
8893 rb_raise(rb_eArgError,
8894 "invalid range \"%c-%c\" in string transliteration",
8898 rb_raise(rb_eArgError,
"invalid range in string transliteration");
8902 else if (t->now < c) {
8911 while (ONIGENC_CODE_TO_MBCLEN(enc, ++t->now) <= 0) {
8912 if (t->now == t->max) {
8917 if (t->now < t->max) {
8933 const unsigned int errc = -1;
8934 unsigned int trans[256];
8936 struct tr trsrc, trrepl;
8938 unsigned int c, c0, last = 0;
8939 int modify = 0, i, l;
8940 unsigned char *s, *send;
8942 int singlebyte = single_byte_optimizable(str);
8946#define CHECK_IF_ASCII(c) \
8947 (void)((cr == ENC_CODERANGE_7BIT && !rb_isascii(c)) ? \
8948 (cr = ENC_CODERANGE_VALID) : 0)
8952 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
8953 if (RSTRING_LEN(repl) == 0) {
8954 return rb_str_delete_bang(1, &src, str);
8958 e1 = rb_enc_check(str, src);
8959 e2 = rb_enc_check(str, repl);
8964 enc = rb_enc_check(src, repl);
8966 trsrc.p = RSTRING_PTR(src); trsrc.pend = trsrc.p + RSTRING_LEN(src);
8967 if (RSTRING_LEN(src) > 1 &&
8968 rb_enc_ascget(trsrc.p, trsrc.pend, &l, enc) ==
'^' &&
8969 trsrc.p + l < trsrc.pend) {
8973 trrepl.p = RSTRING_PTR(repl);
8974 trrepl.pend = trrepl.p + RSTRING_LEN(repl);
8975 trsrc.gen = trrepl.gen = 0;
8976 trsrc.now = trrepl.now = 0;
8977 trsrc.max = trrepl.max = 0;
8980 for (i=0; i<256; i++) {
8983 while ((c = trnext(&trsrc, enc)) != errc) {
8988 if (!hash) hash = rb_hash_new();
8992 while ((c = trnext(&trrepl, enc)) != errc)
8995 for (i=0; i<256; i++) {
8996 if (trans[i] != errc) {
9004 for (i=0; i<256; i++) {
9007 while ((c = trnext(&trsrc, enc)) != errc) {
9008 r = trnext(&trrepl, enc);
9009 if (r == errc) r = trrepl.now;
9012 if (rb_enc_codelen(r, enc) != 1) singlebyte = 0;
9015 if (!hash) hash = rb_hash_new();
9023 str_modify_keep_cr(str);
9024 s = (
unsigned char *)RSTRING_PTR(str); send = (
unsigned char *)
RSTRING_END(str);
9025 termlen = rb_enc_mbminlen(enc);
9028 long offset, max = RSTRING_LEN(str);
9029 unsigned int save = -1;
9030 unsigned char *buf =
ALLOC_N(
unsigned char, max + termlen), *t = buf;
9035 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
9037 SIZED_FREE_N(buf, max + termlen);
9038 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
9041 c0 = c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
9043 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9052 if (cflag) c = last;
9055 else if (cflag) c = errc;
9061 if (c != (
unsigned int)-1) {
9067 tlen = rb_enc_codelen(c, enc);
9073 if (enc != e1) may_modify = 1;
9075 if ((offset = t - buf) + tlen > max) {
9076 size_t MAYBE_UNUSED(old) = max + termlen;
9077 max = offset + tlen + (send - s);
9078 SIZED_REALLOC_N(buf,
unsigned char, max + termlen, old);
9081 rb_enc_mbcput(c, t, enc);
9082 if (may_modify && memcmp(s, t, tlen) != 0) {
9088 if (!STR_EMBED_P(str)) {
9089 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9091 TERM_FILL((
char *)t, termlen);
9092 RSTRING(str)->as.heap.ptr = (
char *)buf;
9093 STR_SET_LEN(str, t - buf);
9094 STR_SET_NOEMBED(str);
9095 RSTRING(str)->as.heap.aux.capa = max;
9099 c = (
unsigned char)*s;
9100 if (trans[c] != errc) {
9117 long offset, max = (long)((send - s) * 1.2);
9118 unsigned char *buf =
ALLOC_N(
unsigned char, max + termlen), *t = buf;
9123 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
9125 SIZED_FREE_N(buf, max + termlen);
9126 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
9129 c0 = c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
9131 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9139 if (cflag) c = last;
9142 else if (cflag) c = errc;
9146 c = cflag ? last : errc;
9149 tlen = rb_enc_codelen(c, enc);
9154 if (enc != e1) may_modify = 1;
9156 if ((offset = t - buf) + tlen > max) {
9157 size_t MAYBE_UNUSED(old) = max + termlen;
9158 max = offset + tlen + (long)((send - s) * 1.2);
9159 SIZED_REALLOC_N(buf,
unsigned char, max + termlen, old);
9163 rb_enc_mbcput(c, t, enc);
9164 if (may_modify && memcmp(s, t, tlen) != 0) {
9171 if (!STR_EMBED_P(str)) {
9172 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9174 TERM_FILL((
char *)t, termlen);
9175 RSTRING(str)->as.heap.ptr = (
char *)buf;
9176 STR_SET_LEN(str, t - buf);
9177 STR_SET_NOEMBED(str);
9178 RSTRING(str)->as.heap.aux.capa = max;
9184 rb_enc_associate(str, enc);
9194 size_t initial_capa;
9198tr_buffer_init(
struct tr_buffer *buffer,
size_t initial_capa)
9200 if (initial_capa < 32) {
9203 *buffer = (
struct tr_buffer){ .initial_capa = initial_capa };
9207tr_buffer_ensure_capa(
struct tr_buffer *buffer,
size_t extra_capa)
9209 size_t offset = buffer->ptr - buffer->buf;
9210 size_t required_capa = offset + extra_capa;
9211 if (UNLIKELY(buffer->capa < required_capa)) {
9212 size_t new_capa = buffer->capa ? buffer->capa : buffer->initial_capa;
9214 while (new_capa < required_capa) {
9215 new_capa = (size_t)(new_capa * 1.2);
9217 SIZED_REALLOC_N(buffer->buf,
unsigned char, new_capa, buffer->capa);
9218 buffer->ptr = buffer->buf + offset;
9219 buffer->capa = new_capa;
9224tr_buffer_append(
struct tr_buffer *buffer,
const unsigned char *ptr,
size_t len)
9227 tr_buffer_ensure_capa(buffer,
len);
9228 memcpy(buffer->ptr, ptr,
len);
9236 tr_buffer_append(buffer, (
unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
9242 tr_buffer_ensure_capa(buffer, 4);
9243 buffer->ptr += rb_enc_mbcput(codepoint, buffer->ptr, enc);
9250 SIZED_FREE_N(buffer->buf, buffer->capa);
9267tr_trans_pairs_coerce_i(st_data_t key, st_data_t value, st_data_t _args)
9270 struct tr_pair *pair = &args->pairs[args->index];
9278 if (RSTRING_LEN(search) != 1 && str_strlen(search, NULL) != 1) {
9279 rb_raise(rb_eArgError,
"keys must be of size 1");
9282 args->enc = rb_enc_check_multi_str(args->enc, &args->cr, search);
9283 args->enc = rb_enc_check_multi_str(args->enc, &args->cr, replace);
9285 pair->search = search;
9286 pair->replace = replace;
9290#define TR_TRANS_PAIRS_SIMD_MAX_NEEDLES 16
9293 const unsigned char *s;
9294 const unsigned char *send;
9297 unsigned char needles[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9299#ifdef HAVE_SIMD_NEON
9300 uint64_t matches_bitmap;
9302#ifdef HAVE_SIMD_SSE2
9307 VALUE trans_table[256];
9313 while (search->s < search->send) {
9314 VALUE repl = search->trans_table[*search->s];
9315 if (UNLIKELY(repl)) {
9325#ifdef HAVE_SIMD_SSE2
9329 size_t next_match_offset = ntz_int32(search->matches_bitmap);
9330 search->matches_bitmap >>= (next_match_offset + 1);
9331 search->s += next_match_offset;
9332 if (search->s > search->send) {
9333 search->s = search->send;
9345 if (search->matches_bitmap) {
9346 return tr_trans_pairs_next_match_sse2(search);
9349 if ((
size_t)(search->send - search->s) >=
sizeof(__m128i)) {
9351 __m128i masks[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9352 for (i = 0; i < search->needles_count; i++) {
9353 masks[i] = _mm_set1_epi8(search->needles[i]);
9357 const __m128i bytes = _mm_loadu_si128((__m128i
const *)search->s);
9359 __m128i matches[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9360 for (i = 0; i < search->needles_count; i++) {
9361 matches[i] = _mm_cmpeq_epi8(bytes, masks[i]);
9364 for (i = i; i < search->needles_count; i++) {
9365 matches[0] = _mm_or_si128(matches[0], matches[i]);
9368 const int bitmap = _mm_movemask_epi8(matches[0]);
9371 search->matches_bitmap = bitmap;
9372 return tr_trans_pairs_next_match_sse2(search);
9374 search->s +=
sizeof(__m128i);
9375 }
while ((
size_t)(search->send - search->s) >=
sizeof(__m128i));
9377 return tr_trans_pairs_search_basic(search);
9380#define tr_trans_pairs_search_impl tr_trans_pairs_search_sse2
9383#ifdef HAVE_SIMD_NEON
9387 size_t next_match_offset = ntz_int64(search->matches_bitmap) / 4;
9388 search->matches_bitmap >>= (next_match_offset + 1) * 4;
9389 search->s += next_match_offset;
9390 if (search->s > search->send) {
9391 search->s = search->send;
9400 if (search->needles_count) {
9404 if (search->matches_bitmap) {
9405 return tr_trans_pairs_next_match_neon(search);
9408 if ((
size_t)(search->send - search->s) >=
sizeof(uint8x16_t)) {
9410 uint8x16_t masks[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9411 for (i = 0; i < search->needles_count; i++) {
9412 masks[i] = vdupq_n_u8(search->needles[i]);
9416 const uint8x16_t bytes = vld1q_u8(search->s);
9418 uint8x16_t matches[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9419 for (i = 0; i < search->needles_count; i++) {
9420 matches[i] = vceqq_u8(bytes, masks[i]);
9423 for (i = i; i < search->needles_count; i++) {
9424 matches[0] = vorrq_u8(matches[0], matches[i]);
9427 const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(matches[0]), 4);
9428 const uint64_t bitmap = vget_lane_u64(vreinterpret_u64_u8(res), 0) & 0x8888888888888888ull;
9431 search->matches_bitmap = bitmap;
9432 return tr_trans_pairs_next_match_neon(search);
9434 search->s +=
sizeof(uint8x16_t);
9435 }
while ((
size_t)(search->send - search->s) >=
sizeof(uint8x16_t));
9438 return tr_trans_pairs_search_basic(search);
9441#define tr_trans_pairs_search_impl tr_trans_pairs_search_neon
9444#ifndef tr_trans_pairs_search_impl
9445#define tr_trans_pairs_search_impl tr_trans_pairs_search_basic
9455 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str) || pairs_count == 0)
return Qnil;
9460 int cr = rb_enc_str_coderange(str);
9473 const unsigned char *sstart = (
unsigned char *)RSTRING_PTR(str);
9474 long str_len = RSTRING_LEN(str);
9475 int termlen = rb_enc_mbminlen(e1);
9478 tr_buffer_init(&buffer, str_len);
9479 bool modify =
false;
9481 if (RB_LIKELY(rb_str_encindex_fastpath(rb_enc_to_index(e1)))) {
9484 .send = sstart + str_len,
9487 for (
size_t index = 0; index < pairs_count; index++) {
9488 struct tr_pair *pair = &pairs[index];
9490 char *ptr = RSTRING_PTR(pair->search);
9491 unsigned int codepoint = rb_enc_mbc_to_codepoint(ptr,
RSTRING_END(pair->search), e1);
9493 const unsigned char first_byte = (
unsigned char)*ptr;
9496 if (pairs_count <= TR_TRANS_PAIRS_SIMD_MAX_NEEDLES) {
9497 search.needles[index] = first_byte;
9498 search.needles_count++;
9502 if (rb_enc_codelen(codepoint, e1) == 1) {
9503 search.trans_table[first_byte] = pair->replace;
9506 search.trans_table[first_byte] =
Qundef;
9508 hash =
rb_obj_hide(rb_hash_new_capa(pairs_count));
9510 rb_hash_aset(hash,
UINT2NUM(codepoint), pair->replace);
9514 const unsigned char *checkpoint = search.s;
9516 while ((repl = tr_trans_pairs_search_impl(&search))) {
9519 if (UNLIKELY(repl ==
Qundef)) {
9520 unsigned int c = rb_enc_mbc_to_codepoint((
char *)search.s, (
char *)search.send, e1);
9521 clen = rb_enc_codelen(c, e1);
9522 repl = rb_hash_lookup2(hash,
UINT2NUM(c), 0);
9531 if (checkpoint < search.s) {
9532 tr_buffer_append(&buffer, checkpoint, search.s - checkpoint);
9534 tr_buffer_append_str(&buffer, repl);
9536 checkpoint = search.s;
9543 if (modify && checkpoint < search.s) {
9544 tr_buffer_append(&buffer, checkpoint, search.s - checkpoint);
9548 const unsigned char *s = sstart;
9549 const unsigned char *send = sstart + str_len;
9551 hash =
rb_obj_hide(rb_hash_new_capa(pairs_count));
9553 for (
size_t index = 0; index < pairs_count; index++) {
9554 struct tr_pair *pair = &pairs[index];
9556 unsigned int codepoint = rb_enc_mbc_to_codepoint(RSTRING_PTR(pair->search),
RSTRING_END(pair->search), e1);
9557 rb_hash_aset(hash,
UINT2NUM(codepoint), pair->replace);
9561 bool may_modify =
false;
9563 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
9565 tr_buffer_free(&buffer);
9566 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
9569 unsigned int c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
9570 unsigned int c0 = c;
9572 long tlen = enc == e1 ? clen : rb_enc_codelen(c, e1);
9575 if (
NIL_P(replacement)) {
9576 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9578 if (enc != e1) may_modify =
true;
9581 tlen = RSTRING_LEN(replacement);
9585 if (
NIL_P(replacement)) {
9586 tr_buffer_mbcput(&buffer, c, enc);
9589 tr_buffer_append_str(&buffer, replacement);
9592 if (may_modify && memcmp(s, buffer.ptr - tlen, tlen) != 0) {
9604 if (!STR_EMBED_P(str)) {
9605 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9607 tr_buffer_ensure_capa(&buffer, termlen);
9608 TERM_FILL((
char *)buffer.ptr, termlen);
9609 RSTRING(str)->as.heap.ptr = (
char *)buffer.buf;
9610 STR_SET_LEN(str, buffer.ptr - buffer.buf);
9611 STR_SET_NOEMBED(str);
9612 RSTRING(str)->as.heap.aux.capa = buffer.capa - termlen;
9619 rb_enc_associate(str, e1);
9639rb_str_tr_bang(
int argc,
VALUE *argv,
VALUE str)
9644 VALUE pairs = argv[0];
9645 return tr_trans_pairs(str, pairs);
9648 VALUE src = argv[0], repl = argv[1];
9649 return tr_trans(str, src, repl, 0);
9698 VALUE pairs = argv[0];
9699 return tr_trans_pairs(str, pairs);
9702 VALUE src = argv[0], repl = argv[1];
9703 tr_trans(str, src, repl, 0);
9707#define TR_TABLE_MAX (UCHAR_MAX+1)
9708#define TR_TABLE_SIZE (TR_TABLE_MAX+1)
9710tr_setup_table(
VALUE str,
char stable[TR_TABLE_SIZE],
int first,
9713 const unsigned int errc = -1;
9714 char buf[TR_TABLE_MAX];
9717 VALUE table = 0, ptable = 0;
9718 int i, l, cflag = 0;
9720 tr.p = RSTRING_PTR(str);
tr.pend =
tr.p + RSTRING_LEN(str);
9721 tr.gen =
tr.now =
tr.max = 0;
9723 if (RSTRING_LEN(str) > 1 && rb_enc_ascget(
tr.p,
tr.pend, &l, enc) ==
'^') {
9728 for (i=0; i<TR_TABLE_MAX; i++) {
9731 stable[TR_TABLE_MAX] = cflag;
9733 else if (stable[TR_TABLE_MAX] && !cflag) {
9734 stable[TR_TABLE_MAX] = 0;
9736 for (i=0; i<TR_TABLE_MAX; i++) {
9740 while ((c = trnext(&
tr, enc)) != errc) {
9741 if (c < TR_TABLE_MAX) {
9742 buf[(
unsigned char)c] = !cflag;
9747 if (!table && (first || *tablep || stable[TR_TABLE_MAX])) {
9750 table = ptable ? ptable : rb_hash_new();
9754 table = rb_hash_new();
9759 if (table && (!ptable || (cflag ^ !
NIL_P(rb_hash_aref(ptable, key))))) {
9760 rb_hash_aset(table, key,
Qtrue);
9764 for (i=0; i<TR_TABLE_MAX; i++) {
9765 stable[i] = stable[i] && buf[i];
9767 if (!table && !cflag) {
9774tr_find(
unsigned int c,
const char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
9776 if (c < TR_TABLE_MAX) {
9777 return table[c] != 0;
9783 if (!
NIL_P(rb_hash_lookup(del, v)) &&
9784 (!nodel ||
NIL_P(rb_hash_lookup(nodel, v)))) {
9788 else if (nodel && !
NIL_P(rb_hash_lookup(nodel, v))) {
9791 return table[TR_TABLE_MAX] ? TRUE : FALSE;
9806rb_str_delete_bang(
int argc,
VALUE *argv,
VALUE str)
9808 char squeez[TR_TABLE_SIZE];
9811 VALUE del = 0, nodel = 0;
9813 int i, ascompat, cr;
9815 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
9817 for (i=0; i<argc; i++) {
9821 enc = rb_enc_check(str, s);
9822 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
9825 str_modify_keep_cr(str);
9826 ascompat = rb_enc_asciicompat(enc);
9827 s = t = RSTRING_PTR(str);
9834 if (ascompat && (c = *(
unsigned char*)s) < 0x80) {
9845 c = rb_enc_codepoint_len(s, send, &clen, enc);
9847 if (tr_find(c, squeez, del, nodel)) {
9851 if (t != s) rb_enc_mbcput(c, t, enc);
9858 TERM_FILL(t, TERM_LEN(str));
9859 STR_SET_LEN(str, t - RSTRING_PTR(str));
9862 if (modify)
return str;
9876rb_str_delete(
int argc,
VALUE *argv,
VALUE str)
9879 rb_str_delete_bang(argc, argv, str);
9897rb_str_squeeze_bang(
int argc,
VALUE *argv,
VALUE str)
9899 char squeez[TR_TABLE_SIZE];
9901 VALUE del = 0, nodel = 0;
9902 unsigned char *s, *send, *t;
9904 int ascompat, singlebyte = single_byte_optimizable(str);
9908 enc = STR_ENC_GET(str);
9911 for (i=0; i<argc; i++) {
9915 enc = rb_enc_check(str, s);
9916 if (singlebyte && !single_byte_optimizable(s))
9918 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
9922 str_modify_keep_cr(str);
9923 s = t = (
unsigned char *)RSTRING_PTR(str);
9924 if (!s || RSTRING_LEN(str) == 0)
return Qnil;
9927 ascompat = rb_enc_asciicompat(enc);
9931 unsigned int c = *s++;
9932 if (c != save || (argc > 0 && !squeez[c])) {
9942 if (ascompat && (c = *s) < 0x80) {
9943 if (c != save || (argc > 0 && !squeez[c])) {
9949 c = rb_enc_codepoint_len((
char *)s, (
char *)send, &clen, enc);
9951 if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
9952 if (t != s) rb_enc_mbcput(c, t, enc);
9961 TERM_FILL((
char *)t, TERM_LEN(str));
9962 if ((
char *)t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
9963 STR_SET_LEN(str, (
char *)t - RSTRING_PTR(str));
9967 if (modify)
return str;
9981rb_str_squeeze(
int argc,
VALUE *argv,
VALUE str)
9984 rb_str_squeeze_bang(argc, argv, str);
10004 return tr_trans(str, src, repl, 1);
10032 tr_trans(str, src, repl, 1);
10045rb_str_count(
int argc,
VALUE *argv,
VALUE str)
10047 char table[TR_TABLE_SIZE];
10049 VALUE del = 0, nodel = 0, tstr;
10050 const char *s, *send;
10059 enc = rb_enc_check(str, tstr);
10062 if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
10063 (ptstr = RSTRING_PTR(tstr),
10064 ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (
const unsigned char *)ptstr, (
const unsigned char *)ptstr+1)) &&
10065 !is_broken_string(str)) {
10067 unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);
10069 s = RSTRING_PTR(str);
10070 if (!s || RSTRING_LEN(str) == 0)
return INT2FIX(0);
10073 if (*(
unsigned char*)s++ == c) n++;
10079 tr_setup_table(tstr, table, TRUE, &del, &nodel, enc);
10080 for (i=1; i<argc; i++) {
10083 enc = rb_enc_check(str, tstr);
10084 tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
10087 s = RSTRING_PTR(str);
10088 if (!s || RSTRING_LEN(str) == 0)
return INT2FIX(0);
10090 ascompat = rb_enc_asciicompat(enc);
10094 if (ascompat && (c = *(
unsigned char*)s) < 0x80) {
10102 c = rb_enc_codepoint_len(s, send, &clen, enc);
10103 if (tr_find(c, table, del, nodel)) {
10114rb_fs_check(
VALUE val)
10118 if (
NIL_P(val))
return 0;
10123static const char isspacetable[256] = {
10124 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
10125 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10126 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10128 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10129 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10130 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10131 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10132 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10133 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10134 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10135 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10136 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10139 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
10142#define ascii_isspace(c) isspacetable[(unsigned char)(c)]
10145split_string(
VALUE result,
VALUE str,
long beg,
long len,
long empty_count)
10147 if (empty_count >= 0 &&
len == 0) {
10148 return empty_count + 1;
10150 if (empty_count > 0) {
10155 }
while (--empty_count > 0);
10159 rb_yield(str_new_empty_String(str));
10160 }
while (--empty_count > 0);
10170 return empty_count;
10174 SPLIT_TYPE_AWK, SPLIT_TYPE_STRING, SPLIT_TYPE_REGEXP, SPLIT_TYPE_CHARS
10178literal_split_pattern(
VALUE spat, split_type_t default_type)
10186 return SPLIT_TYPE_CHARS;
10188 else if (rb_enc_asciicompat(enc)) {
10189 if (
len == 1 && ptr[0] ==
' ') {
10190 return SPLIT_TYPE_AWK;
10195 if (rb_enc_ascget(ptr, ptr +
len, &l, enc) ==
' ' &&
len == l) {
10196 return SPLIT_TYPE_AWK;
10199 return default_type;
10212rb_str_split_m(
int argc,
VALUE *argv,
VALUE str)
10217 split_type_t split_type;
10218 long beg, end, i = 0, empty_count = -1;
10223 if (
rb_scan_args(argc, argv,
"02", &spat, &limit) == 2) {
10225 if (lim <= 0) limit =
Qnil;
10226 else if (lim == 1) {
10227 if (RSTRING_LEN(str) == 0)
10238 if (
NIL_P(limit) && !lim) empty_count = 0;
10240 enc = STR_ENC_GET(str);
10241 split_type = SPLIT_TYPE_REGEXP;
10242 if (!
NIL_P(spat)) {
10243 spat = get_pat_quoted(spat, 0);
10245 else if (
NIL_P(spat = rb_fs)) {
10246 split_type = SPLIT_TYPE_AWK;
10248 else if (!(spat = rb_fs_check(spat))) {
10249 rb_raise(
rb_eTypeError,
"value of $; must be String or Regexp");
10254 if (split_type != SPLIT_TYPE_AWK) {
10259 split_type = literal_split_pattern(tmp, SPLIT_TYPE_REGEXP);
10260 if (split_type == SPLIT_TYPE_AWK) {
10262 split_type = SPLIT_TYPE_STRING;
10267 mustnot_broken(spat);
10268 split_type = literal_split_pattern(spat, SPLIT_TYPE_STRING);
10276#define SPLIT_STR(beg, len) ( \
10277 empty_count = split_string(result, str, beg, len, empty_count), \
10278 str_mod_check(str, str_start, str_len))
10281 const char *ptr = RSTRING_PTR(str);
10282 const char *
const str_start = ptr;
10283 const long str_len = RSTRING_LEN(str);
10284 const char *
const eptr = str_start + str_len;
10285 if (split_type == SPLIT_TYPE_AWK) {
10286 const char *bptr = ptr;
10292 if (is_ascii_string(str)) {
10293 while (ptr < eptr) {
10294 c = (
unsigned char)*ptr++;
10296 if (ascii_isspace(c)) {
10302 if (!
NIL_P(limit) && lim <= i)
break;
10305 else if (ascii_isspace(c)) {
10306 SPLIT_STR(beg, end-beg);
10309 if (!
NIL_P(limit)) ++i;
10317 while (ptr < eptr) {
10320 c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
10329 if (!
NIL_P(limit) && lim <= i)
break;
10333 SPLIT_STR(beg, end-beg);
10336 if (!
NIL_P(limit)) ++i;
10344 else if (split_type == SPLIT_TYPE_STRING) {
10345 const char *substr_start = ptr;
10346 const char *sptr = RSTRING_PTR(spat);
10347 long slen = RSTRING_LEN(spat);
10350 mustnot_broken(str);
10351 enc = rb_enc_check(str, spat);
10352 while (ptr < eptr &&
10353 (end =
rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
10356 if (t != ptr + end) {
10360 SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start);
10361 str_mod_check(spat, sptr, slen);
10363 substr_start = ptr;
10364 if (!
NIL_P(limit) && lim <= ++i)
break;
10366 beg = ptr - str_start;
10368 else if (split_type == SPLIT_TYPE_CHARS) {
10372 mustnot_broken(str);
10373 enc = rb_enc_get(str);
10374 while (ptr < eptr &&
10375 (n = rb_enc_precise_mbclen(ptr, eptr, enc)) > 0) {
10376 SPLIT_STR(ptr - str_start, n);
10378 if (!
NIL_P(limit) && lim <= ++i)
break;
10380 beg = ptr - str_start;
10384 long len = RSTRING_LEN(str);
10391 (match ? (rb_match_unbusy(match),
rb_backref_set(match)) : (void)0)) {
10394 end = RMATCH_BEG(match, 0);
10395 if (start == end && RMATCH_BEG(match, 0) == RMATCH_END(match, 0)) {
10400 else if (last_null == 1) {
10401 SPLIT_STR(beg, rb_enc_fast_mbclen(ptr+beg, eptr, enc));
10408 start += rb_enc_fast_mbclen(ptr+start,eptr,enc);
10414 SPLIT_STR(beg, end-beg);
10415 beg = start = RMATCH_END(match, 0);
10419 for (idx = 1; idx < RMATCH_NREGS(match); idx++) {
10420 if (RMATCH_BEG(match, idx) == -1)
continue;
10421 SPLIT_STR(RMATCH_BEG(match, idx), RMATCH_END(match, idx) - RMATCH_BEG(match, idx));
10423 if (!
NIL_P(limit) && lim <= ++i)
break;
10425 if (match) rb_match_unbusy(match);
10427 if (RSTRING_LEN(str) > 0 && (!
NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
10428 SPLIT_STR(beg, RSTRING_LEN(str)-beg);
10431 return result ? result : str;
10441 return rb_str_split_m(1, &sep, str);
10444#define WANTARRAY(m, size) (!rb_block_given_p() ? rb_ary_new_capa(size) : 0)
10459#define ENUM_ELEM(ary, e) enumerator_element(ary, e)
10462chomp_newline(
const char *p,
const char *e,
rb_encoding *enc)
10464 const char *prev = rb_enc_prev_char(p, e, e, enc);
10467 prev = rb_enc_prev_char(p, e, e, enc);
10468 if (prev && rb_enc_ascget(prev, e, NULL, enc) ==
'\r')
10480 RSTRING_LEN(rs) != 1 ||
10481 RSTRING_PTR(rs)[0] !=
'\n')) {
10487#define rb_rs get_rs()
10494 const char *pend, *subptr, *subend, *rsptr, *hit, *adjusted;
10500 if (!
NIL_P(opts)) {
10501 static ID keywords[1];
10502 if (!keywords[0]) {
10506 chomp = (!UNDEF_P(chomp) &&
RTEST(chomp));
10510 if (!ENUM_ELEM(ary, str)) {
10518 if (!RSTRING_LEN(str))
goto end;
10520 const char *
const ptr = subptr = RSTRING_PTR(str);
10521 const long len = RSTRING_LEN(str);
10524 rslen = RSTRING_LEN(rs);
10527 enc = rb_enc_get(str);
10529 enc = rb_enc_check(str, rs);
10534 const char *eol = NULL;
10536 while (subend < pend) {
10537 long chomp_rslen = 0;
10539 if (rb_enc_ascget(subend, pend, &n, enc) !=
'\r')
10541 rslen = n + rb_enc_mbclen(subend + n, pend, enc);
10543 if (eol == subend)
break;
10547 chomp_rslen = -rslen;
10551 if (!subptr) subptr = subend;
10555 }
while (subend < pend);
10556 if (!subptr)
break;
10557 if (rslen == 0) chomp_rslen = 0;
10559 subend - subptr + (chomp ? chomp_rslen : rslen));
10560 if (ENUM_ELEM(ary, line)) {
10561 str_mod_check(str, ptr,
len);
10563 subptr = eol = NULL;
10568 rsptr = RSTRING_PTR(rs);
10569 if (RSTRING_LEN(rs) == rb_enc_mbminlen(enc) &&
10578 rsptr = RSTRING_PTR(rs);
10579 rslen = RSTRING_LEN(rs);
10582 while (subptr < pend) {
10583 pos =
rb_memsearch(rsptr, rslen, subptr, pend - subptr, enc);
10584 if (pos < 0)
break;
10585 hit = subptr + pos;
10587 if (hit != adjusted) {
10591 subend = hit += rslen;
10594 subend = chomp_newline(subptr, subend, enc);
10601 if (ENUM_ELEM(ary, line)) {
10602 str_mod_check(str, ptr,
len);
10607 if (subptr != pend) {
10610 pend = chomp_newline(subptr, pend, enc);
10612 else if (pend - subptr >= rslen &&
10613 memcmp(pend - rslen, rsptr, rslen) == 0) {
10618 ENUM_ELEM(ary, line);
10639rb_str_each_line(
int argc,
VALUE *argv,
VALUE str)
10642 return rb_str_enumerate_lines(argc, argv, str, 0);
10697rb_str_lines(
int argc,
VALUE *argv,
VALUE str)
10699 VALUE ary = WANTARRAY(
"lines", 0);
10700 return rb_str_enumerate_lines(argc, argv, str, ary);
10706 return LONG2FIX(RSTRING_LEN(str));
10714 for (i=0; i<RSTRING_LEN(str); i++) {
10715 ENUM_ELEM(ary,
INT2FIX((
unsigned char)RSTRING_PTR(str)[i]));
10733rb_str_each_byte(
VALUE str)
10736 return rb_str_enumerate_bytes(str, 0);
10748rb_str_bytes(
VALUE str)
10750 VALUE ary = WANTARRAY(
"bytes", RSTRING_LEN(str));
10751 return rb_str_enumerate_bytes(str, ary);
10769 ptr = RSTRING_PTR(str);
10770 len = RSTRING_LEN(str);
10771 enc = rb_enc_get(str);
10774 for (i = 0; i <
len; i += n) {
10775 n = rb_enc_fast_mbclen(ptr + i, ptr +
len, enc);
10780 for (i = 0; i <
len; i += n) {
10781 n = rb_enc_mbclen(ptr + i, ptr +
len, enc);
10802rb_str_each_char(
VALUE str)
10805 return rb_str_enumerate_chars(str, 0);
10817rb_str_chars(
VALUE str)
10820 return rb_str_enumerate_chars(str, ary);
10824rb_str_enumerate_codepoints(
VALUE str,
VALUE ary)
10829 const char *ptr, *end;
10831 int enc_asciicompat;
10833 if (single_byte_optimizable(str))
10834 return rb_str_enumerate_bytes(str, ary);
10837 ptr = RSTRING_PTR(str);
10839 enc = STR_ENC_GET(str);
10840 enc_asciicompat = rb_enc_asciicompat(enc);
10842 while (ptr < end) {
10847 c = (enc_asciicompat &&
ISASCII(*ptr)) ?
10848 (
unsigned char)*ptr : rb_enc_codepoint_len(ptr, end, &n, enc);
10869rb_str_each_codepoint(
VALUE str)
10872 return rb_str_enumerate_codepoints(str, 0);
10884rb_str_codepoints(
VALUE str)
10887 return rb_str_enumerate_codepoints(str, ary);
10893 int encidx = rb_enc_to_index(enc);
10895 const OnigUChar source_ascii[] =
"\\X";
10896 const OnigUChar *source = source_ascii;
10897 size_t source_len =
sizeof(source_ascii) - 1;
10900#define CHARS_16BE(x) (OnigUChar)((x)>>8), (OnigUChar)(x)
10901#define CHARS_16LE(x) (OnigUChar)(x), (OnigUChar)((x)>>8)
10902#define CHARS_32BE(x) CHARS_16BE((x)>>16), CHARS_16BE(x)
10903#define CHARS_32LE(x) CHARS_16LE(x), CHARS_16LE((x)>>16)
10904#define CASE_UTF(e) \
10905 case ENCINDEX_UTF_##e: { \
10906 static const OnigUChar source_UTF_##e[] = {CHARS_##e('\\'), CHARS_##e('X')}; \
10907 source = source_UTF_##e; \
10908 source_len = sizeof(source_UTF_##e); \
10911 CASE_UTF(16BE); CASE_UTF(16LE); CASE_UTF(32BE); CASE_UTF(32LE);
10919 regex_t *reg_grapheme_cluster;
10921 int r = onig_new(®_grapheme_cluster, source, source + source_len,
10922 ONIG_OPTION_DEFAULT, enc, OnigDefaultSyntax, &einfo);
10924 UChar message[ONIG_MAX_ERROR_MESSAGE_LEN];
10925 onig_error_code_to_str(message, r, &einfo);
10926 rb_fatal(
"cannot compile grapheme cluster regexp: %s", (
char *)message);
10929 return reg_grapheme_cluster;
10935 int encidx = rb_enc_to_index(enc);
10936 static regex_t *reg_grapheme_cluster_utf8 = NULL;
10938 if (encidx == rb_utf8_encindex()) {
10939 if (!reg_grapheme_cluster_utf8) {
10940 reg_grapheme_cluster_utf8 = get_reg_grapheme_cluster(enc);
10943 return reg_grapheme_cluster_utf8;
10952 size_t grapheme_cluster_count = 0;
10954 const char *ptr, *end;
10956 if (!rb_enc_unicode_p(enc)) {
10960 bool cached_reg_grapheme_cluster =
true;
10961 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
10962 if (!reg_grapheme_cluster) {
10963 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
10964 cached_reg_grapheme_cluster =
false;
10967 ptr = RSTRING_PTR(str);
10970 while (ptr < end) {
10971 OnigPosition
len = onig_match(reg_grapheme_cluster,
10972 (
const OnigUChar *)ptr, (
const OnigUChar *)end,
10973 (
const OnigUChar *)ptr, NULL, 0);
10974 if (
len <= 0)
break;
10975 grapheme_cluster_count++;
10979 if (!cached_reg_grapheme_cluster) {
10980 onig_free(reg_grapheme_cluster);
10983 return SIZET2NUM(grapheme_cluster_count);
10987rb_str_enumerate_grapheme_clusters(
VALUE str,
VALUE ary)
10991 const char *ptr0, *ptr, *end;
10993 if (!rb_enc_unicode_p(enc)) {
10994 return rb_str_enumerate_chars(str, ary);
10999 bool cached_reg_grapheme_cluster =
true;
11000 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
11001 if (!reg_grapheme_cluster) {
11002 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
11003 cached_reg_grapheme_cluster =
false;
11006 ptr0 = ptr = RSTRING_PTR(str);
11009 while (ptr < end) {
11010 OnigPosition
len = onig_match(reg_grapheme_cluster,
11011 (
const OnigUChar *)ptr, (
const OnigUChar *)end,
11012 (
const OnigUChar *)ptr, NULL, 0);
11013 if (
len <= 0)
break;
11018 if (!cached_reg_grapheme_cluster) {
11019 onig_free(reg_grapheme_cluster);
11039rb_str_each_grapheme_cluster(
VALUE str)
11042 return rb_str_enumerate_grapheme_clusters(str, 0);
11054rb_str_grapheme_clusters(
VALUE str)
11057 return rb_str_enumerate_grapheme_clusters(str, ary);
11061chopped_length(
VALUE str)
11064 const char *p, *p2, *beg, *end;
11066 beg = RSTRING_PTR(str);
11067 end = beg + RSTRING_LEN(str);
11068 if (beg >= end)
return 0;
11069 p = rb_enc_prev_char(beg, end, end, enc);
11071 if (p > beg && rb_enc_ascget(p, end, 0, enc) ==
'\n') {
11072 p2 = rb_enc_prev_char(beg, p, end, enc);
11073 if (p2 && rb_enc_ascget(p2, end, 0, enc) ==
'\r') p = p2;
11091rb_str_chop_bang(
VALUE str)
11093 str_modify_keep_cr(str);
11094 if (RSTRING_LEN(str) > 0) {
11096 len = chopped_length(str);
11097 STR_SET_LEN(str,
len);
11098 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
11117rb_str_chop(
VALUE str)
11123smart_chomp(
VALUE str,
const char *e,
const char *p)
11126 if (rb_enc_mbminlen(enc) > 1) {
11131 pp = e - rb_enc_mbminlen(enc);
11134 if (rb_enc_ascget(pp, e, 0, enc) ==
'\r') {
11142 if (--e > p && *(e-1) ==
'\r') {
11159 const char *pp, *e, *rsptr;
11161 const char *
const p = RSTRING_PTR(str);
11162 long len = RSTRING_LEN(str);
11164 if (
len == 0)
return 0;
11167 return smart_chomp(str, e, p);
11170 enc = rb_enc_get(str);
11173 if (rb_enc_mbminlen(enc) > 1) {
11178 pp -= rb_enc_mbminlen(enc);
11181 if (rb_enc_ascget(pp, e, 0, enc) ==
'\r') {
11188 while (e > p && *(e-1) ==
'\n') {
11190 if (e > p && *(e-1) ==
'\r')
11196 if (rslen >
len)
return len;
11198 enc = rb_enc_get(rs);
11199 newline = rsptr[rslen-1];
11200 if (rslen == rb_enc_mbminlen(enc)) {
11202 if (newline ==
'\n')
11203 return smart_chomp(str, e, p);
11207 return smart_chomp(str, e, p);
11211 enc = rb_enc_check(str, rs);
11212 if (is_broken_string(rs)) {
11216 if (p[
len-1] == newline &&
11218 memcmp(rsptr, pp, rslen) == 0)) {
11219 if (at_char_boundary(p, pp, e, enc))
11220 return len - rslen;
11232chomp_rs(
int argc,
const VALUE *argv)
11236 VALUE rs = argv[0];
11248 long olen = RSTRING_LEN(str);
11249 long len = chompped_length(str, rs);
11250 if (
len >= olen)
return Qnil;
11251 str_modify_keep_cr(str);
11252 STR_SET_LEN(str,
len);
11253 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
11273rb_str_chomp_bang(
int argc,
VALUE *argv,
VALUE str)
11276 str_modifiable(str);
11277 if (RSTRING_LEN(str) == 0 && argc < 2)
return Qnil;
11278 rs = chomp_rs(argc, argv);
11280 return rb_str_chomp_string(str, rs);
11293rb_str_chomp(
int argc,
VALUE *argv,
VALUE str)
11295 VALUE rs = chomp_rs(argc, argv);
11301tr_setup_table_multi(
char table[TR_TABLE_SIZE],
VALUE *tablep,
VALUE *ctablep,
11302 VALUE str,
int num_selectors,
VALUE *selectors)
11306 for (i=0; i<num_selectors; i++) {
11307 VALUE selector = selectors[i];
11311 enc = rb_enc_check(str, selector);
11312 tr_setup_table(selector, table, i==0, tablep, ctablep, enc);
11319 const char *
const start = s;
11321 if (!s || s >= e)
return 0;
11324 if (single_byte_optimizable(str)) {
11325 while (s < e && (*s ==
'\0' || ascii_isspace(*s))) s++;
11330 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
11340lstrip_offset_table(
VALUE str,
const char *s,
const char *e,
rb_encoding *enc,
11341 char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
11343 const char *
const start = s;
11345 if (!s || s >= e)
return 0;
11350 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
11352 if (!tr_find(cc, table, del, nodel))
break;
11371rb_str_lstrip_bang(
int argc,
VALUE *argv,
VALUE str)
11375 long olen, loffset;
11377 str_modify_keep_cr(str);
11378 enc = STR_ENC_GET(str);
11381 char table[TR_TABLE_SIZE];
11382 VALUE del = 0, nodel = 0;
11384 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11385 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11388 loffset = lstrip_offset(str, start, start+olen, enc);
11392 long len = olen-loffset;
11393 memmove(start, start + loffset,
len);
11394 STR_SET_LEN(str,
len);
11395 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
11430rb_str_lstrip(
int argc,
VALUE *argv,
VALUE str)
11437 char table[TR_TABLE_SIZE];
11438 VALUE del = 0, nodel = 0;
11440 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11441 loffset = lstrip_offset_table(str, start, start+
len, STR_ENC_GET(str), table, del, nodel);
11444 loffset = lstrip_offset(str, start, start+
len, STR_ENC_GET(str));
11446 if (loffset <= 0)
return str_duplicate(
rb_cString, str);
11455 rb_str_check_dummy_enc(enc);
11459 if (!s || s >= e)
return 0;
11463 if (single_byte_optimizable(str)) {
11465 while (s < t && ((c = *(t-1)) ==
'\0' || ascii_isspace(c))) t--;
11470 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
11480rstrip_offset_table(
VALUE str,
const char *s,
const char *e,
rb_encoding *enc,
11481 char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
11483 const char *t, *tp;
11485 rb_str_check_dummy_enc(enc);
11489 if (!s || s >= e)
return 0;
11493 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
11495 if (!tr_find(c, table, del, nodel))
break;
11515rb_str_rstrip_bang(
int argc,
VALUE *argv,
VALUE str)
11519 long olen, roffset;
11521 str_modify_keep_cr(str);
11522 enc = STR_ENC_GET(str);
11525 char table[TR_TABLE_SIZE];
11526 VALUE del = 0, nodel = 0;
11528 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11529 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11532 roffset = rstrip_offset(str, start, start+olen, enc);
11535 long len = olen - roffset;
11537 STR_SET_LEN(str,
len);
11538 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
11572rb_str_rstrip(
int argc,
VALUE *argv,
VALUE str)
11576 long olen, roffset;
11578 enc = STR_ENC_GET(str);
11581 char table[TR_TABLE_SIZE];
11582 VALUE del = 0, nodel = 0;
11584 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11585 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11588 roffset = rstrip_offset(str, start, start+olen, enc);
11590 if (roffset <= 0)
return str_duplicate(
rb_cString, str);
11608rb_str_strip_bang(
int argc,
VALUE *argv,
VALUE str)
11611 long olen, loffset, roffset;
11614 str_modify_keep_cr(str);
11615 enc = STR_ENC_GET(str);
11619 char table[TR_TABLE_SIZE];
11620 VALUE del = 0, nodel = 0;
11622 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11623 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11624 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
11627 loffset = lstrip_offset(str, start, start+olen, enc);
11628 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
11631 if (loffset > 0 || roffset > 0) {
11632 long len = olen-roffset;
11635 memmove(start, start + loffset,
len);
11637 STR_SET_LEN(str,
len);
11638 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
11673rb_str_strip(
int argc,
VALUE *argv,
VALUE str)
11676 long olen, loffset, roffset;
11682 char table[TR_TABLE_SIZE];
11683 VALUE del = 0, nodel = 0;
11685 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11686 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11687 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
11690 loffset = lstrip_offset(str, start, start+olen, enc);
11691 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
11694 if (loffset <= 0 && roffset <= 0)
return str_duplicate(
rb_cString, str);
11699scan_once(
VALUE str,
VALUE pat,
long *start,
int set_backref_str)
11702 long end, pos = rb_pat_search(pat, str, *start, set_backref_str);
11706 end = pos + RSTRING_LEN(pat);
11710 pos = RMATCH_BEG(match, 0);
11711 end = RMATCH_END(match, 0);
11719 if (RSTRING_LEN(str) > end)
11720 *start = end + rb_enc_fast_mbclen(RSTRING_PTR(str) + end,
11729 if (
NIL_P(match) || RMATCH_NREGS(match) == 1) {
11734 int num_regs = RMATCH_NREGS(match);
11736 for (
int i = 1; i < num_regs; i++) {
11738 if (RMATCH_BEG(match, i) >= 0) {
11739 s =
rb_str_subseq(str, RMATCH_BEG(match, i), RMATCH_END(match, i) - RMATCH_BEG(match, i));
11767 long last = -1, prev = 0;
11768 const char *p = RSTRING_PTR(str);
11769 long len = RSTRING_LEN(str);
11771 pat = get_pat_quoted(pat, 1);
11772 mustnot_broken(str);
11776 while (!
NIL_P(result = scan_once(str, pat, &start, 0))) {
11781 if (last >= 0) rb_pat_search(pat, str, last, 1);
11786 while (!
NIL_P(result = scan_once(str, pat, &start, 1))) {
11790 str_mod_check(str, p,
len);
11792 if (last >= 0) rb_pat_search(pat, str, last, 1);
11844rb_str_hex(
VALUE str)
11846 return rb_str_to_inum(str, 16, FALSE);
11930rb_str_oct(
VALUE str)
11932 return rb_str_to_inum(str, -8, FALSE);
11935#ifndef HAVE_CRYPT_R
11940 rb_nativethread_lock_t lock;
11941} crypt_mutex = {PTHREAD_MUTEX_INITIALIZER};
12010# define CRYPT_END() ALLOCV_END(databuf)
12013 extern char *crypt(
const char *,
const char *);
12014# define CRYPT_END() rb_nativethread_lock_unlock(&crypt_mutex.lock)
12017 const char *s, *saltp, *res;
12019 char salt_8bit_clean[3];
12023 mustnot_wchar(str);
12024 mustnot_wchar(salt);
12026 saltp = RSTRING_PTR(salt);
12027 if (RSTRING_LEN(salt) < 2 || !saltp[0] || !saltp[1]) {
12028 rb_raise(rb_eArgError,
"salt too short (need >=2 bytes)");
12032 if (!
ISASCII((
unsigned char)saltp[0]) || !
ISASCII((
unsigned char)saltp[1])) {
12033 salt_8bit_clean[0] = saltp[0] & 0x7f;
12034 salt_8bit_clean[1] = saltp[1] & 0x7f;
12035 salt_8bit_clean[2] =
'\0';
12036 saltp = salt_8bit_clean;
12041# ifdef HAVE_STRUCT_CRYPT_DATA_INITIALIZED
12042 data->initialized = 0;
12044 res = crypt_r(s, saltp, data);
12047 res = crypt(s, saltp);
12062 size_t res_size = strlen(res);
12063 tmp_buf =
ALLOCA_N(
char, res_size);
12064 memcpy(tmp_buf, res, res_size);
12100 char *ptr, *p, *pend;
12103 unsigned long sum0 = 0;
12108 ptr = p = RSTRING_PTR(str);
12109 len = RSTRING_LEN(str);
12115 str_mod_check(str, ptr,
len);
12118 sum0 += (
unsigned char)*p;
12129 if (bits < (
int)
sizeof(
long)*CHAR_BIT) {
12130 sum0 &= (((
unsigned long)1)<<bits)-1;
12150rb_str_justify(
int argc,
VALUE *argv,
VALUE str,
char jflag)
12154 long width,
len, flen = 1, fclen = 1;
12157 const char *f =
" ";
12158 long n, size, llen, rlen, llen2 = 0, rlen2 = 0;
12160 int singlebyte = 1, cr;
12164 enc = STR_ENC_GET(str);
12168 enc = rb_enc_check(str, pad);
12169 f = RSTRING_PTR(pad);
12170 flen = RSTRING_LEN(pad);
12171 fclen = str_strlen(pad, enc);
12172 singlebyte = single_byte_optimizable(pad);
12173 if (flen == 0 || fclen == 0) {
12174 rb_raise(rb_eArgError,
"zero width padding");
12177 termlen = rb_enc_mbminlen(enc);
12178 len = str_strlen(str, enc);
12179 if (width < 0 || len >= width)
return str_duplicate(
rb_cString, str);
12181 llen = (jflag ==
'l') ? 0 : ((jflag ==
'r') ? n : n/2);
12185 llen2 = str_offset(f, f + flen, llen % fclen, enc, singlebyte);
12186 rlen2 = str_offset(f, f + flen, rlen % fclen, enc, singlebyte);
12188 size = RSTRING_LEN(str);
12189 if ((
len = llen / fclen + rlen / fclen) >= LONG_MAX / flen ||
12190 (
len *= flen) >= LONG_MAX - llen2 - rlen2 ||
12191 (
len += llen2 + rlen2) >= LONG_MAX - size) {
12192 rb_raise(rb_eArgError,
"argument too big");
12196 p = RSTRING_PTR(res);
12198 memset(p, *f, llen);
12202 while (llen >= fclen) {
12208 memcpy(p, f, llen2);
12212 memcpy(p, RSTRING_PTR(str), size);
12215 memset(p, *f, rlen);
12219 while (rlen >= fclen) {
12225 memcpy(p, f, rlen2);
12229 TERM_FILL(p, termlen);
12230 STR_SET_LEN(res, p-RSTRING_PTR(res));
12251rb_str_ljust(
int argc,
VALUE *argv,
VALUE str)
12253 return rb_str_justify(argc, argv, str,
'l');
12265rb_str_rjust(
int argc,
VALUE *argv,
VALUE str)
12267 return rb_str_justify(argc, argv, str,
'r');
12280rb_str_center(
int argc,
VALUE *argv,
VALUE str)
12282 return rb_str_justify(argc, argv, str,
'c');
12298 sep = get_pat_quoted(sep, 0);
12305 pos = RMATCH_BEG(match, 0);
12309 pos = rb_str_index(str, sep, 0);
12310 if (pos < 0)
goto failed;
12315 RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
12318 return rb_ary_new3(3, str_duplicate(
rb_cString, str), str_new_empty_String(str), str_new_empty_String(str));
12332 long pos = RSTRING_LEN(str);
12334 sep = get_pat_quoted(sep, 0);
12341 pos = RMATCH_BEG(match, 0);
12346 pos = rb_str_rindex(str, sep, pos);
12355 RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
12357 return rb_ary_new3(3, str_new_empty_String(str), str_new_empty_String(str), str_duplicate(
rb_cString, str));
12369rb_str_start_with(
int argc,
VALUE *argv,
VALUE str)
12373 for (i=0; i<argc; i++) {
12374 VALUE tmp = argv[i];
12376 if (rb_reg_start_with_p(tmp, str))
12380 const char *p, *s, *e;
12385 enc = rb_enc_check(str, tmp);
12386 if ((tlen = RSTRING_LEN(tmp)) == 0)
return Qtrue;
12387 if ((slen = RSTRING_LEN(str)) < tlen)
continue;
12388 p = RSTRING_PTR(str);
12391 if (!at_char_right_boundary(p, s, e, enc))
12393 if (memcmp(p, RSTRING_PTR(tmp), tlen) == 0)
12409rb_str_end_with(
int argc,
VALUE *argv,
VALUE str)
12413 for (i=0; i<argc; i++) {
12414 VALUE tmp = argv[i];
12415 const char *p, *s, *e;
12420 enc = rb_enc_check(str, tmp);
12421 if ((tlen = RSTRING_LEN(tmp)) == 0)
return Qtrue;
12422 if ((slen = RSTRING_LEN(str)) < tlen)
continue;
12423 p = RSTRING_PTR(str);
12426 if (!at_char_boundary(p, s, e, enc))
12428 if (memcmp(s, RSTRING_PTR(tmp), tlen) == 0)
12444deleted_prefix_length(
VALUE str,
VALUE prefix)
12446 const char *strptr, *prefixptr;
12447 long olen, prefixlen;
12452 if (!is_broken_string(prefix) ||
12453 !rb_enc_asciicompat(enc) ||
12454 !rb_enc_asciicompat(rb_enc_get(prefix))) {
12455 enc = rb_enc_check(str, prefix);
12459 prefixlen = RSTRING_LEN(prefix);
12460 if (prefixlen <= 0)
return 0;
12461 olen = RSTRING_LEN(str);
12462 if (olen < prefixlen)
return 0;
12463 strptr = RSTRING_PTR(str);
12464 prefixptr = RSTRING_PTR(prefix);
12465 if (memcmp(strptr, prefixptr, prefixlen) != 0)
return 0;
12466 if (is_broken_string(prefix)) {
12467 if (!is_broken_string(str)) {
12471 const char *strend = strptr + olen;
12472 const char *after_prefix = strptr + prefixlen;
12473 if (!at_char_right_boundary(strptr, after_prefix, strend, enc)) {
12494rb_str_delete_prefix_bang(
VALUE str,
VALUE prefix)
12497 str_modify_keep_cr(str);
12499 prefixlen = deleted_prefix_length(str, prefix);
12500 if (prefixlen <= 0)
return Qnil;
12514rb_str_delete_prefix(
VALUE str,
VALUE prefix)
12518 prefixlen = deleted_prefix_length(str, prefix);
12519 if (prefixlen <= 0)
return str_duplicate(
rb_cString, str);
12521 return rb_str_subseq(str, prefixlen, RSTRING_LEN(str) - prefixlen);
12534deleted_suffix_length(
VALUE str,
VALUE suffix)
12536 const char *strptr, *suffixptr;
12537 long olen, suffixlen;
12541 if (is_broken_string(suffix))
return 0;
12542 enc = rb_enc_check(str, suffix);
12545 suffixlen = RSTRING_LEN(suffix);
12546 if (suffixlen <= 0)
return 0;
12547 olen = RSTRING_LEN(str);
12548 if (olen < suffixlen)
return 0;
12549 strptr = RSTRING_PTR(str);
12550 suffixptr = RSTRING_PTR(suffix);
12551 const char *strend = strptr + olen;
12552 const char *before_suffix = strend - suffixlen;
12553 if (memcmp(before_suffix, suffixptr, suffixlen) != 0)
return 0;
12554 if (!at_char_boundary(strptr, before_suffix, strend, enc))
return 0;
12570rb_str_delete_suffix_bang(
VALUE str,
VALUE suffix)
12572 long olen, suffixlen,
len;
12573 str_modifiable(str);
12575 suffixlen = deleted_suffix_length(str, suffix);
12576 if (suffixlen <= 0)
return Qnil;
12578 olen = RSTRING_LEN(str);
12579 str_modify_keep_cr(str);
12580 len = olen - suffixlen;
12581 STR_SET_LEN(str,
len);
12582 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
12598rb_str_delete_suffix(
VALUE str,
VALUE suffix)
12602 suffixlen = deleted_suffix_length(str, suffix);
12603 if (suffixlen <= 0)
return str_duplicate(
rb_cString, str);
12605 return rb_str_subseq(str, 0, RSTRING_LEN(str) - suffixlen);
12612 rb_raise(
rb_eTypeError,
"value of %"PRIsVALUE
" must be String", rb_id2str(
id));
12618nil_setter_warning(
ID id)
12620 rb_warn_deprecated(
"non-nil '%"PRIsVALUE
"'", NULL, rb_id2str(
id));
12627 if (!
NIL_P(*var)) {
12628 nil_setter_warning(
id);
12635 val = rb_fs_check(val);
12638 "value of %"PRIsVALUE
" must be String or Regexp",
12642 nil_setter_warning(
id);
12659 str_modifiable(str);
12662 int idx = rb_enc_to_index(encoding);
12669 rb_enc_associate_index(str, idx);
12693 if (STR_EMBED_P(str)) {
12694 str2 = str_alloc_embed(
rb_cString, RSTRING_LEN(str) + TERM_LEN(str));
12699 str_replace_shared_without_enc(str2, str);
12701 if (rb_enc_asciicompat(STR_ENC_GET(str))) {
12724rb_str_valid_encoding_p(
VALUE str)
12726 int cr = rb_enc_str_coderange(str);
12733rb_str_is_ascii_only_p(
VALUE str)
12735 int cr = rb_enc_str_coderange(str);
12743 static const char ellipsis[] =
"...";
12744 const long ellipsislen =
sizeof(ellipsis) - 1;
12746 const long blen = RSTRING_LEN(str);
12747 const char *
const p = RSTRING_PTR(str), *e = p + blen;
12748 VALUE estr, ret = 0;
12751 if (
len * rb_enc_mbminlen(enc) >= blen ||
12755 else if (
len <= ellipsislen ||
12757 if (rb_enc_asciicompat(enc)) {
12759 rb_enc_associate(ret, enc);
12766 else if (ret =
rb_str_subseq(str, 0, e - p), rb_enc_asciicompat(enc)) {
12771 rb_enc_from_encoding(enc), 0,
Qnil);
12782 cr = rb_enc_str_coderange(str);
12784 rb_raise(rb_eArgError,
"replacement must be valid byte sequence '%+"PRIsVALUE
"'", str);
12790 rb_enc_inspect_name(enc), rb_enc_inspect_name(e));
12809 if (enc == STR_ENC_GET(str)) {
12814 return enc_str_scrub(enc, str, repl, cr);
12822 const char *rep, *p, *e, *p1, *sp;
12828 rb_raise(rb_eArgError,
"both of block and replacement given");
12835 if (!
NIL_P(repl)) {
12836 repl = str_compat_and_valid(repl, enc);
12839 if (rb_enc_dummy_p(enc)) {
12842 encidx = rb_enc_to_index(enc);
12844#define DEFAULT_REPLACE_CHAR(str) do { \
12845 RBIMPL_ATTR_NONSTRING() static const char replace[sizeof(str)-1] = str; \
12846 rep = replace; replen = (int)sizeof(replace); \
12849 slen = RSTRING_LEN(str);
12850 p = RSTRING_PTR(str);
12855 if (rb_enc_asciicompat(enc)) {
12861 else if (!
NIL_P(repl)) {
12862 rep = RSTRING_PTR(repl);
12863 replen = RSTRING_LEN(repl);
12866 else if (encidx == rb_utf8_encindex()) {
12867 DEFAULT_REPLACE_CHAR(
"\xEF\xBF\xBD");
12871 DEFAULT_REPLACE_CHAR(
"?");
12876 p = search_nonascii(p, e);
12881 int ret = rb_enc_precise_mbclen(p, e, enc);
12889 p = search_nonascii(p, e);
12906 if (e - p < clen) clen = e - p;
12913 for (; clen > 1; clen--) {
12914 ret = rb_enc_precise_mbclen(q, q + clen, enc);
12925 repl =
rb_yield(rb_enc_str_new(p, clen, enc));
12926 str_mod_check(str, sp, slen);
12927 repl = str_compat_and_valid(repl, enc);
12934 p = search_nonascii(p, e);
12960 repl =
rb_yield(rb_enc_str_new(p, e-p, enc));
12961 str_mod_check(str, sp, slen);
12962 repl = str_compat_and_valid(repl, enc);
12971 long mbminlen = rb_enc_mbminlen(enc);
12975 else if (!
NIL_P(repl)) {
12976 rep = RSTRING_PTR(repl);
12977 replen = RSTRING_LEN(repl);
12979 else if (encidx == ENCINDEX_UTF_16BE) {
12980 DEFAULT_REPLACE_CHAR(
"\xFF\xFD");
12982 else if (encidx == ENCINDEX_UTF_16LE) {
12983 DEFAULT_REPLACE_CHAR(
"\xFD\xFF");
12985 else if (encidx == ENCINDEX_UTF_32BE) {
12986 DEFAULT_REPLACE_CHAR(
"\x00\x00\xFF\xFD");
12988 else if (encidx == ENCINDEX_UTF_32LE) {
12989 DEFAULT_REPLACE_CHAR(
"\xFD\xFF\x00\x00");
12992 DEFAULT_REPLACE_CHAR(
"?");
12996 int ret = rb_enc_precise_mbclen(p, e, enc);
13009 if (e - p < clen) clen = e - p;
13010 if (clen <= mbminlen * 2) {
13015 for (; clen > mbminlen; clen-=mbminlen) {
13016 ret = rb_enc_precise_mbclen(q, q + clen, enc);
13026 repl =
rb_yield(rb_enc_str_new(p, clen, enc));
13027 str_mod_check(str, sp, slen);
13028 repl = str_compat_and_valid(repl, enc);
13053 repl =
rb_yield(rb_enc_str_new(p, e-p, enc));
13054 str_mod_check(str, sp, slen);
13055 repl = str_compat_and_valid(repl, enc);
13095str_scrub_bang(
int argc,
VALUE *argv,
VALUE str)
13103static ID id_normalize;
13104static ID id_normalized_p;
13105static VALUE mUnicodeNormalize;
13108unicode_normalize_common(
int argc,
VALUE *argv,
VALUE str,
ID id)
13110 static int UnicodeNormalizeRequired = 0;
13113 if (!UnicodeNormalizeRequired) {
13114 rb_require(
"unicode_normalize/normalize.rb");
13115 UnicodeNormalizeRequired = 1;
13119 return rb_funcallv(mUnicodeNormalize,
id, argc+1, argv2);
13130rb_str_unicode_normalize(
int argc,
VALUE *argv,
VALUE str)
13132 return unicode_normalize_common(argc, argv, str, id_normalize);
13146rb_str_unicode_normalize_bang(
int argc,
VALUE *argv,
VALUE str)
13148 return rb_str_replace(str, unicode_normalize_common(argc, argv, str, id_normalize));
13175rb_str_unicode_normalized_p(
int argc,
VALUE *argv,
VALUE str)
13177 return unicode_normalize_common(argc, argv, str, id_normalized_p);
13309#define sym_equal rb_obj_equal
13312sym_printable(
const char *s,
const char *send,
rb_encoding *enc)
13316 int c = rb_enc_precise_mbclen(s, send, enc);
13320 c = rb_enc_mbc_to_codepoint(s, send, enc);
13328rb_str_symname_p(
VALUE sym)
13333 rb_encoding *resenc = rb_default_internal_encoding();
13335 if (resenc == NULL) resenc = rb_default_external_encoding();
13336 enc = STR_ENC_GET(sym);
13337 ptr = RSTRING_PTR(sym);
13338 len = RSTRING_LEN(sym);
13339 if ((resenc != enc && !rb_str_is_ascii_only_p(sym)) ||
len != (
long)strlen(ptr) ||
13347rb_str_quote_unprintable(
VALUE str)
13355 resenc = rb_default_internal_encoding();
13356 if (resenc == NULL) resenc = rb_default_external_encoding();
13357 enc = STR_ENC_GET(str);
13358 ptr = RSTRING_PTR(str);
13359 len = RSTRING_LEN(str);
13360 if ((resenc != enc && !rb_str_is_ascii_only_p(str)) ||
13361 !sym_printable(ptr, ptr +
len, enc)) {
13362 return rb_str_escape(str);
13368rb_id_quote_unprintable(
ID id)
13370 VALUE str = rb_id2str(
id);
13371 if (!rb_str_symname_p(str)) {
13372 return rb_str_escape(str);
13390sym_inspect(
VALUE sym)
13397 if (!rb_str_symname_p(str)) {
13399 len = RSTRING_LEN(str);
13400 rb_str_resize(str,
len + 1);
13401 dest = RSTRING_PTR(str);
13402 memmove(dest + 1, dest,
len);
13406 VALUE orig_str = str;
13408 len = RSTRING_LEN(orig_str);
13409 str = rb_enc_str_new(0,
len + 1, enc);
13412 ptr = RSTRING_PTR(orig_str);
13413 dest = RSTRING_PTR(str);
13414 memcpy(dest + 1, ptr,
len);
13432rb_sym_proc_call(
ID mid,
int argc,
const VALUE *argv,
int kw_splat,
VALUE passed_proc)
13437 rb_raise(rb_eArgError,
"no receiver given");
13540 return rb_str_match(
rb_sym2str(sym), other);
13555sym_match_m(
int argc,
VALUE *argv,
VALUE sym)
13557 return rb_str_match_m(argc, argv,
rb_sym2str(sym));
13570sym_match_m_p(
int argc,
VALUE *argv,
VALUE sym)
13572 return rb_str_match_m_p(argc, argv, sym);
13590 return rb_str_aref_m(argc, argv,
rb_sym2str(sym));
13601sym_length(
VALUE sym)
13635sym_downcase(
int argc,
VALUE *argv,
VALUE sym)
13651sym_capitalize(
int argc,
VALUE *argv,
VALUE sym)
13667sym_swapcase(
int argc,
VALUE *argv,
VALUE sym)
13681sym_start_with(
int argc,
VALUE *argv,
VALUE sym)
13683 return rb_str_start_with(argc, argv,
rb_sym2str(sym));
13696sym_end_with(
int argc,
VALUE *argv,
VALUE sym)
13698 return rb_str_end_with(argc, argv,
rb_sym2str(sym));
13710sym_encoding(
VALUE sym)
13716string_for_symbol(
VALUE name)
13721 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a symbol nor a string",
13735 name = string_for_symbol(name);
13736 return rb_intern_str(name);
13745 name = string_for_symbol(name);
13769 return rb_fstring(str);
13775 struct RString fake_str = {RBASIC_INIT};
13776 int encidx = ENCINDEX_US_ASCII;
13779 encidx = ENCINDEX_ASCII_8BIT;
13782 VALUE str = setup_fake_str(&fake_str,
ptr,
len, encidx);
13784 return register_fstring(str,
true,
false);
13796 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
13797 rb_enc_autoload(enc);
13800 struct RString fake_str = {RBASIC_INIT};
13801 return register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
true,
false);
13807 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
13808 rb_enc_autoload(enc);
13811 struct RString fake_str = {RBASIC_INIT};
13812 VALUE str = register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
true,
true);
13823#if USE_YJIT || USE_ZJIT
13825rb_jit_str_concat_codepoint(
VALUE str,
VALUE codepoint)
13830 if (RB_LIKELY(code >= 0 && code < 0xff)) {
13831 rb_str_buf_cat_byte(str, (
char) code);
13841fstring_set_class_i(
VALUE *str,
void *data)
13845 return ST_CONTINUE;
13853 rb_concurrent_set_foreach_with_replace(fstring_table_obj, fstring_set_class_i, NULL);
14021 mUnicodeNormalize = rb_define_module(
"UnicodeNormalize");
14032 rb_gc_register_address(&
rb_fs);
14070#include "string.rbinc"
#define RUBY_ASSERT_ALWAYS(expr,...)
A variant of RUBY_ASSERT that does not interface with RUBY_DEBUG.
#define RBIMPL_ASSERT_OR_ASSUME(...)
This is either RUBY_ASSERT or RBIMPL_ASSUME, depending on RUBY_DEBUG.
#define RUBY_ASSERT_BUILTIN_TYPE(obj, type)
A variant of RUBY_ASSERT that asserts when either RUBY_DEBUG or built-in type of obj is type.
#define RUBY_ASSERT(...)
Asserts that the given expression is truthy if and only if RUBY_DEBUG is truthy.
@ RUBY_ENC_CODERANGE_7BIT
The object holds 0 to 127 inclusive and nothing else.
static enum ruby_coderange_type RB_ENC_CODERANGE_AND(enum ruby_coderange_type a, enum ruby_coderange_type b)
"Mix" two code ranges into one.
static int rb_isspace(int c)
Our own locale-insensitive version of isspace(3).
static int rb_isascii(int c)
Our own locale-insensitive version of isascii(3).
#define rb_define_method(klass, mid, func, arity)
Defines klass#mid.
#define rb_define_singleton_method(klass, mid, func, arity)
Defines klass.mid.
static bool rb_enc_is_newline(const char *p, const char *e, rb_encoding *enc)
Queries if the passed pointer points to a newline character.
static bool rb_enc_isprint(OnigCodePoint c, rb_encoding *enc)
Identical to rb_isprint(), except it additionally takes an encoding.
static bool rb_enc_isctype(OnigCodePoint c, OnigCtype t, rb_encoding *enc)
Queries if the passed code point is of passed character type in the passed encoding.
VALUE rb_enc_sprintf(rb_encoding *enc, const char *fmt,...)
Identical to rb_sprintf(), except it additionally takes an encoding.
static VALUE RB_OBJ_FROZEN_RAW(VALUE obj)
This is an implementation detail of RB_OBJ_FROZEN().
static VALUE RB_FL_TEST_RAW(VALUE obj, VALUE flags)
This is an implementation detail of RB_FL_TEST().
void rb_include_module(VALUE klass, VALUE module)
Includes a module to a class.
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
void rb_undef_method(VALUE klass, const char *name)
Defines an undef of a method.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Retrieves argument from argc and argv to given VALUE references according to the format string.
int rb_block_given_p(void)
Determines if the current method is given a block.
int rb_get_kwargs(VALUE keyword_hash, const ID *table, int required, int optional, VALUE *values)
Keyword argument deconstructor.
#define TYPE(_)
Old name of rb_type.
#define ENCODING_SET_INLINED(obj, i)
Old name of RB_ENCODING_SET_INLINED.
#define RB_INTEGER_TYPE_P
Old name of rb_integer_type_p.
#define ENC_CODERANGE_7BIT
Old name of RUBY_ENC_CODERANGE_7BIT.
#define ENC_CODERANGE_VALID
Old name of RUBY_ENC_CODERANGE_VALID.
#define FL_UNSET_RAW
Old name of RB_FL_UNSET_RAW.
#define rb_str_buf_cat2
Old name of rb_usascii_str_new_cstr.
#define ALLOCV
Old name of RB_ALLOCV.
#define ISSPACE
Old name of rb_isspace.
#define T_STRING
Old name of RUBY_T_STRING.
#define ENC_CODERANGE_CLEAN_P(cr)
Old name of RB_ENC_CODERANGE_CLEAN_P.
#define ENC_CODERANGE_AND(a, b)
Old name of RB_ENC_CODERANGE_AND.
#define Qundef
Old name of RUBY_Qundef.
#define INT2FIX
Old name of RB_INT2FIX.
#define OBJ_FROZEN
Old name of RB_OBJ_FROZEN.
#define rb_str_cat2
Old name of rb_str_cat_cstr.
#define UNREACHABLE
Old name of RBIMPL_UNREACHABLE.
#define ID2SYM
Old name of RB_ID2SYM.
#define T_BIGNUM
Old name of RUBY_T_BIGNUM.
#define OBJ_FREEZE
Old name of RB_OBJ_FREEZE.
#define T_FIXNUM
Old name of RUBY_T_FIXNUM.
#define UNREACHABLE_RETURN
Old name of RBIMPL_UNREACHABLE_RETURN.
#define SYM2ID
Old name of RB_SYM2ID.
#define ENC_CODERANGE(obj)
Old name of RB_ENC_CODERANGE.
#define CLASS_OF
Old name of rb_class_of.
#define ENC_CODERANGE_UNKNOWN
Old name of RUBY_ENC_CODERANGE_UNKNOWN.
#define SIZET2NUM
Old name of RB_SIZE2NUM.
#define FIXABLE
Old name of RB_FIXABLE.
#define xmalloc
Old name of ruby_xmalloc.
#define ENCODING_GET(obj)
Old name of RB_ENCODING_GET.
#define LONG2FIX
Old name of RB_INT2FIX.
#define ISDIGIT
Old name of rb_isdigit.
#define ENC_CODERANGE_MASK
Old name of RUBY_ENC_CODERANGE_MASK.
#define ZALLOC_N
Old name of RB_ZALLOC_N.
#define T_HASH
Old name of RUBY_T_HASH.
#define ALLOC_N
Old name of RB_ALLOC_N.
#define MBCLEN_CHARFOUND_LEN(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_LEN.
#define FL_TEST_RAW
Old name of RB_FL_TEST_RAW.
#define FL_SET
Old name of RB_FL_SET.
#define rb_ary_new3
Old name of rb_ary_new_from_args.
#define ENCODING_INLINE_MAX
Old name of RUBY_ENCODING_INLINE_MAX.
#define LONG2NUM
Old name of RB_LONG2NUM.
#define FL_ANY_RAW
Old name of RB_FL_ANY_RAW.
#define ISALPHA
Old name of rb_isalpha.
#define MBCLEN_INVALID_P(ret)
Old name of ONIGENC_MBCLEN_INVALID_P.
#define ISASCII
Old name of rb_isascii.
#define ULL2NUM
Old name of RB_ULL2NUM.
#define TOLOWER
Old name of rb_tolower.
#define Qtrue
Old name of RUBY_Qtrue.
#define ST2FIX
Old name of RB_ST2FIX.
#define MBCLEN_NEEDMORE_P(ret)
Old name of ONIGENC_MBCLEN_NEEDMORE_P.
#define FIXNUM_MAX
Old name of RUBY_FIXNUM_MAX.
#define NUM2INT
Old name of RB_NUM2INT.
#define Qnil
Old name of RUBY_Qnil.
#define Qfalse
Old name of RUBY_Qfalse.
#define FIX2LONG
Old name of RB_FIX2LONG.
#define ENC_CODERANGE_BROKEN
Old name of RUBY_ENC_CODERANGE_BROKEN.
#define scan_hex(s, l, e)
Old name of ruby_scan_hex.
#define NIL_P
Old name of RB_NIL_P.
#define ALLOCV_N
Old name of RB_ALLOCV_N.
#define MBCLEN_CHARFOUND_P(ret)
Old name of ONIGENC_MBCLEN_CHARFOUND_P.
#define NUM2ULL
Old name of RB_NUM2ULL.
#define DBL2NUM
Old name of rb_float_new.
#define ISPRINT
Old name of rb_isprint.
#define BUILTIN_TYPE
Old name of RB_BUILTIN_TYPE.
#define ENCODING_SHIFT
Old name of RUBY_ENCODING_SHIFT.
#define FL_TEST
Old name of RB_FL_TEST.
#define FL_FREEZE
Old name of RUBY_FL_FREEZE.
#define NUM2LONG
Old name of RB_NUM2LONG.
#define ENCODING_GET_INLINED(obj)
Old name of RB_ENCODING_GET_INLINED.
#define ENC_CODERANGE_CLEAR(obj)
Old name of RB_ENC_CODERANGE_CLEAR.
#define FL_UNSET
Old name of RB_FL_UNSET.
#define UINT2NUM
Old name of RB_UINT2NUM.
#define ENCODING_IS_ASCII8BIT(obj)
Old name of RB_ENCODING_IS_ASCII8BIT.
#define FIXNUM_P
Old name of RB_FIXNUM_P.
#define CONST_ID
Old name of RUBY_CONST_ID.
#define rb_ary_new2
Old name of rb_ary_new_capa.
#define ENC_CODERANGE_SET(obj, cr)
Old name of RB_ENC_CODERANGE_SET.
#define ENCODING_CODERANGE_SET(obj, encindex, cr)
Old name of RB_ENCODING_CODERANGE_SET.
#define FL_SET_RAW
Old name of RB_FL_SET_RAW.
#define SYMBOL_P
Old name of RB_SYMBOL_P.
#define OBJ_FROZEN_RAW
Old name of RB_OBJ_FROZEN_RAW.
#define T_REGEXP
Old name of RUBY_T_REGEXP.
#define ENCODING_MASK
Old name of RUBY_ENCODING_MASK.
void rb_category_warn(rb_warning_category_t category, const char *fmt,...)
Identical to rb_category_warning(), except it reports unless $VERBOSE is nil.
void rb_exc_raise(VALUE mesg)
Raises an exception in the current thread.
void rb_syserr_fail(int e, const char *mesg)
Raises appropriate exception that represents a C errno.
VALUE rb_eRangeError
RangeError exception.
VALUE rb_eTypeError
TypeError exception.
VALUE rb_eEncCompatError
Encoding::CompatibilityError exception.
VALUE rb_eRuntimeError
RuntimeError exception.
VALUE rb_eIndexError
IndexError exception.
@ RB_WARN_CATEGORY_DEPRECATED
Warning is for deprecated features.
VALUE rb_cObject
Object class.
VALUE rb_any_to_s(VALUE obj)
Generates a textual representation of the given object.
VALUE rb_obj_alloc(VALUE klass)
Allocates an instance of the given class.
VALUE rb_obj_hide(VALUE obj)
Make the object invisible from Ruby code.
VALUE rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass)
Identical to rb_class_new_instance(), except it passes the passed keywords if any to the #initialize ...
VALUE rb_obj_frozen_p(VALUE obj)
Just calls RB_OBJ_FROZEN() inside.
double rb_str_to_dbl(VALUE str, int mode)
Identical to rb_cstr_to_dbl(), except it accepts a Ruby's string instead of C's.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
VALUE rb_cSymbol
Symbol class.
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
VALUE rb_mComparable
Comparable module.
VALUE rb_cString
String class.
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
static char * rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the left boundary of a character.
static char * rb_enc_right_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the right boundary of a character.
static unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
Queries the code point of character pointed by the passed pointer.
static int rb_enc_mbmaxlen(rb_encoding *enc)
Queries the maximum number of bytes that the passed encoding needs to represent a character.
static int RB_ENCODING_GET_INLINED(VALUE obj)
Queries the encoding of the passed object.
static int rb_enc_code_to_mbclen(int c, rb_encoding *enc)
Identical to rb_enc_codelen(), except it returns 0 for invalid code points.
static char * rb_enc_step_back(const char *s, const char *p, const char *e, int n, rb_encoding *enc)
Scans the string backwards for n characters.
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
Encoding conversion main routine.
VALUE rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc)
Identical to rb_enc_str_new(), except it takes a C string literal.
char * rb_enc_nth(const char *head, const char *tail, long nth, rb_encoding *enc)
Queries the n-th character.
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
Identical to rb_str_conv_enc(), except it additionally takes IO encoder options.
VALUE rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc)
Identical to rb_enc_str_new(), except it returns a "f"string.
long rb_memsearch(const void *x, long m, const void *y, long n, rb_encoding *enc)
Looks for the passed string in the passed buffer.
long rb_enc_strlen(const char *head, const char *tail, rb_encoding *enc)
Counts the number of characters of the passed string, according to the passed encoding.
VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc)
Identical to rb_str_cat(), except it additionally takes an encoding.
VALUE rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
Identical to rb_enc_str_new(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_export_to_enc(VALUE obj, rb_encoding *enc)
Identical to rb_str_export(), except it additionally takes an encoding.
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *enc)
Identical to rb_external_str_new(), except it additionally takes an encoding.
int rb_enc_str_asciionly_p(VALUE str)
Queries if the passed string is "ASCII only".
VALUE rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc)
Identical to rb_enc_str_new_cstr(), except it returns a "f"string.
long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr)
Scans the passed string until it finds something odd.
int rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
Identical to rb_enc_symname_p(), except it additionally takes the passed string's length.
rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags)
Converts a string from an encoding to another.
rb_econv_result_t
return value of rb_econv_convert()
@ econv_finished
The conversion stopped after converting everything.
@ econv_destination_buffer_full
The conversion stopped because there is no destination.
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Identical to rb_econv_open(), except it additionally takes a hash of optional strings.
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Converts the contents of the passed string from its encoding to the passed one.
void rb_econv_close(rb_econv_t *ec)
Destructs a converter.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
VALUE rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval, int kw_splat)
Identical to rb_funcallv_with_block(), except you can specify how to handle the last element of the g...
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_freeze(VALUE obj)
Freeze an array, preventing further modifications.
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
VALUE rb_fs
The field separator character for inputs, or the $;.
VALUE rb_default_rs
This is the default value of rb_rs, i.e.
VALUE rb_backref_get(void)
Queries the last match, or Regexp.last_match, or the $~.
VALUE rb_sym_all_symbols(void)
Collects every single bits of symbols that have ever interned in the entire history of the current pr...
void rb_backref_set(VALUE md)
Updates $~.
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Deconstructs a numerical range.
int rb_reg_backref_number(VALUE match, VALUE backref)
Queries the index of the given named capture.
int rb_reg_options(VALUE re)
Queries the options of the passed regular expression.
VALUE rb_reg_match(VALUE re, VALUE str)
This is the match operator.
void rb_match_busy(VALUE md)
Asserts that the given MatchData is "occupied".
VALUE rb_reg_nth_match(int n, VALUE md)
Queries the nth captured substring.
void rb_str_free(VALUE str)
Destroys the given string for no reason.
VALUE rb_str_new_shared(VALUE str)
Identical to rb_str_new_cstr(), except it takes a Ruby's string instead of C's.
VALUE rb_str_plus(VALUE lhs, VALUE rhs)
Generates a new string, concatenating the former to the latter.
#define rb_utf8_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "UTF-8" encoding.
#define rb_hash_end(h)
Just another name of st_hash_end.
#define rb_hash_uint32(h, i)
Just another name of st_hash_uint32.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_filesystem_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "filesystem" encoding.
VALUE rb_sym_to_s(VALUE sym)
This is an rb_sym2str() + rb_str_dup() combo.
VALUE rb_str_times(VALUE str, VALUE num)
Repetition of a string.
VALUE rb_external_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "default external" encoding.
VALUE rb_str_tmp_new(long len)
Allocates a "temporary" string.
long rb_str_offset(VALUE str, long pos)
"Inverse" of rb_str_sublen().
VALUE rb_str_succ(VALUE orig)
Searches for the "successor" of a string.
int rb_str_hash_cmp(VALUE str1, VALUE str2)
Compares two strings.
VALUE rb_str_subseq(VALUE str, long beg, long len)
Identical to rb_str_substr(), except the numbers are interpreted as byte offsets instead of character...
VALUE rb_str_ellipsize(VALUE str, long len)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
void rb_str_shared_replace(VALUE dst, VALUE src)
Replaces the contents of the former with the latter.
#define rb_str_buf_cat
Just another name of rb_str_cat.
VALUE rb_str_new_static(const char *ptr, long len)
Identical to rb_str_new(), except it takes a C string literal.
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
size_t rb_str_capacity(VALUE str)
Queries the capacity of the given string.
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
st_index_t rb_str_hash(VALUE str)
Calculates a hash value of a string.
VALUE rb_str_cat(VALUE dst, const char *src, long srclen)
Destructively appends the passed contents to the string.
VALUE rb_str_locktmp(VALUE str)
Obtains a "temporary lock" of the string.
long rb_str_strlen(VALUE str)
Counts the number of characters (not bytes) that are stored inside of the given string.
VALUE rb_str_resurrect(VALUE str)
Like rb_str_dup(), but always create an instance of rb_cString regardless of the given object's class...
#define rb_str_buf_new_cstr(str)
Identical to rb_str_new_cstr, except done differently.
#define rb_usascii_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "US ASCII" encoding.
VALUE rb_str_replace(VALUE dst, VALUE src)
Replaces the contents of the former object with the stringised contents of the latter.
char * rb_str_subpos(VALUE str, long beg, long *len)
Identical to rb_str_substr(), except it returns a C's string instead of Ruby's.
rb_gvar_setter_t rb_str_setter
This is a rb_gvar_setter_t that refutes non-string assignments.
VALUE rb_interned_str_cstr(const char *ptr)
Identical to rb_interned_str(), except it assumes the passed pointer is a pointer to a C's string.
VALUE rb_filesystem_str_new_cstr(const char *ptr)
Identical to rb_filesystem_str_new(), except it assumes the passed pointer is a pointer to a C string...
#define rb_external_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "default external" encoding.
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
long rb_str_sublen(VALUE str, long pos)
Byte offset to character offset conversion.
VALUE rb_str_equal(VALUE str1, VALUE str2)
Equality of two strings.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
VALUE rb_str_inspect(VALUE str)
Generates a "readable" version of the receiver.
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
VALUE rb_interned_str(const char *ptr, long len)
Identical to rb_str_new(), except it returns an infamous "f"string.
int rb_str_cmp(VALUE lhs, VALUE rhs)
Compares two strings, as in strcmp(3).
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
int rb_str_comparable(VALUE str1, VALUE str2)
Checks if two strings are comparable each other or not.
#define rb_strlen_lit(str)
Length of a string literal.
VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src)
Identical to rb_str_cat_cstr(), except it additionally assumes the source string be a NUL terminated ...
VALUE rb_str_freeze(VALUE str)
This is the implementation of String#freeze.
void rb_str_update(VALUE dst, long beg, long len, VALUE src)
Replaces some (or all) of the contents of the given string.
VALUE rb_str_scrub(VALUE str, VALUE repl)
"Cleanses" the string.
#define rb_locale_str_new_cstr(str)
Identical to rb_external_str_new_cstr, except it generates a string of "locale" encoding instead of "...
VALUE rb_str_new_with_class(VALUE obj, const char *ptr, long len)
Identical to rb_str_new(), except it takes the class of the allocating object.
#define rb_str_dup_frozen
Just another name of rb_str_new_frozen.
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
VALUE rb_str_substr(VALUE str, long beg, long len)
This is the implementation of two-argumented String#slice.
#define rb_str_cat_cstr(buf, str)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_unlocktmp(VALUE str)
Releases a lock formerly obtained by rb_str_locktmp().
VALUE rb_utf8_str_new_static(const char *ptr, long len)
Identical to rb_str_new_static(), except it generates a string of "UTF-8" encoding instead of "binary...
#define rb_utf8_str_new(str, len)
Identical to rb_str_new, except it generates a string of "UTF-8" encoding.
void rb_str_modify_expand(VALUE str, long capa)
Identical to rb_str_modify(), except it additionally expands the capacity of the receiver.
VALUE rb_str_dump(VALUE str)
"Inverse" of rb_eval_string().
VALUE rb_locale_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "locale" encoding.
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
VALUE rb_str_length(VALUE)
Identical to rb_str_strlen(), except it returns the value in rb_cInteger.
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_drop_bytes(VALUE str, long len)
Shrinks the given string for the given number of bytes.
VALUE rb_str_split(VALUE str, const char *delim)
Divides the given string based on the given delimiter.
VALUE rb_usascii_str_new_static(const char *ptr, long len)
Identical to rb_str_new_static(), except it generates a string of "US ASCII" encoding instead of "bin...
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
void rb_undef_alloc_func(VALUE klass)
Deletes the allocator function of a class.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
VALUE rb_to_symbol(VALUE name)
Identical to rb_intern_str(), except it generates a dynamic symbol if necessary.
ID rb_to_id(VALUE str)
Identical to rb_intern_str(), except it tries to convert the parameter object to an instance of rb_cS...
int capa
Designed capacity of the buffer.
int off
Offset inside of ptr.
int len
Length of the buffer.
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
long rb_reg_search(VALUE re, VALUE str, long pos, int dir)
Runs the passed regular expression over the passed string.
VALUE rb_reg_regcomp(VALUE str)
Creates a new instance of rb_cRegexp.
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Formats a string.
VALUE rb_yield(VALUE val)
Yields the block.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define ALLOCA_N(type, n)
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
VALUE type(ANYARGS)
ANYARGS-ed function type.
void rb_hash_foreach(VALUE q, int_type *w, VALUE e)
Iteration over the given hash.
VALUE rb_ensure(type *q, VALUE w, type *e, VALUE r)
An equivalent of ensure clause.
Defines RBIMPL_ATTR_NONSTRING.
static int RARRAY_LENINT(VALUE ary)
Identical to rb_array_len(), except it differs for the return type.
#define RARRAY_CONST_PTR
Just another name of rb_array_const_ptr.
static VALUE RBASIC_CLASS(VALUE obj)
Queries the class of an object.
#define RBASIC(obj)
Convenient casting macro.
#define RHASH_SIZE(h)
Queries the size of the hash.
static VALUE RREGEXP_SRC(VALUE rexp)
Convenient getter function.
#define StringValue(v)
Ensures that the parameter object is a String.
VALUE rb_str_export_locale(VALUE obj)
Identical to rb_str_export(), except it converts into the locale encoding instead.
char * rb_string_value_cstr(volatile VALUE *ptr)
Identical to rb_string_value_ptr(), except it additionally checks for the contents for viability as a...
static int RSTRING_LENINT(VALUE str)
Identical to RSTRING_LEN(), except it differs for the return type.
static char * RSTRING_END(VALUE str)
Queries the end of the contents pointer of the string.
#define RSTRING_GETMEM(str, ptrvar, lenvar)
Convenient macro to obtain the contents and length at once.
VALUE rb_string_value(volatile VALUE *ptr)
Identical to rb_str_to_str(), except it fills the passed pointer with the converted object.
#define RSTRING(obj)
Convenient casting macro.
VALUE rb_str_export(VALUE obj)
Identical to rb_str_to_str(), except it additionally converts the string into default external encodi...
char * rb_string_value_ptr(volatile VALUE *ptr)
Identical to rb_str_to_str(), except it returns the converted string's backend memory region.
VALUE rb_str_to_str(VALUE obj)
Identical to rb_check_string_type(), except it raises exceptions in case of conversion failures.
#define StringValueCStr(v)
Identical to StringValuePtr, except it additionally checks for the contents for viability as a C stri...
#define DATA_PTR(obj)
Convenient casting macro for backward compatibility.
#define TypedData_Wrap_Struct(klass, data_type, sval)
Converts sval, a pointer to your struct, into a Ruby object.
VALUE rb_require(const char *feature)
Identical to rb_require_string(), except it takes C's string instead of Ruby's.
#define errno
Ractor-aware version of errno.
#define RB_NUM2SSIZE
Converts an instance of rb_cInteger into C's ssize_t.
#define RTEST
This is an old name of RB_TEST.
#define _(args)
This was a transition path from K&R to ANSI.
VALUE flags
Per-object flags.
struct RBasic basic
Basic part, including flags and class.
union RString::@60::@61::@63 aux
Auxiliary info.
long capa
Capacity of *ptr.
long len
Length of the string, not including terminating NUL character.
struct RString::@60::@61 heap
Strings that use separated memory region for contents use this pattern.
struct RString::@60::@62 embed
Embedded contents.
VALUE shared
Parent of the string.
char * ptr
Pointer to the contents of the string.
union RString::@60 as
String's specific fields.
This is the struct that holds necessary info for a struct.
void rb_nativethread_lock_lock(rb_nativethread_lock_t *lock)
Blocks until the current thread obtains a lock.
uintptr_t ID
Type that represents a Ruby identifier such as a variable name.
uintptr_t VALUE
Type that represents a Ruby object.
static enum ruby_value_type rb_type(VALUE obj)
Identical to RB_BUILTIN_TYPE(), except it can also accept special constants.
static void Check_Type(VALUE v, enum ruby_value_type t)
Identical to RB_TYPE_P(), except it raises exceptions on predication failure.
static bool RB_TYPE_P(VALUE obj, enum ruby_value_type t)
Queries if the given object is of given type.
ruby_value_type
C-level type of an object.