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;
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);
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 (s + slen <= e && memcmp(s, t, slen) == 0) {
4854 hit = memrchr(sbeg, c, searchlen);
4857 if (hit != adjusted) {
4858 searchlen = adjusted - sbeg;
4861 if (hit + slen <= e && 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;
4887 if (
len - pos < slen) pos =
len - slen;
4888 if (
len == 0)
return pos;
4890 sbeg = RSTRING_PTR(str);
4893 if (RSTRING_LEN(sub) <= RSTRING_LEN(str) &&
4894 memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0) {
4902 s = str_nth(sbeg,
RSTRING_END(str), pos, enc, singlebyte);
4903 return str_rindex(str, sub, s, enc);
4915rb_str_rindex_m(
int argc,
VALUE *argv,
VALUE str)
4920 long pos,
len = str_strlen(str, enc);
4922 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4924 if (pos < 0 && (pos +=
len) < 0) {
4930 if (pos >
len) pos =
len;
4938 pos = str_offset(RSTRING_PTR(str),
RSTRING_END(str), pos,
4939 enc, single_byte_optimizable(str));
4949 pos = rb_str_rindex(str, sub, pos);
4959rb_str_byterindex(
VALUE str,
VALUE sub,
long pos)
4962 const char *sbeg, *s;
4965 enc = rb_enc_check(str, sub);
4966 if (is_broken_string(sub))
return -1;
4967 len = RSTRING_LEN(str);
4968 slen = RSTRING_LEN(sub);
4971 if (
len < slen)
return -1;
4972 if (
len - pos < slen) pos =
len - slen;
4973 if (
len == 0)
return pos;
4975 sbeg = RSTRING_PTR(str);
4978 if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
4985 return str_rindex(str, sub, s, enc);
5075rb_str_byterindex_m(
int argc,
VALUE *argv,
VALUE str)
5079 long pos,
len = RSTRING_LEN(str);
5081 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
5083 if (pos < 0 && (pos +=
len) < 0) {
5089 if (pos >
len) pos =
len;
5095 str_ensure_byte_pos(str, pos);
5100 pos = RMATCH_BEG(match, 0);
5106 pos = rb_str_byterindex(str, sub, pos);
5107 if (pos >= 0)
return LONG2NUM(pos);
5149 switch (OBJ_BUILTIN_TYPE(y)) {
5201rb_str_match_m(
int argc,
VALUE *argv,
VALUE str)
5208 result =
rb_funcallv(get_pat(re), rb_intern(
"match"), argc, argv);
5239rb_str_match_m_p(
int argc,
VALUE *argv,
VALUE str)
5243 re = get_pat(argv[0]);
5244 return rb_reg_match_p(re, str, argc > 1 ?
NUM2LONG(argv[1]) : 0);
5253static enum neighbor_char
5259 if (rb_enc_mbminlen(enc) > 1) {
5261 int r = rb_enc_precise_mbclen(p, p +
len, enc), c;
5263 return NEIGHBOR_NOT_CHAR;
5265 c = rb_enc_mbc_to_codepoint(p, p +
len, enc) + 1;
5267 if (!l)
return NEIGHBOR_NOT_CHAR;
5268 if (l !=
len)
return NEIGHBOR_WRAPPED;
5269 rb_enc_mbcput(c, p, enc);
5270 r = rb_enc_precise_mbclen(p, p +
len, enc);
5272 return NEIGHBOR_NOT_CHAR;
5274 return NEIGHBOR_FOUND;
5277 for (i =
len-1; 0 <= i && (
unsigned char)p[i] == 0xff; i--)
5280 return NEIGHBOR_WRAPPED;
5281 ++((
unsigned char*)p)[i];
5282 l = rb_enc_precise_mbclen(p, p+
len, enc);
5286 return NEIGHBOR_FOUND;
5289 memset(p+l, 0xff,
len-l);
5295 for (len2 =
len-1; 0 < len2; len2--) {
5296 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5300 memset(p+len2+1, 0xff,
len-(len2+1));
5305static enum neighbor_char
5310 if (rb_enc_mbminlen(enc) > 1) {
5312 int r = rb_enc_precise_mbclen(p, p +
len, enc), c;
5314 return NEIGHBOR_NOT_CHAR;
5316 c = rb_enc_mbc_to_codepoint(p, p +
len, enc);
5317 if (!c)
return NEIGHBOR_NOT_CHAR;
5320 if (!l)
return NEIGHBOR_NOT_CHAR;
5321 if (l !=
len)
return NEIGHBOR_WRAPPED;
5322 rb_enc_mbcput(c, p, enc);
5323 r = rb_enc_precise_mbclen(p, p +
len, enc);
5325 return NEIGHBOR_NOT_CHAR;
5327 return NEIGHBOR_FOUND;
5330 for (i =
len-1; 0 <= i && (
unsigned char)p[i] == 0; i--)
5333 return NEIGHBOR_WRAPPED;
5334 --((
unsigned char*)p)[i];
5335 l = rb_enc_precise_mbclen(p, p+
len, enc);
5339 return NEIGHBOR_FOUND;
5342 memset(p+l, 0,
len-l);
5348 for (len2 =
len-1; 0 < len2; len2--) {
5349 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5353 memset(p+len2+1, 0,
len-(len2+1));
5367static enum neighbor_char
5368enc_succ_alnum_char(
char *p,
long len,
rb_encoding *enc,
char *carry)
5370 enum neighbor_char ret;
5374 char save[ONIGENC_CODE_TO_MBC_MAXLEN];
5378 const int max_gaps = 1;
5380 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5382 ctype = ONIGENC_CTYPE_DIGIT;
5384 ctype = ONIGENC_CTYPE_ALPHA;
5386 return NEIGHBOR_NOT_CHAR;
5389 for (
try = 0;
try <= max_gaps; ++
try) {
5390 ret = enc_succ_char(p,
len, enc);
5391 if (ret == NEIGHBOR_FOUND) {
5392 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5394 return NEIGHBOR_FOUND;
5401 ret = enc_pred_char(p,
len, enc);
5402 if (ret == NEIGHBOR_FOUND) {
5403 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5416 return NEIGHBOR_NOT_CHAR;
5419 if (ctype != ONIGENC_CTYPE_DIGIT) {
5421 return NEIGHBOR_WRAPPED;
5425 enc_succ_char(carry,
len, enc);
5426 return NEIGHBOR_WRAPPED;
5444 str =
rb_str_new(RSTRING_PTR(orig), RSTRING_LEN(orig));
5445 rb_enc_cr_str_copy_for_substr(str, orig);
5446 return str_succ(str);
5453 char *sbeg, *s, *e, *last_alnum = 0;
5454 int found_alnum = 0;
5456 char carry[ONIGENC_CODE_TO_MBC_MAXLEN] =
"\1";
5457 long carry_pos = 0, carry_len = 1;
5458 enum neighbor_char neighbor = NEIGHBOR_FOUND;
5460 slen = RSTRING_LEN(str);
5461 if (slen == 0)
return str;
5463 enc = STR_ENC_GET(str);
5464 sbeg = RSTRING_PTR(str);
5465 s = e = sbeg + slen;
5467 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5468 if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
5474 l = rb_enc_precise_mbclen(s, e, enc);
5475 if (!ONIGENC_MBCLEN_CHARFOUND_P(l))
continue;
5476 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5477 neighbor = enc_succ_alnum_char(s, l, enc, carry);
5479 case NEIGHBOR_NOT_CHAR:
5481 case NEIGHBOR_FOUND:
5483 case NEIGHBOR_WRAPPED:
5488 carry_pos = s - sbeg;
5493 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5494 enum neighbor_char neighbor;
5495 char tmp[ONIGENC_CODE_TO_MBC_MAXLEN];
5496 l = rb_enc_precise_mbclen(s, e, enc);
5497 if (!ONIGENC_MBCLEN_CHARFOUND_P(l))
continue;
5498 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5500 neighbor = enc_succ_char(tmp, l, enc);
5502 case NEIGHBOR_FOUND:
5506 case NEIGHBOR_WRAPPED:
5509 case NEIGHBOR_NOT_CHAR:
5512 if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
5514 enc_succ_char(s, l, enc);
5516 if (!rb_enc_asciicompat(enc)) {
5517 MEMCPY(carry, s,
char, l);
5520 carry_pos = s - sbeg;
5524 RESIZE_CAPA(str, slen + carry_len);
5525 sbeg = RSTRING_PTR(str);
5526 s = sbeg + carry_pos;
5527 memmove(s + carry_len, s, slen - carry_pos);
5528 memmove(s, carry, carry_len);
5530 STR_SET_LEN(str, slen);
5531 TERM_FILL(&sbeg[slen], rb_enc_mbminlen(enc));
5532 rb_enc_str_coderange(str);
5547rb_str_succ_bang(
VALUE str)
5555all_digits_p(
const char *s,
long len)
5583 VALUE end, exclusive;
5587 return rb_str_upto_each(beg, end,
RTEST(exclusive), str_upto_i,
Qnil);
5593 VALUE current, after_end;
5600 enc = rb_enc_check(beg, end);
5601 ascii = (is_ascii_string(beg) && is_ascii_string(end));
5603 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && ascii) {
5604 char c = RSTRING_PTR(beg)[0];
5605 char e = RSTRING_PTR(end)[0];
5607 if (c > e || (excl && c == e))
return beg;
5609 VALUE str = rb_enc_str_new(&c, 1, enc);
5611 if ((*each)(str, arg))
break;
5612 if (!excl && c == e)
break;
5614 if (excl && c == e)
break;
5619 if (ascii &&
ISDIGIT(RSTRING_PTR(beg)[0]) &&
ISDIGIT(RSTRING_PTR(end)[0]) &&
5620 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) &&
5621 all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) {
5626 b = rb_str_to_inum(beg, 10, FALSE);
5627 e = rb_str_to_inum(end, 10, FALSE);
5634 if (excl && bi == ei)
break;
5635 if ((*each)(
rb_enc_sprintf(usascii,
"%.*ld", width, bi), arg))
break;
5640 ID op = excl ?
'<' : idLE;
5641 VALUE args[2], fmt = rb_fstring_lit(
"%.*d");
5646 if ((*each)(
rb_str_format(numberof(args), args, fmt), arg))
break;
5654 if (n > 0 || (excl && n == 0))
return beg;
5662 if ((*each)(current, arg))
break;
5663 if (
NIL_P(next))
break;
5667 if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
5682 if (is_ascii_string(beg) &&
ISDIGIT(RSTRING_PTR(beg)[0]) &&
5683 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg))) {
5684 VALUE b, args[2], fmt = rb_fstring_lit(
"%.*d");
5686 b = rb_str_to_inum(beg, 10, FALSE);
5692 if ((*each)(
rb_enc_sprintf(usascii,
"%.*ld", width, bi), arg))
break;
5700 if ((*each)(
rb_str_format(numberof(args), args, fmt), arg))
break;
5708 if ((*each)(current, arg))
break;
5711 if (RSTRING_LEN(current) == 0)
5722 if (!
rb_equal(str, *argp))
return 0;
5736 if (rb_enc_asciicompat(STR_ENC_GET(beg)) &&
5737 rb_enc_asciicompat(STR_ENC_GET(end)) &&
5738 rb_enc_asciicompat(STR_ENC_GET(val))) {
5739 const char *bp = RSTRING_PTR(beg);
5740 const char *ep = RSTRING_PTR(end);
5741 const char *vp = RSTRING_PTR(val);
5742 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
5743 if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
5751 if (b <= v && v < e)
return Qtrue;
5752 return RBOOL(!
RTEST(exclusive) && v == e);
5759 all_digits_p(bp, RSTRING_LEN(beg)) &&
5760 all_digits_p(ep, RSTRING_LEN(end))) {
5765 rb_str_upto_each(beg, end,
RTEST(exclusive), include_range_i, (
VALUE)&val);
5767 return RBOOL(
NIL_P(val));
5790 return rb_str_subpat(str, indx,
INT2FIX(0));
5793 if (rb_str_index(str, indx, 0) != -1)
5799 long beg,
len = str_strlen(str, NULL);
5811 return str_substr(str, idx, 1, FALSE);
5828rb_str_aref_m(
int argc,
VALUE *argv,
VALUE str)
5832 return rb_str_subpat(str, argv[0], argv[1]);
5835 return rb_str_substr_two_fixnums(str, argv[0], argv[1], TRUE);
5839 return rb_str_aref(str, argv[0]);
5845 char *
ptr = RSTRING_PTR(str);
5846 long olen = RSTRING_LEN(str), nlen;
5848 str_modifiable(str);
5849 if (
len > olen)
len = olen;
5851 if (str_embed_capa(str) >= nlen + TERM_LEN(str)) {
5853 size_t old_capa =
RSTRING(str)->as.heap.aux.capa + TERM_LEN(str);
5854 int fl = (int)(
RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED|STR_NOFREE));
5857 memmove(
ptr, oldptr +
len, nlen);
5858 if (fl == STR_NOEMBED) {
5859 SIZED_FREE_N(oldptr, old_capa);
5863 if (!STR_SHARED_P(str)) {
5865 rb_enc_cr_str_exact_copy(
shared, str);
5870 STR_SET_LEN(str, nlen);
5872 if (!SHARABLE_MIDDLE_SUBSTRING) {
5873 TERM_FILL(
ptr + nlen, TERM_LEN(str));
5880rb_str_update_1(
VALUE str,
long beg,
long len,
VALUE val,
long vbeg,
long vlen)
5886 if (beg == 0 && vlen == 0) {
5891 str_modify_keep_cr(str);
5895 RESIZE_CAPA(str, slen + vlen -
len);
5896 sptr = RSTRING_PTR(str);
5900 cr = rb_enc_str_coderange(val);
5905 memmove(sptr + beg + vlen,
5907 slen - (beg +
len));
5909 if (vlen < beg &&
len < 0) {
5913 memmove(sptr + beg, RSTRING_PTR(val) + vbeg, vlen);
5916 STR_SET_LEN(str, slen);
5917 TERM_FILL(&sptr[slen], TERM_LEN(str));
5924 rb_str_update_1(str, beg,
len, val, 0, RSTRING_LEN(val));
5933 int singlebyte = single_byte_optimizable(str);
5939 enc = rb_enc_check(str, val);
5940 slen = str_strlen(str, enc);
5942 if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) {
5951 if (
len > slen - beg) {
5954 p = str_nth(RSTRING_PTR(str),
RSTRING_END(str), beg, enc, singlebyte);
5959 beg = p - RSTRING_PTR(str);
5961 rb_str_update_0(str, beg,
len, val);
5962 rb_enc_associate(str, enc);
5973 long start, end,
len;
5981 int num_regs = RMATCH_NREGS(match);
5982 if ((nth >= num_regs) || ((nth < 0) && (-nth >= num_regs))) {
5989 start = RMATCH_BEG(match, nth);
5993 end = RMATCH_END(match, nth);
5996 enc = rb_enc_check_str(str, val);
5997 rb_str_update_0(str, start,
len, val);
5998 rb_enc_associate(str, enc);
6006 switch (
TYPE(indx)) {
6008 rb_str_subpat_set(str, indx,
INT2FIX(0), val);
6012 beg = rb_str_index(str, indx, 0);
6051rb_str_aset_m(
int argc,
VALUE *argv,
VALUE str)
6055 rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
6063 return rb_str_aset(str, argv[0], argv[1]);
6115rb_str_slice_bang(
int argc,
VALUE *argv,
VALUE str)
6123 str_modify_keep_cr(str);
6128 int num_regs = RMATCH_NREGS(match);
6131 if ((nth += num_regs) <= 0)
return Qnil;
6133 else if (nth >= num_regs)
return Qnil;
6134 beg = RMATCH_BEG(match, nth);
6135 len = RMATCH_END(match, nth) - beg;
6138 else if (argc == 2) {
6147 beg = p - RSTRING_PTR(str);
6151 beg = rb_str_index(str, indx, 0);
6152 if (beg == -1)
return Qnil;
6153 len = RSTRING_LEN(indx);
6165 beg = p - RSTRING_PTR(str);
6174 beg = p - RSTRING_PTR(str);
6178 rb_enc_cr_str_copy_for_substr(result, str);
6186 char *sptr = RSTRING_PTR(str);
6187 long slen = RSTRING_LEN(str);
6188 if (beg +
len > slen)
6192 slen - (beg +
len));
6194 STR_SET_LEN(str, slen);
6195 TERM_FILL(&sptr[slen], TERM_LEN(str));
6206 switch (OBJ_BUILTIN_TYPE(pat)) {
6225get_pat_quoted(
VALUE pat,
int check)
6229 switch (OBJ_BUILTIN_TYPE(pat)) {
6243 if (check && is_broken_string(pat)) {
6250rb_pat_search0(
VALUE pat,
VALUE str,
long pos,
int set_backref_str,
VALUE *match)
6253 pos = rb_str_byteindex(str, pat, pos);
6254 if (set_backref_str) {
6256 str = rb_str_new_frozen_String(str);
6257 VALUE match_data = rb_backref_set_string(str, pos, RSTRING_LEN(pat));
6259 *match = match_data;
6269 return rb_reg_search0(pat, str, pos, 0, set_backref_str, match);
6274rb_pat_search(
VALUE pat,
VALUE str,
long pos,
int set_backref_str)
6276 return rb_pat_search0(pat, str, pos, set_backref_str, NULL);
6294rb_str_sub_bang(
int argc,
VALUE *argv,
VALUE str)
6309 hash = rb_check_hash_type(repl);
6316 pat = get_pat_quoted(argv[0], 1);
6318 str_modifiable(str);
6319 beg = rb_pat_search(pat, str, 0, 1);
6331 end0 = beg0 + RSTRING_LEN(pat);
6335 beg0 = RMATCH_BEG(match, 0);
6336 end0 = RMATCH_END(match, 0);
6340 if (iter || !
NIL_P(hash)) {
6341 p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
6347 repl = rb_hash_aref(hash,
rb_str_subseq(str, beg0, end0 - beg0));
6350 str_mod_check(str, p,
len);
6351 rb_check_frozen(str);
6354 repl = rb_reg_regsub_match(repl, str, match);
6357 enc = rb_enc_compatible(str, repl);
6360 p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
6364 rb_enc_inspect_name(str_enc),
6365 rb_enc_inspect_name(STR_ENC_GET(repl)));
6367 enc = STR_ENC_GET(repl);
6370 rb_enc_associate(str, enc);
6380 rlen = RSTRING_LEN(repl);
6381 len = RSTRING_LEN(str);
6383 RESIZE_CAPA(str,
len + rlen - plen);
6385 p = RSTRING_PTR(str);
6387 memmove(p + beg0 + rlen, p + beg0 + plen,
len - beg0 - plen);
6389 rp = RSTRING_PTR(repl);
6390 memmove(p + beg0, rp, rlen);
6392 STR_SET_LEN(str,
len);
6393 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
6416 rb_str_sub_bang(argc, argv, str);
6421str_gsub(
int argc,
VALUE *argv,
VALUE str,
int bang)
6424 long beg, beg0, end0;
6425 long offset, blen, slen,
len, last;
6426 enum {STR, ITER, FAST_MAP, MAP} mode = STR;
6428 int need_backref_str = -1;
6439 hash = rb_check_hash_type(repl);
6443 else if (rb_hash_default_unredefined(hash) && !
FL_TEST_RAW(hash, RHASH_PROC_DEFAULT)) {
6452 rb_error_arity(argc, 1, 2);
6455 pat = get_pat_quoted(argv[0], 1);
6456 beg = rb_pat_search0(pat, str, 0, need_backref_str, &match);
6459 if (bang)
return Qnil;
6462 if (bang) str_modify_keep_cr(str);
6465 blen = RSTRING_LEN(str) + 30;
6467 sp = RSTRING_PTR(str);
6468 slen = RSTRING_LEN(str);
6470 str_enc = STR_ENC_GET(str);
6471 rb_enc_associate(dest, str_enc);
6477 end0 = beg0 + RSTRING_LEN(pat);
6481 beg0 = RMATCH_BEG(match, 0);
6482 end0 = RMATCH_END(match, 0);
6491 struct RString fake_str = {RBASIC_INIT};
6493 if (mode == FAST_MAP) {
6502 val = rb_hash_aref(hash, key);
6505 str_mod_check(str, sp, slen);
6510 else if (need_backref_str) {
6511 val = rb_reg_regsub_match(repl, str, match);
6512 if (need_backref_str < 0) {
6513 need_backref_str = val != repl;
6520 len = beg0 - offset;
6534 if (RSTRING_LEN(str) <= end0)
break;
6535 len = rb_enc_fast_mbclen(RSTRING_PTR(str)+end0,
RSTRING_END(str), str_enc);
6537 offset = end0 +
len;
6539 cp = RSTRING_PTR(str) + offset;
6540 if (offset > RSTRING_LEN(str))
break;
6543 if (mode != FAST_MAP && mode != STR) {
6546 beg = rb_pat_search0(pat, str, offset, need_backref_str, &match);
6551 if (RSTRING_LEN(str) > offset) {
6554 rb_pat_search0(pat, str, last, 1, &match);
6556 str_shared_replace(str, dest);
6581rb_str_gsub_bang(
int argc,
VALUE *argv,
VALUE str)
6583 str_modifiable(str);
6584 return str_gsub(argc, argv, str, 1);
6634 return str_gsub(argc, argv, str, 0);
6654 str_modifiable(str);
6655 if (str == str2)
return str;
6659 return str_replace(str, str2);
6676rb_str_clear(
VALUE str)
6680 STR_SET_LEN(str, 0);
6681 RSTRING_PTR(str)[0] = 0;
6682 if (rb_enc_asciicompat(STR_ENC_GET(str)))
6698rb_str_chr(
VALUE str)
6716 pos += RSTRING_LEN(str);
6717 if (pos < 0 || RSTRING_LEN(str) <= pos)
6720 return INT2FIX((
unsigned char)RSTRING_PTR(str)[pos]);
6740 long len = RSTRING_LEN(str);
6741 char *
ptr, *head, *left = 0;
6745 if (pos < -
len ||
len <= pos)
6752 char byte = (char)(
NUM2INT(w) & 0xFF);
6754 if (!str_independent(str))
6755 str_make_independent(str);
6756 enc = STR_ENC_GET(str);
6757 head = RSTRING_PTR(str);
6759 if (!STR_EMBED_P(str)) {
6766 nlen = rb_enc_precise_mbclen(left, head+
len, enc);
6774 width = rb_enc_precise_mbclen(left, head+
len, enc);
6776 nlen = rb_enc_precise_mbclen(left, head+
len, enc);
6792str_bit_offset_out_of_range(
long byte_len, uint64_t bit_offset)
6795 return bit_offset / CHAR_BIT >= (uint64_t)byte_len;
6811str_bit_offset_from_index(
VALUE index)
6823 offset.long_value =
FIX2LONG(integer);
6824 if (offset.long_value < 0) {
6827 offset.value = (uint64_t)offset.long_value;
6828 offset.fits_long =
true;
6833 if (rb_int_negative_p(integer)) {
6836 if (rb_cmpint(rb_int_cmp(integer,
ULL2NUM(UINT64_MAX)), integer,
ULL2NUM(UINT64_MAX)) > 0) {
6837 rb_raise(rb_eArgError,
"bit index out of representable range");
6840 offset.value = (uint64_t)
NUM2ULL(integer);
6841 if (offset.value <= (uint64_t)LONG_MAX) {
6842 offset.long_value = (long)offset.value;
6843 offset.fits_long =
true;
6846 offset.long_value = 0;
6847 offset.fits_long =
false;
6857str_bit_length_from_index(
VALUE index)
6864 rb_raise(rb_eArgError,
"negative bit length");
6866 return (uint64_t)value;
6870 if (rb_int_negative_p(integer)) {
6871 rb_raise(rb_eArgError,
"negative bit length");
6873 if (rb_cmpint(rb_int_cmp(integer,
ULL2NUM(UINT64_MAX)), integer,
ULL2NUM(UINT64_MAX)) > 0) {
6874 rb_raise(rb_eArgError,
"bit length out of representable range");
6876 return (uint64_t)
NUM2ULL(integer);
6879static inline uint64_t
6880str_bit_size(
long byte_len)
6886 if ((uint64_t)byte_len > UINT64_MAX / CHAR_BIT)
return UINT64_MAX;
6887 return (uint64_t)byte_len * CHAR_BIT;
6892 uint64_t end_exclusive;
6915 out->beg =
NIL_P(beg_v) ? 0 : str_bit_offset_from_index(beg_v).value;
6917 out->end_open =
true;
6918 out->end_exclusive = 0;
6921 uint64_t end = str_bit_offset_from_index(end_v).value;
6922 out->end_open =
false;
6927 out->end_exclusive = (excl || end == UINT64_MAX) ? end : end + 1;
6937str_bit_range_resolve(
const struct str_bit_range *range, uint64_t total_bits, uint64_t *begp, uint64_t *lenp)
6939 uint64_t beg = range->beg;
6940 if (beg > total_bits)
return false;
6942 uint64_t end_exclusive = range->end_open ? total_bits : range->end_exclusive;
6943 if (end_exclusive < beg) end_exclusive = beg;
6946 *lenp = end_exclusive - beg;
6951str_lsb_first_from_opts(
VALUE opts)
6953 static ID keywords[1];
6961 if (vlsb_first ==
Qundef || vlsb_first ==
Qtrue) {
6964 if (vlsb_first ==
Qfalse) {
6967 rb_raise(rb_eArgError,
"lsb_first must be true or false");
6972str_lsb_first(
int argc,
VALUE *argv,
VALUE *index)
6977 return str_lsb_first_from_opts(opts);
6980static inline uint64_t
6981str_logical_to_physical_bit64(uint64_t logical,
bool lsb_first)
6983 return lsb_first ? logical : ((logical & ~(uint64_t)7) | (7 - (logical & 7)));
6987str_logical_to_physical_bit(
long logical,
bool lsb_first)
6989 return lsb_first ? logical : ((logical & ~7L) | (7 - (logical & 7L)));
6994 unsigned int bit_offset;
6998str_bit_location_from_offset(uint64_t logical, bool lsb_first)
7004 uint64_t physical = str_logical_to_physical_bit64(logical, lsb_first);
7006 location.byte_index = (long)(physical / CHAR_BIT);
7007 location.bit_offset = (
unsigned int)(physical % CHAR_BIT);
7012str_get_bit(
const char *ptr,
long bit_index)
7014 return (((
unsigned char)ptr[bit_index / CHAR_BIT]) >> (bit_index % CHAR_BIT)) & 1;
7020 return (((
unsigned char)ptr[location.byte_index]) >> location.bit_offset) & 1;
7027 bool lsb_first = str_lsb_first(argc, argv, &index);
7030 if (str_bit_offset_out_of_range(RSTRING_LEN(str), offset.value)) {
7034 if (offset.fits_long) {
7035 return str_get_bit(RSTRING_PTR(str), str_logical_to_physical_bit(offset.long_value, lsb_first));
7038 return str_get_bit_location(RSTRING_PTR(str), str_bit_location_from_offset(offset.value, lsb_first));
7050rb_str_bit_get(
int argc,
VALUE *argv,
VALUE str)
7052 int bit = str_bit_get(argc, argv, str);
7064rb_str_bit_set_p(
int argc,
VALUE *argv,
VALUE str)
7066 int bit = str_bit_get(argc, argv, str);
7067 return bit < 0 ?
Qnil : RBOOL(bit);
7070enum str_bit_mutation {
7081static inline unsigned char
7082str_bit_region_byte_mask(
unsigned int lo,
unsigned int hi,
bool lsb_first)
7085 return (
unsigned char)((0xFFu >> (7 - hi)) & (0xFFu << lo));
7088 return (
unsigned char)((0xFFu >> lo) & (0xFFu << (7 - hi)));
7093str_apply_bit_mask(
unsigned char *
byte,
unsigned char mask,
enum str_bit_mutation mutation)
7100 *
byte &= (
unsigned char)~mask;
7110str_mutate_bit_region(
unsigned char *ptr, uint64_t beg, uint64_t
len,
bool lsb_first,
enum str_bit_mutation mutation)
7112 uint64_t first_bit = beg;
7113 uint64_t last_bit = beg +
len - 1;
7114 long first_byte = (long)(first_bit / CHAR_BIT);
7115 long last_byte = (long)(last_bit / CHAR_BIT);
7116 unsigned int first_off = (
unsigned int)(first_bit % CHAR_BIT);
7117 unsigned int last_off = (
unsigned int)(last_bit % CHAR_BIT);
7119 if (first_byte == last_byte) {
7120 str_apply_bit_mask(ptr + first_byte, str_bit_region_byte_mask(first_off, last_off, lsb_first), mutation);
7124 str_apply_bit_mask(ptr + first_byte, str_bit_region_byte_mask(first_off, 7, lsb_first), mutation);
7125 long middle_len = last_byte - first_byte - 1;
7126 if (middle_len > 0) {
7127 unsigned char *middle = ptr + first_byte + 1;
7130 memset(middle, 0xFF, middle_len);
7133 memset(middle, 0, middle_len);
7141 for (
long i = 0; i < middle_len; i++) {
7147 str_apply_bit_mask(ptr + last_byte, str_bit_region_byte_mask(0, last_off, lsb_first), mutation);
7151str_mutate_single_bit(
VALUE str,
VALUE index,
bool lsb_first,
enum str_bit_mutation mutation)
7159 if (str_bit_offset_out_of_range(RSTRING_LEN(str), offset.value)) {
7164 ptr = (
unsigned char *)RSTRING_PTR(str);
7165 if (offset.fits_long) {
7166 bit_index = str_logical_to_physical_bit(offset.long_value, lsb_first);
7167 mask = (
unsigned char)(1u << (bit_index % CHAR_BIT));
7168 location.byte_index = bit_index / CHAR_BIT;
7171 location = str_bit_location_from_offset(offset.value, lsb_first);
7172 mask = (
unsigned char)(1u << location.bit_offset);
7175 str_apply_bit_mask(ptr + location.byte_index, mask, mutation);
7180str_mutate_bit(
int argc,
VALUE *argv,
VALUE str,
enum str_bit_mutation mutation)
7182 VALUE target, length_v, opts;
7183 uint64_t beg = 0,
len = 0;
7186 int nargs =
rb_scan_args(argc, argv,
"11:", &target, &length_v, &opts);
7187 bool lsb_first = str_lsb_first_from_opts(opts);
7190 if (nargs == 1 && !is_range) {
7191 return str_mutate_single_bit(str, target, lsb_first, mutation);
7198 rb_raise(rb_eArgError,
"bit length not allowed with a Range");
7200 str_bit_range_to_offsets(target, &range);
7203 offset = str_bit_offset_from_index(target);
7204 len = str_bit_length_from_index(length_v);
7213 uint64_t total_bits = str_bit_size(RSTRING_LEN(str));
7215 if (!str_bit_range_resolve(&range, total_bits, &beg, &
len) ||
len > total_bits - beg) {
7221 if (beg > total_bits ||
len > total_bits - beg) {
7226 rb_check_frozen(str);
7227 if (
len == 0)
return str;
7230 str_mutate_bit_region((
unsigned char *)RSTRING_PTR(str), beg,
len, lsb_first, mutation);
7244rb_str_bit_set(
int argc,
VALUE *argv,
VALUE str)
7246 return str_mutate_bit(argc, argv, str, STR_BIT_SET);
7259rb_str_bit_clear(
int argc,
VALUE *argv,
VALUE str)
7261 return str_mutate_bit(argc, argv, str, STR_BIT_CLEAR);
7274rb_str_bit_flip(
int argc,
VALUE *argv,
VALUE str)
7276 return str_mutate_bit(argc, argv, str, STR_BIT_FLIP);
7280str_count_bits(
const unsigned char *ptr,
long len)
7284 long unrolled_end =
len & ~31L;
7285 long aligned_end =
len & ~7L;
7288 for (;
off < unrolled_end;
off += 32) {
7289 uint64_t w0, w1, w2, w3;
7290 memcpy(&w0, ptr +
off, 8);
7291 memcpy(&w1, ptr +
off + 8, 8);
7292 memcpy(&w2, ptr +
off + 16, 8);
7293 memcpy(&w3, ptr +
off + 24, 8);
7294 count += rb_popcount64(w0);
7295 count += rb_popcount64(w1);
7296 count += rb_popcount64(w2);
7297 count += rb_popcount64(w3);
7301 for (;
off < aligned_end;
off += 8) {
7303 memcpy(&word, ptr +
off, 8);
7304 count += rb_popcount64(word);
7311 for (;
off <
len;
off++, shift += CHAR_BIT) {
7312 word |= (uint64_t)ptr[
off] << shift;
7314 count += rb_popcount64(word);
7321str_count_bits_region(
const unsigned char *ptr, uint64_t beg, uint64_t
len,
bool lsb_first)
7323 uint64_t first_bit = beg;
7324 uint64_t last_bit = beg +
len - 1;
7325 long first_byte = (long)(first_bit / CHAR_BIT);
7326 long last_byte = (long)(last_bit / CHAR_BIT);
7327 unsigned int first_off = (
unsigned int)(first_bit % CHAR_BIT);
7328 unsigned int last_off = (
unsigned int)(last_bit % CHAR_BIT);
7330 if (first_byte == last_byte) {
7331 return rb_popcount32((uint32_t)(ptr[first_byte] & str_bit_region_byte_mask(first_off, last_off, lsb_first)));
7334 uint64_t count = rb_popcount32((uint32_t)(ptr[first_byte] & str_bit_region_byte_mask(first_off, 7, lsb_first)));
7335 count += str_count_bits(ptr + first_byte + 1, last_byte - first_byte - 1);
7336 count += rb_popcount32((uint32_t)(ptr[last_byte] & str_bit_region_byte_mask(0, last_off, lsb_first)));
7350rb_str_bit_count(
int argc,
VALUE *argv,
VALUE str)
7353 uint64_t beg = 0,
len = 0;
7356 int nargs =
rb_scan_args(argc, argv,
"02:", &v0, &v1, &opts);
7361 bool lsb_first = str_lsb_first_from_opts(opts);
7364 return ULL2NUM(str_count_bits((
const unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)));
7371 rb_raise(rb_eArgError,
"bit length not allowed with a Range");
7373 str_bit_range_to_offsets(v0, &range);
7375 else if (nargs == 1) {
7376 rb_raise(rb_eArgError,
"no bit length given");
7379 beg = str_bit_offset_from_index(v0).value;
7380 len = str_bit_length_from_index(v1);
7383 const unsigned char *ptr = (
const unsigned char *)RSTRING_PTR(str);
7384 uint64_t total_bits = str_bit_size(RSTRING_LEN(str));
7386 if (!str_bit_range_resolve(&range, total_bits, &beg, &
len)) {
7390 else if (beg >= total_bits) {
7395 if (
len > total_bits - beg)
len = total_bits - beg;
7397 return ULL2NUM(str_count_bits_region(ptr, beg,
len, lsb_first));
7401str_check_bitwise_length(
VALUE str,
VALUE other)
7403 if (RSTRING_LEN(str) != RSTRING_LEN(other)) {
7404 rb_raise(rb_eArgError,
"operands must have the same length (%ld vs %ld)",
7405 RSTRING_LEN(str), RSTRING_LEN(other));
7410str_bitwise_result(
VALUE str)
7412 long len = RSTRING_LEN(str);
7414 rb_str_resize(result,
len);
7415 rb_enc_associate(result, rb_ascii8bit_encoding());
7420#define STR_DEFINE_UNARY_BITWISE_KERNEL(name, expr_word, expr_byte) \
7422 name(unsigned char *dst, const unsigned char *src, long len) \
7425 long unrolled_end = len & ~31L; \
7426 long aligned_end = len & ~7L; \
7427 for (; off < unrolled_end; off += 32) { \
7428 uint64_t s0, s1, s2, s3; \
7429 memcpy(&s0, src + off, 8); \
7430 memcpy(&s1, src + off + 8, 8); \
7431 memcpy(&s2, src + off + 16, 8); \
7432 memcpy(&s3, src + off + 24, 8); \
7433 s0 = (expr_word(s0)); \
7434 s1 = (expr_word(s1)); \
7435 s2 = (expr_word(s2)); \
7436 s3 = (expr_word(s3)); \
7437 memcpy(dst + off, &s0, 8); \
7438 memcpy(dst + off + 8, &s1, 8); \
7439 memcpy(dst + off + 16, &s2, 8); \
7440 memcpy(dst + off + 24, &s3, 8); \
7442 for (; off < aligned_end; off += 8) { \
7444 memcpy(&word, src + off, 8); \
7445 word = (expr_word(word)); \
7446 memcpy(dst + off, &word, 8); \
7448 for (; off < len; off++) dst[off] = (expr_byte(src[off])); \
7451#define STR_DEFINE_BINARY_BITWISE_KERNEL(name, expr_word, expr_byte) \
7453 name(unsigned char *dst, const unsigned char *lhs, \
7454 const unsigned char *rhs, long len) \
7457 long unrolled_end = len & ~31L; \
7458 long aligned_end = len & ~7L; \
7459 for (; off < unrolled_end; off += 32) { \
7460 uint64_t l0, l1, l2, l3, r0, r1, r2, r3; \
7461 memcpy(&l0, lhs + off, 8); memcpy(&r0, rhs + off, 8); \
7462 memcpy(&l1, lhs + off + 8, 8); memcpy(&r1, rhs + off + 8, 8); \
7463 memcpy(&l2, lhs + off + 16, 8); memcpy(&r2, rhs + off + 16, 8); \
7464 memcpy(&l3, lhs + off + 24, 8); memcpy(&r3, rhs + off + 24, 8); \
7465 l0 = expr_word(l0, r0); \
7466 l1 = expr_word(l1, r1); \
7467 l2 = expr_word(l2, r2); \
7468 l3 = expr_word(l3, r3); \
7469 memcpy(dst + off, &l0, 8); \
7470 memcpy(dst + off + 8, &l1, 8); \
7471 memcpy(dst + off + 16, &l2, 8); \
7472 memcpy(dst + off + 24, &l3, 8); \
7474 for (; off < aligned_end; off += 8) { \
7475 uint64_t lhs_word, rhs_word; \
7476 memcpy(&lhs_word, lhs + off, 8); \
7477 memcpy(&rhs_word, rhs + off, 8); \
7478 lhs_word = expr_word(lhs_word, rhs_word); \
7479 memcpy(dst + off, &lhs_word, 8); \
7481 for (; off < len; off++) dst[off] = expr_byte(lhs[off], rhs[off]); \
7484#define STR_BITWISE_NOT_WORD(x) (~(x))
7485#define STR_BITWISE_NOT_BYTE(x) ((unsigned char)~(x))
7486#define STR_BITWISE_AND_WORD(x, y) ((x) & (y))
7487#define STR_BITWISE_AND_BYTE(x, y) ((unsigned char)((x) & (y)))
7488#define STR_BITWISE_OR_WORD(x, y) ((x) | (y))
7489#define STR_BITWISE_OR_BYTE(x, y) ((unsigned char)((x) | (y)))
7490#define STR_BITWISE_XOR_WORD(x, y) ((x) ^ (y))
7491#define STR_BITWISE_XOR_BYTE(x, y) ((unsigned char)((x) ^ (y)))
7493STR_DEFINE_UNARY_BITWISE_KERNEL(str_bitwise_not, STR_BITWISE_NOT_WORD, STR_BITWISE_NOT_BYTE)
7494STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_and, STR_BITWISE_AND_WORD, STR_BITWISE_AND_BYTE)
7495STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_or, STR_BITWISE_OR_WORD, STR_BITWISE_OR_BYTE)
7496STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_xor, STR_BITWISE_XOR_WORD, STR_BITWISE_XOR_BYTE)
7506rb_str_bitwise_not(
VALUE str)
7508 long len = RSTRING_LEN(str);
7509 VALUE result = str_bitwise_result(str);
7510 str_bitwise_not((
unsigned char *)RSTRING_PTR(result),
7511 (
const unsigned char *)RSTRING_PTR(str),
len);
7523rb_str_bitwise_not_bang(
VALUE str)
7529 len = RSTRING_LEN(str);
7530 ptr = (
unsigned char *)RSTRING_PTR(str);
7531 str_bitwise_not(ptr, ptr,
len);
7535#define STR_DEFINE_BINARY_BITWISE_METHOD(name) \
7537 rb_str_bitwise_##name(VALUE str, VALUE other) \
7541 StringValue(other); \
7542 str_check_bitwise_length(str, other); \
7543 len = RSTRING_LEN(str); \
7544 result = str_bitwise_result(str); \
7545 str_bitwise_##name((unsigned char *)RSTRING_PTR(result), \
7546 (const unsigned char *)RSTRING_PTR(str), \
7547 (const unsigned char *)RSTRING_PTR(other), len); \
7551 rb_str_bitwise_##name##_bang(VALUE str, VALUE other) \
7554 unsigned char *ptr; \
7555 StringValue(other); \
7556 str_check_bitwise_length(str, other); \
7557 rb_str_modify(str); \
7558 len = RSTRING_LEN(str); \
7559 ptr = (unsigned char *)RSTRING_PTR(str); \
7560 str_bitwise_##name(ptr, ptr, \
7561 (const unsigned char *)RSTRING_PTR(other), len); \
7565STR_DEFINE_BINARY_BITWISE_METHOD(and)
7566STR_DEFINE_BINARY_BITWISE_METHOD(or)
7567STR_DEFINE_BINARY_BITWISE_METHOD(xor)
7570str_byte_substr(
VALUE str,
long beg,
long len,
int empty)
7572 long n = RSTRING_LEN(str);
7574 if (beg > n ||
len < 0)
return Qnil;
7577 if (beg < 0)
return Qnil;
7582 if (!empty)
return Qnil;
7586 VALUE str2 = str_subseq(str, beg,
len);
7588 str_enc_copy_direct(str2, str);
7590 if (RSTRING_LEN(str2) == 0) {
7591 if (!rb_enc_asciicompat(STR_ENC_GET(str)))
7625 long beg,
len = RSTRING_LEN(str);
7633 return str_byte_substr(str, beg,
len, TRUE);
7638 return str_byte_substr(str, idx, 1, FALSE);
7650rb_str_byteslice(
int argc,
VALUE *argv,
VALUE str)
7655 return str_byte_substr(str, beg,
len, TRUE);
7658 return str_byte_aref(str, argv[0]);
7662str_check_beg_len(
VALUE str,
long *beg,
long *
len)
7664 long end, slen = RSTRING_LEN(str);
7667 if ((slen < *beg) || ((*beg < 0) && (*beg + slen < 0))) {
7676 if (*
len > slen - *beg) {
7680 str_ensure_byte_pos(str, *beg);
7681 str_ensure_byte_pos(str, end);
7695rb_str_bytesplice(
int argc,
VALUE *argv,
VALUE str)
7697 long beg,
len, vbeg, vlen;
7702 if (!(argc == 2 || argc == 3 || argc == 5)) {
7703 rb_raise(rb_eArgError,
"wrong number of arguments (given %d, expected 2, 3, or 5)", argc);
7707 rb_raise(
rb_eTypeError,
"wrong argument type %s (expected Range)",
7708 rb_builtin_class_name(argv[0]));
7715 vlen = RSTRING_LEN(val);
7720 rb_raise(
rb_eTypeError,
"wrong argument type %s (expected Range)",
7721 rb_builtin_class_name(argv[2]));
7733 vlen = RSTRING_LEN(val);
7741 str_check_beg_len(str, &beg, &
len);
7742 str_check_beg_len(val, &vbeg, &vlen);
7743 str_modify_keep_cr(str);
7746 rb_enc_associate(str, rb_enc_check(str, val));
7749 rb_str_update_1(str, beg,
len, val, vbeg, vlen);
7771rb_str_reverse(
VALUE str)
7778 if (RSTRING_LEN(str) <= 1)
return str_duplicate(
rb_cString, str);
7779 enc = STR_ENC_GET(str);
7785 if (RSTRING_LEN(str) > 1) {
7786 if (single_byte_optimizable(str)) {
7793 int clen = rb_enc_fast_mbclen(s, e, enc);
7801 cr = rb_enc_asciicompat(enc) ?
7804 int clen = rb_enc_mbclen(s, e, enc);
7813 STR_SET_LEN(rev, RSTRING_LEN(str));
7814 str_enc_copy_direct(rev, str);
7836rb_str_reverse_bang(
VALUE str)
7838 if (RSTRING_LEN(str) > 1) {
7839 if (single_byte_optimizable(str)) {
7842 str_modify_keep_cr(str);
7843 s = RSTRING_PTR(str);
7852 str_shared_replace(str, rb_str_reverse(str));
7856 str_modify_keep_cr(str);
7885 i = rb_str_index(str, arg, 0);
7887 return RBOOL(i != -1);
7931 rb_raise(rb_eArgError,
"invalid radix %d", base);
7933 return rb_str_to_inum(str, base, FALSE);
7958rb_str_to_f(
VALUE str)
7975rb_str_to_s(
VALUE str)
7987 char s[RUBY_MAX_CHAR_LEN];
7988 int n = rb_enc_codelen(c, enc);
7990 rb_enc_mbcput(c, s, enc);
7995#define CHAR_ESC_LEN 13
7998rb_str_buf_cat_escaped_char(
VALUE result,
unsigned int c,
int unicode_p)
8000 char buf[CHAR_ESC_LEN + 1];
8008 snprintf(buf, CHAR_ESC_LEN,
"%c", c);
8010 else if (c < 0x10000) {
8011 snprintf(buf, CHAR_ESC_LEN,
"\\u%04X", c);
8014 snprintf(buf, CHAR_ESC_LEN,
"\\u{%X}", c);
8019 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", c);
8022 snprintf(buf, CHAR_ESC_LEN,
"\\x{%X}", c);
8025 l = (int)strlen(buf);
8031ruby_escaped_char(
int c)
8034 case '\0':
return "\\0";
8035 case '\n':
return "\\n";
8036 case '\r':
return "\\r";
8037 case '\t':
return "\\t";
8038 case '\f':
return "\\f";
8039 case '\013':
return "\\v";
8040 case '\010':
return "\\b";
8041 case '\007':
return "\\a";
8042 case '\033':
return "\\e";
8043 case '\x7f':
return "\\c?";
8049rb_str_escape(
VALUE str)
8053 const char *p = RSTRING_PTR(str);
8055 const char *prev = p;
8056 char buf[CHAR_ESC_LEN + 1];
8058 int unicode_p = rb_enc_unicode_p(enc);
8059 int asciicompat = rb_enc_asciicompat(enc);
8064 int n = rb_enc_precise_mbclen(p, pend, enc);
8066 if (p > prev) str_buf_cat(result, prev, p - prev);
8067 n = rb_enc_mbminlen(enc);
8069 n = (int)(pend - p);
8071 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", *p & 0377);
8072 str_buf_cat(result, buf, strlen(buf));
8078 c = rb_enc_mbc_to_codepoint(p, pend, enc);
8080 cc = ruby_escaped_char(c);
8082 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
8083 str_buf_cat(result, cc, strlen(cc));
8086 else if (asciicompat && rb_enc_isascii(c, enc) &&
ISPRINT(c)) {
8089 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
8090 rb_str_buf_cat_escaped_char(result, c, unicode_p);
8094 if (p > prev) str_buf_cat(result, prev, p - prev);
8104static const bool inspect_no_escape[256] = {
8105 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8106 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8107 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
8108 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
8109 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
8110 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
8111 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
8112 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
8128 const char *p, *pend, *prev;
8129 char buf[CHAR_ESC_LEN + 1];
8131 rb_encoding *resenc = rb_default_internal_encoding();
8132 int unicode_p = rb_enc_unicode_p(enc);
8133 int asciicompat = rb_enc_asciicompat(enc);
8134 int cr = rb_enc_str_coderange(str);
8136 if (resenc == NULL) resenc = rb_default_external_encoding();
8137 if (!rb_enc_asciicompat(resenc)) resenc = rb_usascii_encoding();
8138 rb_enc_associate(result, resenc);
8139 str_buf_cat2(result,
"\"");
8152 while (p < pend && inspect_no_escape[(
unsigned char)*p]) p++;
8153 if (p >= pend)
break;
8156 n = rb_enc_precise_mbclen(p, pend, enc);
8158 if (p > prev) str_buf_cat(result, prev, p - prev);
8159 n = rb_enc_mbminlen(enc);
8161 n = (int)(pend - p);
8163 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", *p & 0377);
8164 str_buf_cat(result, buf, strlen(buf));
8170 c = rb_enc_mbc_to_codepoint(p, pend, enc);
8172 if ((asciicompat || unicode_p) &&
8173 (c ==
'"'|| c ==
'\\' ||
8178 (cc ==
'$' || cc ==
'@' || cc ==
'{'))))) {
8179 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
8180 str_buf_cat2(result,
"\\");
8181 if (asciicompat || enc == resenc) {
8187 case '\n': cc =
'n';
break;
8188 case '\r': cc =
'r';
break;
8189 case '\t': cc =
't';
break;
8190 case '\f': cc =
'f';
break;
8191 case '\013': cc =
'v';
break;
8192 case '\010': cc =
'b';
break;
8193 case '\007': cc =
'a';
break;
8194 case 033: cc =
'e';
break;
8195 default: cc = 0;
break;
8198 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
8201 str_buf_cat(result, buf, 2);
8214 (asciicompat && rb_enc_isascii(c, enc) &&
ISPRINT(c))) {
8218 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
8219 rb_str_buf_cat_escaped_char(result, c, unicode_p);
8224 if (p > prev) str_buf_cat(result, prev, p - prev);
8225 str_buf_cat2(result,
"\"");
8230#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
8243 int encidx = rb_enc_get_index(str);
8246 const char *p, *pend;
8249 int u8 = (encidx == rb_utf8_encindex());
8250 static const char nonascii_suffix[] =
".dup.force_encoding(\"%s\")";
8253 if (!rb_enc_asciicompat(enc)) {
8255 len += strlen(enc->name);
8258 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
8261 unsigned char c = *p++;
8264 case '"':
case '\\':
8265 case '\n':
case '\r':
8266 case '\t':
case '\f':
8267 case '\013':
case '\010':
case '\007':
case '\033':
8272 clen = IS_EVSTR(p, pend) ? 2 : 1;
8280 if (u8 && c > 0x7F) {
8281 int n = rb_enc_precise_mbclen(p-1, pend, enc);
8283 unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
8286 else if (cc <= 0xFFFFF)
8299 if (clen > LONG_MAX -
len) {
8306 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
8307 q = RSTRING_PTR(result); qend = q +
len + 1;
8311 unsigned char c = *p++;
8313 if (c ==
'"' || c ==
'\\') {
8317 else if (c ==
'#') {
8318 if (IS_EVSTR(p, pend)) *q++ =
'\\';
8321 else if (c ==
'\n') {
8325 else if (c ==
'\r') {
8329 else if (c ==
'\t') {
8333 else if (c ==
'\f') {
8337 else if (c ==
'\013') {
8341 else if (c ==
'\010') {
8345 else if (c ==
'\007') {
8349 else if (c ==
'\033') {
8359 int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
8361 int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
8364 snprintf(q, qend-q,
"u%04X", cc);
8366 snprintf(q, qend-q,
"u{%X}", cc);
8371 snprintf(q, qend-q,
"x%02X", c);
8377 if (!rb_enc_asciicompat(enc)) {
8378 snprintf(q, qend-q, nonascii_suffix, enc->name);
8379 encidx = rb_ascii8bit_encindex();
8382 rb_enc_associate_index(result, encidx);
8388unescape_ascii(
unsigned int c)
8412undump_after_backslash(
VALUE undumped,
const char **ss,
const char *s_end,
rb_encoding **penc,
bool *utf8,
bool *binary)
8414 const char *s = *ss;
8418 unsigned char buf[6];
8436 *buf = unescape_ascii(*s);
8448 if (enc_utf8 == NULL) enc_utf8 = rb_utf8_encoding();
8449 if (*penc != enc_utf8) {
8451 rb_enc_associate(undumped, enc_utf8);
8468 if (hexlen == 0 || hexlen > 6) {
8474 if (0xd800 <= c && c <= 0xdfff) {
8477 codelen = rb_enc_mbcput(c, (
char *)buf, *penc);
8487 if (0xd800 <= c && c <= 0xdfff) {
8490 codelen = rb_enc_mbcput(c, (
char *)buf, *penc);
8520static VALUE rb_str_is_ascii_only_p(
VALUE str);
8532str_undump(
VALUE str)
8534 const char *s = RSTRING_PTR(str);
8537 VALUE undumped = rb_enc_str_new(s, 0L, enc);
8539 bool binary =
false;
8543 if (rb_str_is_ascii_only_p(str) ==
Qfalse) {
8546 if (!str_null_check(str, &w)) {
8549 if (RSTRING_LEN(str) < 2)
goto invalid_format;
8550 if (*s !=
'"')
goto invalid_format;
8568 static const char force_encoding_suffix[] =
".force_encoding(\"";
8569 static const char dup_suffix[] =
".dup";
8570 const char *encname;
8575 size =
sizeof(dup_suffix) - 1;
8576 if (s_end - s > size && memcmp(s, dup_suffix, size) == 0) s += size;
8578 size =
sizeof(force_encoding_suffix) - 1;
8579 if (s_end - s <= size)
goto invalid_format;
8580 if (memcmp(s, force_encoding_suffix, size) != 0)
goto invalid_format;
8584 rb_raise(
rb_eRuntimeError,
"dumped string contained Unicode escape but used force_encoding");
8588 s = memchr(s,
'"', s_end-s);
8590 if (!s)
goto invalid_format;
8591 if (s_end - s != 2)
goto invalid_format;
8592 if (s[0] !=
'"' || s[1] !=
')')
goto invalid_format;
8594 encidx = rb_enc_find_index2(encname, (
long)size);
8598 rb_enc_associate_index(undumped, encidx);
8608 undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
8619 rb_raise(
rb_eRuntimeError,
"invalid dumped string; not wrapped with '\"' nor '\"...\".force_encoding(\"...\")' form");
8625 if (rb_enc_dummy_p(enc)) {
8632str_true_enc(
VALUE str)
8635 rb_str_check_dummy_enc(enc);
8639static OnigCaseFoldType
8640check_case_options(
int argc,
VALUE *argv, OnigCaseFoldType flags)
8645 rb_raise(rb_eArgError,
"too many options");
8646 if (argv[0]==sym_turkic) {
8647 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
8649 if (argv[1]==sym_lithuanian)
8650 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
8652 rb_raise(rb_eArgError,
"invalid second option");
8655 else if (argv[0]==sym_lithuanian) {
8656 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
8658 if (argv[1]==sym_turkic)
8659 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
8661 rb_raise(rb_eArgError,
"invalid second option");
8665 rb_raise(rb_eArgError,
"too many options");
8666 else if (argv[0]==sym_ascii)
8667 flags |= ONIGENC_CASE_ASCII_ONLY;
8668 else if (argv[0]==sym_fold) {
8669 if ((flags & (ONIGENC_CASE_UPCASE|ONIGENC_CASE_DOWNCASE)) == ONIGENC_CASE_DOWNCASE)
8670 flags ^= ONIGENC_CASE_FOLD|ONIGENC_CASE_DOWNCASE;
8672 rb_raise(rb_eArgError,
"option :fold only allowed for downcasing");
8675 rb_raise(rb_eArgError,
"invalid option");
8682 if ((flags & ONIGENC_CASE_ASCII_ONLY) && (enc==rb_utf8_encoding() ||
rb_enc_mbmaxlen(enc) == 1))
8684 return !(flags & ONIGENC_CASE_FOLD_TURKISH_AZERI) &&
8689#define CASE_MAPPING_ADDITIONAL_LENGTH 20
8690#ifndef CASEMAP_DEBUG
8691# define CASEMAP_DEBUG 0
8699 OnigUChar space[FLEX_ARY_LEN];
8703mapping_buffer_free(
void *p)
8707 while (current_buffer) {
8708 previous_buffer = current_buffer;
8709 current_buffer = current_buffer->next;
8710 ruby_xfree_sized(previous_buffer, offsetof(
mapping_buffer, space) + previous_buffer->capa);
8716 {0, mapping_buffer_free,},
8717 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED
8725 const OnigUChar *source_current, *source_end;
8726 int target_length = 0;
8727 VALUE buffer_anchor;
8730 size_t buffer_count = 0;
8731 int buffer_length_or_invalid;
8733 if (RSTRING_LEN(source) == 0)
return str_duplicate(
rb_cString, source);
8735 source_current = (OnigUChar*)RSTRING_PTR(source);
8740 while (source_current < source_end) {
8742 size_t capa = (size_t)(source_end-source_current)*++buffer_count + CASE_MAPPING_ADDITIONAL_LENGTH;
8743 if (CASEMAP_DEBUG) {
8744 fprintf(stderr,
"Buffer allocation, capa is %"PRIuSIZE
"\n",
capa);
8747 *pre_buffer = current_buffer;
8748 pre_buffer = ¤t_buffer->next;
8749 current_buffer->next = NULL;
8750 current_buffer->capa =
capa;
8751 buffer_length_or_invalid = enc->case_map(flags,
8752 &source_current, source_end,
8753 current_buffer->space,
8754 current_buffer->space+current_buffer->capa,
8756 if (buffer_length_or_invalid < 0) {
8757 current_buffer =
DATA_PTR(buffer_anchor);
8759 mapping_buffer_free(current_buffer);
8760 rb_raise(rb_eArgError,
"input string invalid");
8762 target_length += current_buffer->used = buffer_length_or_invalid;
8764 if (CASEMAP_DEBUG) {
8765 fprintf(stderr,
"Buffer count is %"PRIuSIZE
"\n", buffer_count);
8768 if (buffer_count==1) {
8769 target =
rb_str_new((
const char*)current_buffer->space, target_length);
8772 char *target_current;
8775 target_current = RSTRING_PTR(target);
8776 current_buffer =
DATA_PTR(buffer_anchor);
8777 while (current_buffer) {
8778 memcpy(target_current, current_buffer->space, current_buffer->used);
8779 target_current += current_buffer->used;
8780 current_buffer = current_buffer->next;
8783 current_buffer =
DATA_PTR(buffer_anchor);
8785 mapping_buffer_free(current_buffer);
8790 str_enc_copy_direct(target, source);
8799 const OnigUChar *source_current, *source_end;
8800 OnigUChar *target_current, *target_end;
8801 long old_length = RSTRING_LEN(source);
8802 int length_or_invalid;
8804 if (old_length == 0)
return Qnil;
8806 source_current = (OnigUChar*)RSTRING_PTR(source);
8808 if (source == target) {
8809 target_current = (OnigUChar*)source_current;
8810 target_end = (OnigUChar*)source_end;
8813 target_current = (OnigUChar*)RSTRING_PTR(target);
8817 length_or_invalid = onigenc_ascii_only_case_map(flags,
8818 &source_current, source_end,
8819 target_current, target_end, enc);
8820 if (length_or_invalid < 0)
8821 rb_raise(rb_eArgError,
"input string invalid");
8822 if (CASEMAP_DEBUG && length_or_invalid != old_length) {
8823 fprintf(stderr,
"problem with rb_str_ascii_casemap"
8824 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
8825 rb_raise(rb_eArgError,
"internal problem with rb_str_ascii_casemap"
8826 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
8829 str_enc_copy(target, source);
8835upcase_single(
VALUE str)
8837 char *s = RSTRING_PTR(str), *send =
RSTRING_END(str);
8838 bool modified =
false;
8841 unsigned int c = *(
unsigned char*)s;
8843 if (
'a' <= c && c <=
'z') {
8844 *s =
'A' + (c -
'a');
8865rb_str_upcase_bang(
int argc,
VALUE *argv,
VALUE str)
8868 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
8870 flags = check_case_options(argc, argv, flags);
8871 str_modify_keep_cr(str);
8872 enc = str_true_enc(str);
8873 if (case_option_single_p(flags, enc, str)) {
8874 if (upcase_single(str))
8875 flags |= ONIGENC_CASE_MODIFIED;
8877 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8878 rb_str_ascii_casemap(str, str, &flags, enc);
8880 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8882 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8895rb_str_upcase(
int argc,
VALUE *argv,
VALUE str)
8898 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
8901 flags = check_case_options(argc, argv, flags);
8902 enc = str_true_enc(str);
8903 if (case_option_single_p(flags, enc, str)) {
8904 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8905 str_enc_copy_direct(ret, str);
8908 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8910 rb_str_ascii_casemap(str, ret, &flags, enc);
8913 ret = rb_str_casemap(str, &flags, enc);
8920downcase_single(
VALUE str)
8922 char *s = RSTRING_PTR(str), *send =
RSTRING_END(str);
8923 bool modified =
false;
8926 unsigned int c = *(
unsigned char*)s;
8928 if (
'A' <= c && c <=
'Z') {
8929 *s =
'a' + (c -
'A');
8951rb_str_downcase_bang(
int argc,
VALUE *argv,
VALUE str)
8954 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8956 flags = check_case_options(argc, argv, flags);
8957 str_modify_keep_cr(str);
8958 enc = str_true_enc(str);
8959 if (case_option_single_p(flags, enc, str)) {
8960 if (downcase_single(str))
8961 flags |= ONIGENC_CASE_MODIFIED;
8963 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8964 rb_str_ascii_casemap(str, str, &flags, enc);
8966 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8968 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8982rb_str_downcase(
int argc,
VALUE *argv,
VALUE str)
8985 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8988 flags = check_case_options(argc, argv, flags);
8989 enc = str_true_enc(str);
8990 if (case_option_single_p(flags, enc, str)) {
8991 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8992 str_enc_copy_direct(ret, str);
8993 downcase_single(ret);
8995 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8997 rb_str_ascii_casemap(str, ret, &flags, enc);
9000 ret = rb_str_casemap(str, &flags, enc);
9007capitalize_single(
VALUE str)
9009 char *s = RSTRING_PTR(str), *send =
RSTRING_END(str);
9010 bool modified =
false;
9013 unsigned int c = (
unsigned char)*s;
9015 if (
'a' <= c && c <=
'z') {
9016 *s =
'A' + (c -
'a');
9022 unsigned int c = (
unsigned char)*s;
9024 if (
'A' <= c && c <=
'Z') {
9025 *s =
'a' + (c -
'A');
9047rb_str_capitalize_bang(
int argc,
VALUE *argv,
VALUE str)
9050 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
9052 flags = check_case_options(argc, argv, flags);
9053 str_modify_keep_cr(str);
9054 enc = str_true_enc(str);
9055 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
9056 if (case_option_single_p(flags, enc, str)) {
9057 if (capitalize_single(str))
9058 flags |= ONIGENC_CASE_MODIFIED;
9060 else if (flags&ONIGENC_CASE_ASCII_ONLY)
9061 rb_str_ascii_casemap(str, str, &flags, enc);
9063 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
9065 if (ONIGENC_CASE_MODIFIED&flags)
return str;
9079rb_str_capitalize(
int argc,
VALUE *argv,
VALUE str)
9082 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
9085 flags = check_case_options(argc, argv, flags);
9086 enc = str_true_enc(str);
9087 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return str;
9088 if (case_option_single_p(flags, enc, str)) {
9089 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
9090 str_enc_copy_direct(ret, str);
9091 capitalize_single(ret);
9093 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
9095 rb_str_ascii_casemap(str, ret, &flags, enc);
9098 ret = rb_str_casemap(str, &flags, enc);
9117rb_str_swapcase_bang(
int argc,
VALUE *argv,
VALUE str)
9120 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
9122 flags = check_case_options(argc, argv, flags);
9123 str_modify_keep_cr(str);
9124 enc = str_true_enc(str);
9125 if (flags&ONIGENC_CASE_ASCII_ONLY)
9126 rb_str_ascii_casemap(str, str, &flags, enc);
9128 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
9130 if (ONIGENC_CASE_MODIFIED&flags)
return str;
9144rb_str_swapcase(
int argc,
VALUE *argv,
VALUE str)
9147 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
9150 flags = check_case_options(argc, argv, flags);
9151 enc = str_true_enc(str);
9152 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return str_duplicate(
rb_cString, str);
9153 if (flags&ONIGENC_CASE_ASCII_ONLY) {
9155 rb_str_ascii_casemap(str, ret, &flags, enc);
9158 ret = rb_str_casemap(str, &flags, enc);
9163typedef unsigned char *USTR;
9167 unsigned int now, max;
9168 const char *p, *pend;
9179 if (t->p == t->pend)
return -1;
9180 if (rb_enc_ascget(t->p, t->pend, &n, enc) ==
'\\' && t->p + n < t->pend) {
9183 t->now = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
9185 if (rb_enc_ascget(t->p, t->pend, &n, enc) ==
'-' && t->p + n < t->pend) {
9187 if (t->p < t->pend) {
9188 unsigned int c = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
9191 if (t->now < 0x80 && c < 0x80) {
9192 rb_raise(rb_eArgError,
9193 "invalid range \"%c-%c\" in string transliteration",
9197 rb_raise(rb_eArgError,
"invalid range in string transliteration");
9201 else if (t->now < c) {
9210 while (ONIGENC_CODE_TO_MBCLEN(enc, ++t->now) <= 0) {
9211 if (t->now == t->max) {
9216 if (t->now < t->max) {
9232 const unsigned int errc = -1;
9233 unsigned int trans[256];
9235 struct tr trsrc, trrepl;
9237 unsigned int c, c0, last = 0;
9238 int modify = 0, i, l;
9239 unsigned char *s, *send;
9241 int singlebyte = single_byte_optimizable(str);
9245#define CHECK_IF_ASCII(c) \
9246 (void)((cr == ENC_CODERANGE_7BIT && !rb_isascii(c)) ? \
9247 (cr = ENC_CODERANGE_VALID) : 0)
9251 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
9252 if (RSTRING_LEN(repl) == 0) {
9253 return rb_str_delete_bang(1, &src, str);
9257 e1 = rb_enc_check(str, src);
9258 e2 = rb_enc_check(str, repl);
9263 enc = rb_enc_check(src, repl);
9265 trsrc.p = RSTRING_PTR(src); trsrc.pend = trsrc.p + RSTRING_LEN(src);
9266 if (RSTRING_LEN(src) > 1 &&
9267 rb_enc_ascget(trsrc.p, trsrc.pend, &l, enc) ==
'^' &&
9268 trsrc.p + l < trsrc.pend) {
9272 trrepl.p = RSTRING_PTR(repl);
9273 trrepl.pend = trrepl.p + RSTRING_LEN(repl);
9274 trsrc.gen = trrepl.gen = 0;
9275 trsrc.now = trrepl.now = 0;
9276 trsrc.max = trrepl.max = 0;
9279 for (i=0; i<256; i++) {
9282 while ((c = trnext(&trsrc, enc)) != errc) {
9287 if (!hash) hash = rb_hash_new();
9291 while ((c = trnext(&trrepl, enc)) != errc)
9294 for (i=0; i<256; i++) {
9295 if (trans[i] != errc) {
9303 for (i=0; i<256; i++) {
9306 while ((c = trnext(&trsrc, enc)) != errc) {
9307 r = trnext(&trrepl, enc);
9308 if (r == errc) r = trrepl.now;
9311 if (rb_enc_codelen(r, enc) != 1) singlebyte = 0;
9314 if (!hash) hash = rb_hash_new();
9322 str_modify_keep_cr(str);
9323 s = (
unsigned char *)RSTRING_PTR(str); send = (
unsigned char *)
RSTRING_END(str);
9324 termlen = rb_enc_mbminlen(enc);
9327 long offset, max = RSTRING_LEN(str);
9328 unsigned int save = -1;
9329 unsigned char *buf =
ALLOC_N(
unsigned char, max + termlen), *t = buf;
9334 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
9336 SIZED_FREE_N(buf, max + termlen);
9337 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
9340 c0 = c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
9342 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9351 if (cflag) c = last;
9354 else if (cflag) c = errc;
9360 if (c != (
unsigned int)-1) {
9366 tlen = rb_enc_codelen(c, enc);
9372 if (enc != e1) may_modify = 1;
9374 if ((offset = t - buf) + tlen > max) {
9375 size_t MAYBE_UNUSED(old) = max + termlen;
9376 max = offset + tlen + (send - s);
9377 SIZED_REALLOC_N(buf,
unsigned char, max + termlen, old);
9380 rb_enc_mbcput(c, t, enc);
9381 if (may_modify && memcmp(s, t, tlen) != 0) {
9387 if (!STR_EMBED_P(str)) {
9388 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9390 TERM_FILL((
char *)t, termlen);
9391 RSTRING(str)->as.heap.ptr = (
char *)buf;
9392 STR_SET_LEN(str, t - buf);
9393 STR_SET_NOEMBED(str);
9394 RSTRING(str)->as.heap.aux.capa = max;
9398 c = (
unsigned char)*s;
9399 if (trans[c] != errc) {
9416 long offset, max = (long)((send - s) * 1.2);
9417 unsigned char *buf =
ALLOC_N(
unsigned char, max + termlen), *t = buf;
9422 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
9424 SIZED_FREE_N(buf, max + termlen);
9425 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
9428 c0 = c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
9430 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9438 if (cflag) c = last;
9441 else if (cflag) c = errc;
9445 c = cflag ? last : errc;
9448 tlen = rb_enc_codelen(c, enc);
9453 if (enc != e1) may_modify = 1;
9455 if ((offset = t - buf) + tlen > max) {
9456 size_t MAYBE_UNUSED(old) = max + termlen;
9457 max = offset + tlen + (long)((send - s) * 1.2);
9458 SIZED_REALLOC_N(buf,
unsigned char, max + termlen, old);
9462 rb_enc_mbcput(c, t, enc);
9463 if (may_modify && memcmp(s, t, tlen) != 0) {
9470 if (!STR_EMBED_P(str)) {
9471 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9473 TERM_FILL((
char *)t, termlen);
9474 RSTRING(str)->as.heap.ptr = (
char *)buf;
9475 STR_SET_LEN(str, t - buf);
9476 STR_SET_NOEMBED(str);
9477 RSTRING(str)->as.heap.aux.capa = max;
9483 rb_enc_associate(str, enc);
9493 size_t initial_capa;
9497tr_buffer_init(
struct tr_buffer *buffer,
size_t initial_capa)
9499 if (initial_capa < 32) {
9502 *buffer = (
struct tr_buffer){ .initial_capa = initial_capa };
9506tr_buffer_ensure_capa(
struct tr_buffer *buffer,
size_t extra_capa)
9508 size_t offset = buffer->ptr - buffer->buf;
9509 size_t required_capa = offset + extra_capa;
9510 if (UNLIKELY(buffer->capa < required_capa)) {
9511 size_t new_capa = buffer->capa ? buffer->capa : buffer->initial_capa;
9513 while (new_capa < required_capa) {
9514 new_capa = (size_t)(new_capa * 1.2);
9516 SIZED_REALLOC_N(buffer->buf,
unsigned char, new_capa, buffer->capa);
9517 buffer->ptr = buffer->buf + offset;
9518 buffer->capa = new_capa;
9523tr_buffer_append(
struct tr_buffer *buffer,
const unsigned char *ptr,
size_t len)
9526 tr_buffer_ensure_capa(buffer,
len);
9527 memcpy(buffer->ptr, ptr,
len);
9535 tr_buffer_append(buffer, (
unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str));
9541 tr_buffer_ensure_capa(buffer, 4);
9542 buffer->ptr += rb_enc_mbcput(codepoint, buffer->ptr, enc);
9549 SIZED_FREE_N(buffer->buf, buffer->capa);
9566tr_trans_pairs_coerce_i(st_data_t key, st_data_t value, st_data_t _args)
9569 struct tr_pair *pair = &args->pairs[args->index];
9577 if (RSTRING_LEN(search) != 1 && str_strlen(search, NULL) != 1) {
9578 rb_raise(rb_eArgError,
"keys must be of size 1");
9581 args->enc = rb_enc_check_multi_str(args->enc, &args->cr, search);
9582 args->enc = rb_enc_check_multi_str(args->enc, &args->cr, replace);
9584 pair->search = search;
9585 pair->replace = replace;
9589#define TR_TRANS_PAIRS_SIMD_MAX_NEEDLES 16
9592 const unsigned char *s;
9593 const unsigned char *send;
9596 unsigned char needles[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9598#ifdef HAVE_SIMD_NEON
9599 uint64_t matches_bitmap;
9601#ifdef HAVE_SIMD_SSE2
9606 VALUE trans_table[256];
9612 while (search->s < search->send) {
9613 VALUE repl = search->trans_table[*search->s];
9614 if (UNLIKELY(repl)) {
9624#ifdef HAVE_SIMD_SSE2
9629 size_t trailing_zeros = (size_t)ntz_int32(search->matches_bitmap);
9631 RUBY_ASSERT(trailing_zeros < (
sizeof(search->matches_bitmap) * CHAR_BIT));
9632 search->matches_bitmap >>= trailing_zeros;
9633 search->s += trailing_zeros;
9636 return search->trans_table[*search->s];
9642 if (search->needles_count) {
9646 if (search->matches_bitmap) {
9647 return tr_trans_pairs_next_match_sse2(search);
9650 if ((
size_t)(search->send - search->s) >=
sizeof(__m128i)) {
9652 __m128i masks[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9653 for (i = 0; i < search->needles_count; i++) {
9654 masks[i] = _mm_set1_epi8(search->needles[i]);
9658 const __m128i bytes = _mm_loadu_si128((__m128i
const *)search->s);
9660 __m128i matches[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9661 for (i = 0; i < search->needles_count; i++) {
9662 matches[i] = _mm_cmpeq_epi8(bytes, masks[i]);
9665 for (i = 1; i < search->needles_count; i++) {
9666 matches[0] = _mm_or_si128(matches[0], matches[i]);
9669 const int bitmap = _mm_movemask_epi8(matches[0]);
9672 search->matches_bitmap = bitmap;
9673 return tr_trans_pairs_next_match_sse2(search);
9675 search->s +=
sizeof(__m128i);
9676 }
while ((
size_t)(search->send - search->s) >=
sizeof(__m128i));
9679 return tr_trans_pairs_search_basic(search);
9682#define tr_trans_pairs_search_impl tr_trans_pairs_search_sse2
9685#ifdef HAVE_SIMD_NEON
9690 size_t trailing_zeros = (size_t)ntz_int64(search->matches_bitmap);
9693 RUBY_ASSERT(trailing_zeros < (
sizeof(search->matches_bitmap) * CHAR_BIT));
9694 search->matches_bitmap >>= trailing_zeros;
9695 search->s += trailing_zeros / 4;
9698 return search->trans_table[*search->s];
9704 if (search->needles_count) {
9708 if (search->matches_bitmap) {
9709 return tr_trans_pairs_next_match_neon(search);
9712 if ((
size_t)(search->send - search->s) >=
sizeof(uint8x16_t)) {
9714 uint8x16_t masks[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9715 for (i = 0; i < search->needles_count; i++) {
9716 masks[i] = vdupq_n_u8(search->needles[i]);
9720 const uint8x16_t bytes = vld1q_u8(search->s);
9722 uint8x16_t matches[TR_TRANS_PAIRS_SIMD_MAX_NEEDLES];
9723 for (i = 0; i < search->needles_count; i++) {
9724 matches[i] = vceqq_u8(bytes, masks[i]);
9727 for (i = 1; i < search->needles_count; i++) {
9728 matches[0] = vorrq_u8(matches[0], matches[i]);
9731 const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(matches[0]), 4);
9732 const uint64_t bitmap = vget_lane_u64(vreinterpret_u64_u8(res), 0);
9735 search->matches_bitmap = bitmap & 0x8888888888888888ull;
9736 return tr_trans_pairs_next_match_neon(search);
9738 search->s +=
sizeof(uint8x16_t);
9739 }
while ((
size_t)(search->send - search->s) >=
sizeof(uint8x16_t));
9742 return tr_trans_pairs_search_basic(search);
9745#define tr_trans_pairs_search_impl tr_trans_pairs_search_neon
9748#ifndef tr_trans_pairs_search_impl
9749#define tr_trans_pairs_search_impl tr_trans_pairs_search_basic
9757 search->matches_bitmap >>= 1;
9766 mustnot_broken(str);
9769 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str) || pairs_count == 0)
return Qnil;
9774 int cr = rb_enc_str_coderange(str);
9787 const unsigned char *sstart = (
unsigned char *)RSTRING_PTR(str);
9788 long str_len = RSTRING_LEN(str);
9789 int termlen = rb_enc_mbminlen(e1);
9792 tr_buffer_init(&buffer, str_len);
9793 bool modify =
false;
9795 if (RB_LIKELY(rb_str_encindex_fastpath(rb_enc_to_index(e1)))) {
9799 .send = sstart + str_len,
9802 for (
size_t index = 0; index < pairs_count; index++) {
9803 struct tr_pair *pair = &pairs[index];
9805 char *ptr = RSTRING_PTR(pair->search);
9806 unsigned int codepoint = rb_enc_mbc_to_codepoint(ptr,
RSTRING_END(pair->search), e1);
9808 const unsigned char first_byte = (
unsigned char)*ptr;
9811 if (pairs_count <= TR_TRANS_PAIRS_SIMD_MAX_NEEDLES) {
9812 search.needles[index] = first_byte;
9813 search.needles_count++;
9817 if (rb_enc_codelen(codepoint, e1) == 1) {
9818 search.trans_table[first_byte] = pair->replace;
9821 search.trans_table[first_byte] =
Qundef;
9823 hash =
rb_obj_hide(rb_hash_new_capa(pairs_count));
9825 rb_hash_aset(hash,
UINT2NUM(codepoint), pair->replace);
9829 const unsigned char *checkpoint = search.s;
9831 while ((repl = tr_trans_pairs_search_impl(&search))) {
9834 if (UNLIKELY(repl ==
Qundef)) {
9835 unsigned int c = rb_enc_mbc_to_codepoint((
char *)search.s, (
char *)search.send, e1);
9836 clen = rb_enc_codelen(c, e1);
9837 repl = rb_hash_lookup2(hash,
UINT2NUM(c), 0);
9839 tr_trans_pairs_consume_match(&search);
9847 if (checkpoint < search.s) {
9848 tr_buffer_append(&buffer, checkpoint, search.s - checkpoint);
9850 tr_buffer_append_str(&buffer, repl);
9851 checkpoint = search.s + clen;
9852 tr_trans_pairs_consume_match(&search);
9859 if (modify && checkpoint < search.s) {
9860 tr_buffer_append(&buffer, checkpoint, search.s - checkpoint);
9864 const unsigned char *s = sstart;
9865 const unsigned char *send = sstart + str_len;
9867 hash =
rb_obj_hide(rb_hash_new_capa(pairs_count));
9869 for (
size_t index = 0; index < pairs_count; index++) {
9870 struct tr_pair *pair = &pairs[index];
9872 unsigned int codepoint = rb_enc_mbc_to_codepoint(RSTRING_PTR(pair->search),
RSTRING_END(pair->search), e1);
9873 rb_hash_aset(hash,
UINT2NUM(codepoint), pair->replace);
9877 bool may_modify =
false;
9879 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
9881 tr_buffer_free(&buffer);
9882 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
9885 unsigned int c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
9886 unsigned int c0 = c;
9888 long tlen = enc == e1 ? clen : rb_enc_codelen(c, e1);
9891 if (
NIL_P(replacement)) {
9892 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9894 if (enc != e1) may_modify =
true;
9897 tlen = RSTRING_LEN(replacement);
9901 if (
NIL_P(replacement)) {
9902 tr_buffer_mbcput(&buffer, c, enc);
9905 tr_buffer_append_str(&buffer, replacement);
9908 if (may_modify && memcmp(s, buffer.ptr - tlen, tlen) != 0) {
9924 if (!STR_EMBED_P(str)) {
9925 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9927 tr_buffer_ensure_capa(&buffer, termlen);
9928 TERM_FILL((
char *)buffer.ptr, termlen);
9929 RSTRING(str)->as.heap.ptr = (
char *)buffer.buf;
9930 STR_SET_LEN(str, buffer.ptr - buffer.buf);
9931 STR_SET_NOEMBED(str);
9932 RSTRING(str)->as.heap.aux.capa = buffer.capa - termlen;
9938 rb_enc_associate(str, e1);
9956rb_str_tr_bang(
int argc,
VALUE *argv,
VALUE str)
9961 VALUE pairs = argv[0];
9962 return tr_trans_pairs(str, pairs);
9965 VALUE src = argv[0], repl = argv[1];
9966 return tr_trans(str, src, repl, 0);
10030 VALUE pairs = argv[0];
10031 VALUE result = tr_trans_pairs(str, pairs);
10032 if (
NIL_P(result)) result = str;
10036 VALUE src = argv[0], repl = argv[1];
10037 tr_trans(str, src, repl, 0);
10041#define TR_TABLE_MAX (UCHAR_MAX+1)
10042#define TR_TABLE_SIZE (TR_TABLE_MAX+1)
10044tr_setup_table(
VALUE str,
char stable[TR_TABLE_SIZE],
int first,
10047 const unsigned int errc = -1;
10048 char buf[TR_TABLE_MAX];
10051 VALUE table = 0, ptable = 0;
10052 int i, l, cflag = 0;
10054 tr.p = RSTRING_PTR(str);
tr.pend =
tr.p + RSTRING_LEN(str);
10055 tr.gen =
tr.now =
tr.max = 0;
10057 if (RSTRING_LEN(str) > 1 && rb_enc_ascget(
tr.p,
tr.pend, &l, enc) ==
'^') {
10062 for (i=0; i<TR_TABLE_MAX; i++) {
10065 stable[TR_TABLE_MAX] = cflag;
10067 else if (stable[TR_TABLE_MAX] && !cflag) {
10068 stable[TR_TABLE_MAX] = 0;
10070 for (i=0; i<TR_TABLE_MAX; i++) {
10074 while ((c = trnext(&
tr, enc)) != errc) {
10075 if (c < TR_TABLE_MAX) {
10076 buf[(
unsigned char)c] = !cflag;
10081 if (!table && (first || *tablep || stable[TR_TABLE_MAX])) {
10084 table = ptable ? ptable : rb_hash_new();
10088 table = rb_hash_new();
10093 if (table && (!ptable || (cflag ^ !
NIL_P(rb_hash_aref(ptable, key))))) {
10094 rb_hash_aset(table, key,
Qtrue);
10098 for (i=0; i<TR_TABLE_MAX; i++) {
10099 stable[i] = stable[i] && buf[i];
10101 if (!table && !cflag) {
10108tr_find(
unsigned int c,
const char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
10110 if (c < TR_TABLE_MAX) {
10111 return table[c] != 0;
10117 if (!
NIL_P(rb_hash_lookup(del, v)) &&
10118 (!nodel ||
NIL_P(rb_hash_lookup(nodel, v)))) {
10122 else if (nodel && !
NIL_P(rb_hash_lookup(nodel, v))) {
10125 return table[TR_TABLE_MAX] ? TRUE : FALSE;
10140rb_str_delete_bang(
int argc,
VALUE *argv,
VALUE str)
10142 char squeez[TR_TABLE_SIZE];
10144 char *s, *send, *t;
10145 VALUE del = 0, nodel = 0;
10147 int i, ascompat, cr;
10149 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
10151 for (i=0; i<argc; i++) {
10155 enc = rb_enc_check(str, s);
10156 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
10159 str_modify_keep_cr(str);
10160 ascompat = rb_enc_asciicompat(enc);
10161 s = t = RSTRING_PTR(str);
10168 if (ascompat && (c = *(
unsigned char*)s) < 0x80) {
10173 if (t != s) *t = c;
10179 c = rb_enc_codepoint_len(s, send, &clen, enc);
10181 if (tr_find(c, squeez, del, nodel)) {
10185 if (t != s) rb_enc_mbcput(c, t, enc);
10192 TERM_FILL(t, TERM_LEN(str));
10193 STR_SET_LEN(str, t - RSTRING_PTR(str));
10196 if (modify)
return str;
10210rb_str_delete(
int argc,
VALUE *argv,
VALUE str)
10213 rb_str_delete_bang(argc, argv, str);
10231rb_str_squeeze_bang(
int argc,
VALUE *argv,
VALUE str)
10233 char squeez[TR_TABLE_SIZE];
10235 VALUE del = 0, nodel = 0;
10236 unsigned char *s, *send, *t;
10238 int ascompat, singlebyte = single_byte_optimizable(str);
10242 enc = STR_ENC_GET(str);
10245 for (i=0; i<argc; i++) {
10249 enc = rb_enc_check(str, s);
10250 if (singlebyte && !single_byte_optimizable(s))
10252 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
10256 str_modify_keep_cr(str);
10257 s = t = (
unsigned char *)RSTRING_PTR(str);
10258 if (!s || RSTRING_LEN(str) == 0)
return Qnil;
10261 ascompat = rb_enc_asciicompat(enc);
10265 unsigned int c = *s++;
10266 if (c != save || (argc > 0 && !squeez[c])) {
10276 if (ascompat && (c = *s) < 0x80) {
10277 if (c != save || (argc > 0 && !squeez[c])) {
10283 c = rb_enc_codepoint_len((
char *)s, (
char *)send, &clen, enc);
10285 if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
10286 if (t != s) rb_enc_mbcput(c, t, enc);
10295 TERM_FILL((
char *)t, TERM_LEN(str));
10296 if ((
char *)t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
10297 STR_SET_LEN(str, (
char *)t - RSTRING_PTR(str));
10301 if (modify)
return str;
10315rb_str_squeeze(
int argc,
VALUE *argv,
VALUE str)
10318 rb_str_squeeze_bang(argc, argv, str);
10338 return tr_trans(str, src, repl, 1);
10366 tr_trans(str, src, repl, 1);
10379rb_str_count(
int argc,
VALUE *argv,
VALUE str)
10381 char table[TR_TABLE_SIZE];
10383 VALUE del = 0, nodel = 0, tstr;
10384 const char *s, *send;
10393 enc = rb_enc_check(str, tstr);
10396 if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
10397 (ptstr = RSTRING_PTR(tstr),
10398 ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (
const unsigned char *)ptstr, (
const unsigned char *)ptstr+1)) &&
10399 !is_broken_string(str)) {
10401 unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);
10403 s = RSTRING_PTR(str);
10404 if (!s || RSTRING_LEN(str) == 0)
return INT2FIX(0);
10407 if (*(
unsigned char*)s++ == c) n++;
10413 tr_setup_table(tstr, table, TRUE, &del, &nodel, enc);
10414 for (i=1; i<argc; i++) {
10417 enc = rb_enc_check(str, tstr);
10418 tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
10421 s = RSTRING_PTR(str);
10422 if (!s || RSTRING_LEN(str) == 0)
return INT2FIX(0);
10424 ascompat = rb_enc_asciicompat(enc);
10428 if (ascompat && (c = *(
unsigned char*)s) < 0x80) {
10436 c = rb_enc_codepoint_len(s, send, &clen, enc);
10437 if (tr_find(c, table, del, nodel)) {
10448rb_fs_check(
VALUE val)
10452 if (
NIL_P(val))
return 0;
10457static const char isspacetable[256] = {
10458 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
10459 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10460 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10461 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10462 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10463 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10464 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10465 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10466 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10467 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10468 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10469 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10470 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10471 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10472 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10473 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
10476#define ascii_isspace(c) isspacetable[(unsigned char)(c)]
10479split_string(
VALUE result,
VALUE str,
long beg,
long len,
long empty_count)
10481 if (empty_count >= 0 &&
len == 0) {
10482 return empty_count + 1;
10484 if (empty_count > 0) {
10489 }
while (--empty_count > 0);
10493 rb_yield(str_new_empty_String(str));
10494 }
while (--empty_count > 0);
10504 return empty_count;
10508 SPLIT_TYPE_AWK, SPLIT_TYPE_STRING, SPLIT_TYPE_REGEXP, SPLIT_TYPE_CHARS
10512literal_split_pattern(
VALUE spat, split_type_t default_type)
10520 return SPLIT_TYPE_CHARS;
10522 else if (rb_enc_asciicompat(enc)) {
10523 if (
len == 1 && ptr[0] ==
' ') {
10524 return SPLIT_TYPE_AWK;
10529 if (rb_enc_ascget(ptr, ptr +
len, &l, enc) ==
' ' &&
len == l) {
10530 return SPLIT_TYPE_AWK;
10533 return default_type;
10546rb_str_split_m(
int argc,
VALUE *argv,
VALUE str)
10551 split_type_t split_type;
10552 long beg, end, i = 0, empty_count = -1;
10557 if (
rb_scan_args(argc, argv,
"02", &spat, &limit) == 2) {
10559 if (lim <= 0) limit =
Qnil;
10560 else if (lim == 1) {
10561 if (RSTRING_LEN(str) == 0)
10572 if (
NIL_P(limit) && !lim) empty_count = 0;
10574 enc = STR_ENC_GET(str);
10575 split_type = SPLIT_TYPE_REGEXP;
10576 if (!
NIL_P(spat)) {
10577 spat = get_pat_quoted(spat, 0);
10579 else if (
NIL_P(spat = rb_fs)) {
10580 split_type = SPLIT_TYPE_AWK;
10582 else if (!(spat = rb_fs_check(spat))) {
10583 rb_raise(
rb_eTypeError,
"value of $; must be String or Regexp");
10588 if (split_type != SPLIT_TYPE_AWK) {
10593 split_type = literal_split_pattern(tmp, SPLIT_TYPE_REGEXP);
10594 if (split_type == SPLIT_TYPE_AWK) {
10596 split_type = SPLIT_TYPE_STRING;
10601 mustnot_broken(spat);
10602 split_type = literal_split_pattern(spat, SPLIT_TYPE_STRING);
10610#define SPLIT_STR(beg, len) ( \
10611 empty_count = split_string(result, str, beg, len, empty_count), \
10612 str_mod_check(str, str_start, str_len))
10615 const char *ptr = RSTRING_PTR(str);
10616 const char *
const str_start = ptr;
10617 const long str_len = RSTRING_LEN(str);
10618 const char *
const eptr = str_start + str_len;
10619 if (split_type == SPLIT_TYPE_AWK) {
10620 const char *bptr = ptr;
10626 if (is_ascii_string(str)) {
10627 while (ptr < eptr) {
10628 c = (
unsigned char)*ptr++;
10630 if (ascii_isspace(c)) {
10636 if (!
NIL_P(limit) && lim <= i)
break;
10639 else if (ascii_isspace(c)) {
10640 SPLIT_STR(beg, end-beg);
10643 if (!
NIL_P(limit)) ++i;
10651 while (ptr < eptr) {
10654 c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
10663 if (!
NIL_P(limit) && lim <= i)
break;
10667 SPLIT_STR(beg, end-beg);
10670 if (!
NIL_P(limit)) ++i;
10678 else if (split_type == SPLIT_TYPE_STRING) {
10679 const char *substr_start = ptr;
10680 const char *sptr = RSTRING_PTR(spat);
10681 long slen = RSTRING_LEN(spat);
10684 mustnot_broken(str);
10685 enc = rb_enc_check(str, spat);
10686 while (ptr < eptr &&
10687 (end =
rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
10690 if (t != ptr + end) {
10694 SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start);
10695 str_mod_check(spat, sptr, slen);
10697 substr_start = ptr;
10698 if (!
NIL_P(limit) && lim <= ++i)
break;
10700 beg = ptr - str_start;
10702 else if (split_type == SPLIT_TYPE_CHARS) {
10706 mustnot_broken(str);
10707 enc = rb_enc_get(str);
10708 while (ptr < eptr &&
10709 (n = rb_enc_precise_mbclen(ptr, eptr, enc)) > 0) {
10710 SPLIT_STR(ptr - str_start, n);
10712 if (!
NIL_P(limit) && lim <= ++i)
break;
10714 beg = ptr - str_start;
10718 long len = RSTRING_LEN(str);
10725 (match ? (rb_match_unbusy(match),
rb_backref_set(match)) : (void)0)) {
10728 end = RMATCH_BEG(match, 0);
10729 if (start == end && RMATCH_BEG(match, 0) == RMATCH_END(match, 0)) {
10734 else if (last_null == 1) {
10735 SPLIT_STR(beg, rb_enc_fast_mbclen(ptr+beg, eptr, enc));
10742 start += rb_enc_fast_mbclen(ptr+start,eptr,enc);
10748 SPLIT_STR(beg, end-beg);
10749 beg = start = RMATCH_END(match, 0);
10753 for (idx = 1; idx < RMATCH_NREGS(match); idx++) {
10754 if (RMATCH_BEG(match, idx) == -1)
continue;
10755 SPLIT_STR(RMATCH_BEG(match, idx), RMATCH_END(match, idx) - RMATCH_BEG(match, idx));
10757 if (!
NIL_P(limit) && lim <= ++i)
break;
10759 if (match) rb_match_unbusy(match);
10761 if (RSTRING_LEN(str) > 0 && (!
NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
10762 SPLIT_STR(beg, RSTRING_LEN(str)-beg);
10765 return result ? result : str;
10775 return rb_str_split_m(1, &sep, str);
10778#define WANTARRAY(m, size) (!rb_block_given_p() ? rb_ary_new_capa(size) : 0)
10793#define ENUM_ELEM(ary, e) enumerator_element(ary, e)
10796chomp_newline(
const char *p,
const char *e,
rb_encoding *enc)
10798 const char *prev = rb_enc_prev_char(p, e, e, enc);
10801 prev = rb_enc_prev_char(p, e, e, enc);
10802 if (prev && rb_enc_ascget(prev, e, NULL, enc) ==
'\r')
10814 RSTRING_LEN(rs) != 1 ||
10815 RSTRING_PTR(rs)[0] !=
'\n')) {
10821#define rb_rs get_rs()
10828 const char *pend, *subptr, *subend, *rsptr, *hit, *adjusted;
10834 if (!
NIL_P(opts)) {
10835 static ID keywords[1];
10836 if (!keywords[0]) {
10840 chomp = (!UNDEF_P(chomp) &&
RTEST(chomp));
10844 if (!ENUM_ELEM(ary, str)) {
10852 if (!RSTRING_LEN(str))
goto end;
10854 const char *
const ptr = subptr = RSTRING_PTR(str);
10855 const long len = RSTRING_LEN(str);
10858 rslen = RSTRING_LEN(rs);
10861 enc = rb_enc_get(str);
10863 enc = rb_enc_check(str, rs);
10868 const char *eol = NULL;
10870 while (subend < pend) {
10871 long chomp_rslen = 0;
10873 if (rb_enc_ascget(subend, pend, &n, enc) !=
'\r')
10875 rslen = n + rb_enc_mbclen(subend + n, pend, enc);
10877 if (eol == subend)
break;
10881 chomp_rslen = -rslen;
10885 if (!subptr) subptr = subend;
10889 }
while (subend < pend);
10890 if (!subptr)
break;
10891 if (rslen == 0) chomp_rslen = 0;
10893 subend - subptr + (chomp ? chomp_rslen : rslen));
10894 if (ENUM_ELEM(ary, line)) {
10895 str_mod_check(str, ptr,
len);
10897 subptr = eol = NULL;
10902 rsptr = RSTRING_PTR(rs);
10903 if (RSTRING_LEN(rs) == rb_enc_mbminlen(enc) &&
10912 rsptr = RSTRING_PTR(rs);
10913 rslen = RSTRING_LEN(rs);
10916 while (subptr < pend) {
10917 pos =
rb_memsearch(rsptr, rslen, subptr, pend - subptr, enc);
10918 if (pos < 0)
break;
10919 hit = subptr + pos;
10921 if (hit != adjusted) {
10925 subend = hit += rslen;
10928 subend = chomp_newline(subptr, subend, enc);
10935 if (ENUM_ELEM(ary, line)) {
10936 str_mod_check(str, ptr,
len);
10941 if (subptr < pend) {
10944 pend = chomp_newline(subptr, pend, enc);
10946 else if (pend - subptr >= rslen &&
10947 memcmp(pend - rslen, rsptr, rslen) == 0) {
10952 ENUM_ELEM(ary, line);
10973rb_str_each_line(
int argc,
VALUE *argv,
VALUE str)
10976 return rb_str_enumerate_lines(argc, argv, str, 0);
11031rb_str_lines(
int argc,
VALUE *argv,
VALUE str)
11033 VALUE ary = WANTARRAY(
"lines", 0);
11034 return rb_str_enumerate_lines(argc, argv, str, ary);
11040 return LONG2FIX(RSTRING_LEN(str));
11048 for (i=0; i<RSTRING_LEN(str); i++) {
11049 ENUM_ELEM(ary,
INT2FIX((
unsigned char)RSTRING_PTR(str)[i]));
11067rb_str_each_byte(
VALUE str)
11070 return rb_str_enumerate_bytes(str, 0);
11082rb_str_bytes(
VALUE str)
11084 VALUE ary = WANTARRAY(
"bytes", RSTRING_LEN(str));
11085 return rb_str_enumerate_bytes(str, ary);
11103 ptr = RSTRING_PTR(str);
11104 len = RSTRING_LEN(str);
11105 enc = rb_enc_get(str);
11108 for (i = 0; i <
len; i += n) {
11109 n = rb_enc_fast_mbclen(ptr + i, ptr +
len, enc);
11114 for (i = 0; i <
len; i += n) {
11115 n = rb_enc_mbclen(ptr + i, ptr +
len, enc);
11136rb_str_each_char(
VALUE str)
11139 return rb_str_enumerate_chars(str, 0);
11151rb_str_chars(
VALUE str)
11154 return rb_str_enumerate_chars(str, ary);
11158rb_str_enumerate_codepoints(
VALUE str,
VALUE ary)
11163 const char *ptr, *end;
11165 int enc_asciicompat;
11167 if (single_byte_optimizable(str))
11168 return rb_str_enumerate_bytes(str, ary);
11171 ptr = RSTRING_PTR(str);
11173 enc = STR_ENC_GET(str);
11174 enc_asciicompat = rb_enc_asciicompat(enc);
11176 while (ptr < end) {
11181 c = (enc_asciicompat &&
ISASCII(*ptr)) ?
11182 (
unsigned char)*ptr : rb_enc_codepoint_len(ptr, end, &n, enc);
11203rb_str_each_codepoint(
VALUE str)
11206 return rb_str_enumerate_codepoints(str, 0);
11218rb_str_codepoints(
VALUE str)
11221 return rb_str_enumerate_codepoints(str, ary);
11227 int encidx = rb_enc_to_index(enc);
11229 const OnigUChar source_ascii[] =
"\\X";
11230 const OnigUChar *source = source_ascii;
11231 size_t source_len =
sizeof(source_ascii) - 1;
11234#define CHARS_16BE(x) (OnigUChar)((x)>>8), (OnigUChar)(x)
11235#define CHARS_16LE(x) (OnigUChar)(x), (OnigUChar)((x)>>8)
11236#define CHARS_32BE(x) CHARS_16BE((x)>>16), CHARS_16BE(x)
11237#define CHARS_32LE(x) CHARS_16LE(x), CHARS_16LE((x)>>16)
11238#define CASE_UTF(e) \
11239 case ENCINDEX_UTF_##e: { \
11240 static const OnigUChar source_UTF_##e[] = {CHARS_##e('\\'), CHARS_##e('X')}; \
11241 source = source_UTF_##e; \
11242 source_len = sizeof(source_UTF_##e); \
11245 CASE_UTF(16BE); CASE_UTF(16LE); CASE_UTF(32BE); CASE_UTF(32LE);
11253 regex_t *reg_grapheme_cluster;
11255 int r = onig_new(®_grapheme_cluster, source, source + source_len,
11256 ONIG_OPTION_DEFAULT, enc, OnigDefaultSyntax, &einfo);
11258 UChar message[ONIG_MAX_ERROR_MESSAGE_LEN];
11259 onig_error_code_to_str(message, r, &einfo);
11260 rb_fatal(
"cannot compile grapheme cluster regexp: %s", (
char *)message);
11263 return reg_grapheme_cluster;
11269 int encidx = rb_enc_to_index(enc);
11270 static regex_t *reg_grapheme_cluster_utf8 = NULL;
11272 if (encidx == rb_utf8_encindex()) {
11273 if (!reg_grapheme_cluster_utf8) {
11274 reg_grapheme_cluster_utf8 = get_reg_grapheme_cluster(enc);
11277 return reg_grapheme_cluster_utf8;
11286 size_t grapheme_cluster_count = 0;
11288 const char *ptr, *end;
11290 if (!rb_enc_unicode_p(enc)) {
11294 bool cached_reg_grapheme_cluster =
true;
11295 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
11296 if (!reg_grapheme_cluster) {
11297 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
11298 cached_reg_grapheme_cluster =
false;
11301 ptr = RSTRING_PTR(str);
11304 while (ptr < end) {
11305 OnigPosition
len = onig_match(reg_grapheme_cluster,
11306 (
const OnigUChar *)ptr, (
const OnigUChar *)end,
11307 (
const OnigUChar *)ptr, NULL, 0);
11308 if (
len <= 0)
break;
11309 grapheme_cluster_count++;
11313 if (!cached_reg_grapheme_cluster) {
11314 onig_free(reg_grapheme_cluster);
11317 return SIZET2NUM(grapheme_cluster_count);
11321rb_str_enumerate_grapheme_clusters(
VALUE str,
VALUE ary)
11325 const char *ptr0, *ptr, *end;
11327 if (!rb_enc_unicode_p(enc)) {
11328 return rb_str_enumerate_chars(str, ary);
11333 bool cached_reg_grapheme_cluster =
true;
11334 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
11335 if (!reg_grapheme_cluster) {
11336 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
11337 cached_reg_grapheme_cluster =
false;
11340 ptr0 = ptr = RSTRING_PTR(str);
11343 while (ptr < end) {
11344 OnigPosition
len = onig_match(reg_grapheme_cluster,
11345 (
const OnigUChar *)ptr, (
const OnigUChar *)end,
11346 (
const OnigUChar *)ptr, NULL, 0);
11347 if (
len <= 0)
break;
11352 if (!cached_reg_grapheme_cluster) {
11353 onig_free(reg_grapheme_cluster);
11373rb_str_each_grapheme_cluster(
VALUE str)
11376 return rb_str_enumerate_grapheme_clusters(str, 0);
11388rb_str_grapheme_clusters(
VALUE str)
11391 return rb_str_enumerate_grapheme_clusters(str, ary);
11395chopped_length(
VALUE str)
11398 const char *p, *p2, *beg, *end;
11400 beg = RSTRING_PTR(str);
11401 end = beg + RSTRING_LEN(str);
11402 if (beg >= end)
return 0;
11403 p = rb_enc_prev_char(beg, end, end, enc);
11405 if (p > beg && rb_enc_ascget(p, end, 0, enc) ==
'\n') {
11406 p2 = rb_enc_prev_char(beg, p, end, enc);
11407 if (p2 && rb_enc_ascget(p2, end, 0, enc) ==
'\r') p = p2;
11425rb_str_chop_bang(
VALUE str)
11427 str_modify_keep_cr(str);
11428 if (RSTRING_LEN(str) > 0) {
11430 len = chopped_length(str);
11431 STR_SET_LEN(str,
len);
11432 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
11451rb_str_chop(
VALUE str)
11457smart_chomp(
VALUE str,
const char *e,
const char *p)
11460 if (rb_enc_mbminlen(enc) > 1) {
11462 if (e - p < rb_enc_mbminlen(enc))
return e - p;
11467 pp = e - rb_enc_mbminlen(enc);
11470 if (rb_enc_ascget(pp, e, 0, enc) ==
'\r') {
11478 if (--e > p && *(e-1) ==
'\r') {
11495 const char *pp, *e, *rsptr;
11497 const char *
const p = RSTRING_PTR(str);
11498 long len = RSTRING_LEN(str);
11500 if (
len == 0)
return 0;
11503 return smart_chomp(str, e, p);
11506 enc = rb_enc_get(str);
11509 if (rb_enc_mbminlen(enc) > 1) {
11510 while (e - p >= rb_enc_mbminlen(enc)) {
11514 pp -= rb_enc_mbminlen(enc);
11517 if (rb_enc_ascget(pp, e, 0, enc) ==
'\r') {
11524 while (e > p && *(e-1) ==
'\n') {
11526 if (e > p && *(e-1) ==
'\r')
11532 if (rslen >
len)
return len;
11534 enc = rb_enc_get(rs);
11535 newline = rsptr[rslen-1];
11536 if (rslen == rb_enc_mbminlen(enc)) {
11538 if (newline ==
'\n')
11539 return smart_chomp(str, e, p);
11543 return smart_chomp(str, e, p);
11547 enc = rb_enc_check(str, rs);
11548 if (is_broken_string(rs)) {
11552 if (p[
len-1] == newline &&
11554 memcmp(rsptr, pp, rslen) == 0)) {
11555 if (at_char_boundary(p, pp, e, enc))
11556 return len - rslen;
11568chomp_rs(
int argc,
const VALUE *argv)
11572 VALUE rs = argv[0];
11584 str_modify_keep_cr(str);
11585 STR_SET_LEN(str,
len);
11586 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
11596 long olen = RSTRING_LEN(str);
11597 long len = chompped_length(str, rs);
11598 if (
len >= olen)
return Qnil;
11599 return str_shrink(str,
len);
11615rb_str_chomp_bang(
int argc,
VALUE *argv,
VALUE str)
11618 str_modifiable(str);
11619 if (RSTRING_LEN(str) == 0 && argc < 2)
return Qnil;
11620 rs = chomp_rs(argc, argv);
11622 return rb_str_chomp_string(str, rs);
11635rb_str_chomp(
int argc,
VALUE *argv,
VALUE str)
11637 VALUE rs = chomp_rs(argc, argv);
11643tr_setup_table_multi(
char table[TR_TABLE_SIZE],
VALUE *tablep,
VALUE *ctablep,
11644 VALUE str,
int num_selectors,
VALUE *selectors)
11648 for (i=0; i<num_selectors; i++) {
11649 VALUE selector = selectors[i];
11653 enc = rb_enc_check(str, selector);
11654 tr_setup_table(selector, table, i==0, tablep, ctablep, enc);
11661 const char *
const start = s;
11663 if (!s || s >= e)
return 0;
11666 if (single_byte_optimizable(str)) {
11667 while (s < e && (*s ==
'\0' || ascii_isspace(*s))) s++;
11672 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
11682lstrip_offset_table(
VALUE str,
const char *s,
const char *e,
rb_encoding *enc,
11683 char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
11685 const char *
const start = s;
11687 if (!s || s >= e)
return 0;
11692 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
11694 if (!tr_find(cc, table, del, nodel))
break;
11713rb_str_lstrip_bang(
int argc,
VALUE *argv,
VALUE str)
11717 long olen, loffset;
11719 str_modify_keep_cr(str);
11720 enc = STR_ENC_GET(str);
11723 char table[TR_TABLE_SIZE];
11724 VALUE del = 0, nodel = 0;
11726 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11727 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11730 loffset = lstrip_offset(str, start, start+olen, enc);
11734 long len = olen-loffset;
11735 memmove(start, start + loffset,
len);
11736 STR_SET_LEN(str,
len);
11737 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
11772rb_str_lstrip(
int argc,
VALUE *argv,
VALUE str)
11779 char table[TR_TABLE_SIZE];
11780 VALUE del = 0, nodel = 0;
11782 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11783 loffset = lstrip_offset_table(str, start, start+
len, STR_ENC_GET(str), table, del, nodel);
11786 loffset = lstrip_offset(str, start, start+
len, STR_ENC_GET(str));
11788 if (loffset <= 0)
return str_duplicate(
rb_cString, str);
11797 rb_str_check_dummy_enc(enc);
11801 if (!s || s >= e)
return 0;
11805 if (single_byte_optimizable(str)) {
11807 while (s < t && ((c = *(t-1)) ==
'\0' || ascii_isspace(c))) t--;
11812 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
11822rstrip_offset_table(
VALUE str,
const char *s,
const char *e,
rb_encoding *enc,
11823 char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
11825 const char *t, *tp;
11827 rb_str_check_dummy_enc(enc);
11831 if (!s || s >= e)
return 0;
11835 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
11837 if (!tr_find(c, table, del, nodel))
break;
11857rb_str_rstrip_bang(
int argc,
VALUE *argv,
VALUE str)
11861 long olen, roffset;
11863 str_modify_keep_cr(str);
11864 enc = STR_ENC_GET(str);
11867 char table[TR_TABLE_SIZE];
11868 VALUE del = 0, nodel = 0;
11870 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11871 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11874 roffset = rstrip_offset(str, start, start+olen, enc);
11877 long len = olen - roffset;
11879 STR_SET_LEN(str,
len);
11880 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
11914rb_str_rstrip(
int argc,
VALUE *argv,
VALUE str)
11918 long olen, roffset;
11920 enc = STR_ENC_GET(str);
11923 char table[TR_TABLE_SIZE];
11924 VALUE del = 0, nodel = 0;
11926 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11927 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11930 roffset = rstrip_offset(str, start, start+olen, enc);
11932 if (roffset <= 0)
return str_duplicate(
rb_cString, str);
11950rb_str_strip_bang(
int argc,
VALUE *argv,
VALUE str)
11953 long olen, loffset, roffset;
11956 str_modify_keep_cr(str);
11957 enc = STR_ENC_GET(str);
11961 char table[TR_TABLE_SIZE];
11962 VALUE del = 0, nodel = 0;
11964 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11965 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11966 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
11969 loffset = lstrip_offset(str, start, start+olen, enc);
11970 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
11973 if (loffset > 0 || roffset > 0) {
11974 long len = olen-roffset;
11977 memmove(start, start + loffset,
len);
11979 STR_SET_LEN(str,
len);
11980 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
12015rb_str_strip(
int argc,
VALUE *argv,
VALUE str)
12018 long olen, loffset, roffset;
12024 char table[TR_TABLE_SIZE];
12025 VALUE del = 0, nodel = 0;
12027 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
12028 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
12029 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
12032 loffset = lstrip_offset(str, start, start+olen, enc);
12033 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
12036 if (loffset <= 0 && roffset <= 0)
return str_duplicate(
rb_cString, str);
12041scan_once(
VALUE str,
VALUE pat,
long *start,
int set_backref_str)
12044 long end, pos = rb_pat_search(pat, str, *start, set_backref_str);
12048 end = pos + RSTRING_LEN(pat);
12052 pos = RMATCH_BEG(match, 0);
12053 end = RMATCH_END(match, 0);
12061 if (RSTRING_LEN(str) > end)
12062 *start = end + rb_enc_fast_mbclen(RSTRING_PTR(str) + end,
12071 if (
NIL_P(match) || RMATCH_NREGS(match) == 1) {
12076 int num_regs = RMATCH_NREGS(match);
12078 for (
int i = 1; i < num_regs; i++) {
12080 if (RMATCH_BEG(match, i) >= 0) {
12081 s =
rb_str_subseq(str, RMATCH_BEG(match, i), RMATCH_END(match, i) - RMATCH_BEG(match, i));
12109 long last = -1, prev = 0;
12110 const char *p = RSTRING_PTR(str);
12111 long len = RSTRING_LEN(str);
12113 pat = get_pat_quoted(pat, 1);
12114 mustnot_broken(str);
12118 while (!
NIL_P(result = scan_once(str, pat, &start, 0))) {
12123 if (last >= 0) rb_pat_search(pat, str, last, 1);
12128 while (!
NIL_P(result = scan_once(str, pat, &start, 1))) {
12132 str_mod_check(str, p,
len);
12134 if (last >= 0) rb_pat_search(pat, str, last, 1);
12186rb_str_hex(
VALUE str)
12188 return rb_str_to_inum(str, 16, FALSE);
12272rb_str_oct(
VALUE str)
12274 return rb_str_to_inum(str, -8, FALSE);
12277#ifndef HAVE_CRYPT_R
12282 rb_nativethread_lock_t lock;
12283} crypt_mutex = {PTHREAD_MUTEX_INITIALIZER};
12352# define CRYPT_END() ALLOCV_END(databuf)
12355 extern char *crypt(
const char *,
const char *);
12356# define CRYPT_END() rb_nativethread_lock_unlock(&crypt_mutex.lock)
12359 const char *s, *saltp, *res;
12361 char salt_8bit_clean[3];
12365 mustnot_wchar(str);
12366 mustnot_wchar(salt);
12368 saltp = RSTRING_PTR(salt);
12369 if (RSTRING_LEN(salt) < 2 || !saltp[0] || !saltp[1]) {
12370 rb_raise(rb_eArgError,
"salt too short (need >=2 bytes)");
12374 if (!
ISASCII((
unsigned char)saltp[0]) || !
ISASCII((
unsigned char)saltp[1])) {
12375 salt_8bit_clean[0] = saltp[0] & 0x7f;
12376 salt_8bit_clean[1] = saltp[1] & 0x7f;
12377 salt_8bit_clean[2] =
'\0';
12378 saltp = salt_8bit_clean;
12383# ifdef HAVE_STRUCT_CRYPT_DATA_INITIALIZED
12384 data->initialized = 0;
12386 res = crypt_r(s, saltp, data);
12389 res = crypt(s, saltp);
12404 size_t res_size = strlen(res);
12405 tmp_buf =
ALLOCA_N(
char, res_size);
12406 memcpy(tmp_buf, res, res_size);
12442 char *ptr, *p, *pend;
12445 unsigned long sum0 = 0;
12450 ptr = p = RSTRING_PTR(str);
12451 len = RSTRING_LEN(str);
12457 str_mod_check(str, ptr,
len);
12460 sum0 += (
unsigned char)*p;
12471 if (bits < (
int)
sizeof(
long)*CHAR_BIT) {
12472 sum0 &= (((
unsigned long)1)<<bits)-1;
12492rb_str_justify(
int argc,
VALUE *argv,
VALUE str,
char jflag)
12496 long width,
len, flen = 1, fclen = 1;
12499 const char *f =
" ";
12500 long n, size, llen, rlen, llen2 = 0, rlen2 = 0;
12502 int singlebyte = 1, cr;
12506 enc = STR_ENC_GET(str);
12510 enc = rb_enc_check(str, pad);
12511 f = RSTRING_PTR(pad);
12512 flen = RSTRING_LEN(pad);
12513 fclen = str_strlen(pad, enc);
12514 singlebyte = single_byte_optimizable(pad);
12515 if (flen == 0 || fclen == 0) {
12516 rb_raise(rb_eArgError,
"zero width padding");
12519 termlen = rb_enc_mbminlen(enc);
12520 len = str_strlen(str, enc);
12521 if (width < 0 || len >= width)
return str_duplicate(
rb_cString, str);
12523 llen = (jflag ==
'l') ? 0 : ((jflag ==
'r') ? n : n/2);
12527 llen2 = str_offset(f, f + flen, llen % fclen, enc, singlebyte);
12528 rlen2 = str_offset(f, f + flen, rlen % fclen, enc, singlebyte);
12530 size = RSTRING_LEN(str);
12531 if ((
len = llen / fclen + rlen / fclen) >= LONG_MAX / flen ||
12532 (
len *= flen) >= LONG_MAX - llen2 - rlen2 ||
12533 (
len += llen2 + rlen2) >= LONG_MAX - size) {
12534 rb_raise(rb_eArgError,
"argument too big");
12538 p = RSTRING_PTR(res);
12540 memset(p, *f, llen);
12544 while (llen >= fclen) {
12550 memcpy(p, f, llen2);
12554 memcpy(p, RSTRING_PTR(str), size);
12557 memset(p, *f, rlen);
12561 while (rlen >= fclen) {
12567 memcpy(p, f, rlen2);
12571 TERM_FILL(p, termlen);
12572 STR_SET_LEN(res, p-RSTRING_PTR(res));
12593rb_str_ljust(
int argc,
VALUE *argv,
VALUE str)
12595 return rb_str_justify(argc, argv, str,
'l');
12607rb_str_rjust(
int argc,
VALUE *argv,
VALUE str)
12609 return rb_str_justify(argc, argv, str,
'r');
12622rb_str_center(
int argc,
VALUE *argv,
VALUE str)
12624 return rb_str_justify(argc, argv, str,
'c');
12640 sep = get_pat_quoted(sep, 0);
12647 pos = RMATCH_BEG(match, 0);
12651 pos = rb_str_index(str, sep, 0);
12652 if (pos < 0)
goto failed;
12655 long rpos = pos + RSTRING_LEN(sep);
12656 if (rpos > RSTRING_LEN(str))
goto failed;
12662 return rb_ary_new3(3, str_duplicate(
rb_cString, str), str_new_empty_String(str), str_new_empty_String(str));
12676 long pos = RSTRING_LEN(str);
12678 sep = get_pat_quoted(sep, 0);
12685 pos = RMATCH_BEG(match, 0);
12690 pos = rb_str_rindex(str, sep, pos);
12696 long rpos = pos + RSTRING_LEN(sep);
12697 if (rpos > RSTRING_LEN(str))
goto failed;
12702 return rb_ary_new3(3, str_new_empty_String(str), str_new_empty_String(str), str_duplicate(
rb_cString, str));
12714rb_str_start_with(
int argc,
VALUE *argv,
VALUE str)
12718 for (i=0; i<argc; i++) {
12719 VALUE tmp = argv[i];
12721 if (rb_reg_start_with_p(tmp, str))
12725 const char *p, *s, *e;
12730 enc = rb_enc_check(str, tmp);
12731 if ((tlen = RSTRING_LEN(tmp)) == 0)
return Qtrue;
12732 if ((slen = RSTRING_LEN(str)) < tlen)
continue;
12733 p = RSTRING_PTR(str);
12736 if (!at_char_right_boundary(p, s, e, enc))
12738 if (memcmp(p, RSTRING_PTR(tmp), tlen) == 0)
12754rb_str_end_with(
int argc,
VALUE *argv,
VALUE str)
12758 for (i=0; i<argc; i++) {
12759 VALUE tmp = argv[i];
12760 const char *p, *s, *e;
12765 enc = rb_enc_check(str, tmp);
12766 if ((tlen = RSTRING_LEN(tmp)) == 0)
return Qtrue;
12767 if ((slen = RSTRING_LEN(str)) < tlen)
continue;
12768 p = RSTRING_PTR(str);
12771 if (!at_char_boundary(p, s, e, enc))
12773 if (memcmp(s, RSTRING_PTR(tmp), tlen) == 0)
12789deleted_prefix_length(
VALUE str,
VALUE prefix)
12791 const char *strptr, *prefixptr;
12792 long olen, prefixlen;
12797 if (!is_broken_string(prefix) ||
12798 !rb_enc_asciicompat(enc) ||
12799 !rb_enc_asciicompat(rb_enc_get(prefix))) {
12800 enc = rb_enc_check(str, prefix);
12804 prefixlen = RSTRING_LEN(prefix);
12805 if (prefixlen <= 0)
return 0;
12806 olen = RSTRING_LEN(str);
12807 if (olen < prefixlen)
return 0;
12808 strptr = RSTRING_PTR(str);
12809 prefixptr = RSTRING_PTR(prefix);
12810 if (memcmp(strptr, prefixptr, prefixlen) != 0)
return 0;
12811 if (is_broken_string(prefix)) {
12812 if (!is_broken_string(str)) {
12816 const char *strend = strptr + olen;
12817 const char *after_prefix = strptr + prefixlen;
12818 if (!at_char_right_boundary(strptr, after_prefix, strend, enc)) {
12839rb_str_delete_prefix_bang(
VALUE str,
VALUE prefix)
12842 str_modify_keep_cr(str);
12844 prefixlen = deleted_prefix_length(str, prefix);
12845 if (prefixlen <= 0)
return Qnil;
12859rb_str_delete_prefix(
VALUE str,
VALUE prefix)
12863 prefixlen = deleted_prefix_length(str, prefix);
12864 if (prefixlen <= 0)
return str_duplicate(
rb_cString, str);
12866 return rb_str_subseq(str, prefixlen, RSTRING_LEN(str) - prefixlen);
12879deleted_suffix_length(
VALUE str,
VALUE suffix)
12881 const char *strptr, *suffixptr;
12882 long olen, suffixlen;
12886 if (is_broken_string(suffix))
return 0;
12887 enc = rb_enc_check(str, suffix);
12890 suffixlen = RSTRING_LEN(suffix);
12891 if (suffixlen <= 0)
return 0;
12892 olen = RSTRING_LEN(str);
12893 if (olen < suffixlen)
return 0;
12894 strptr = RSTRING_PTR(str);
12895 suffixptr = RSTRING_PTR(suffix);
12896 const char *strend = strptr + olen;
12897 const char *before_suffix = strend - suffixlen;
12898 if (memcmp(before_suffix, suffixptr, suffixlen) != 0)
return 0;
12899 if (!at_char_boundary(strptr, before_suffix, strend, enc))
return 0;
12915rb_str_delete_suffix_bang(
VALUE str,
VALUE suffix)
12918 str_modifiable(str);
12920 suffixlen = deleted_suffix_length(str, suffix);
12921 if (suffixlen <= 0)
return Qnil;
12923 return str_shrink(str, RSTRING_LEN(str) - suffixlen);
12935rb_str_delete_suffix(
VALUE str,
VALUE suffix)
12939 suffixlen = deleted_suffix_length(str, suffix);
12940 if (suffixlen <= 0)
return str_duplicate(
rb_cString, str);
12942 return rb_str_subseq(str, 0, RSTRING_LEN(str) - suffixlen);
12949 rb_raise(
rb_eTypeError,
"value of %"PRIsVALUE
" must be String", rb_id2str(
id));
12955nil_setter_warning(
ID id)
12957 rb_warn_deprecated(
"non-nil '%"PRIsVALUE
"'", NULL, rb_id2str(
id));
12964 if (!
NIL_P(*var)) {
12965 nil_setter_warning(
id);
12972 val = rb_fs_check(val);
12975 "value of %"PRIsVALUE
" must be String or Regexp",
12979 nil_setter_warning(
id);
12996 str_modifiable(str);
12999 int idx = rb_enc_to_index(encoding);
13006 rb_enc_associate_index(str, idx);
13030 if (STR_EMBED_P(str)) {
13031 str2 = str_alloc_embed(
rb_cString, RSTRING_LEN(str) + TERM_LEN(str));
13036 str_replace_shared_without_enc(str2, str);
13038 if (rb_enc_asciicompat(STR_ENC_GET(str))) {
13061rb_str_valid_encoding_p(
VALUE str)
13063 int cr = rb_enc_str_coderange(str);
13070rb_str_is_ascii_only_p(
VALUE str)
13072 int cr = rb_enc_str_coderange(str);
13080 static const char ellipsis[] =
"...";
13081 const long ellipsislen =
sizeof(ellipsis) - 1;
13083 const long blen = RSTRING_LEN(str);
13084 const char *
const p = RSTRING_PTR(str), *e = p + blen;
13085 VALUE estr, ret = 0;
13088 if (
len * rb_enc_mbminlen(enc) >= blen ||
13092 else if (
len <= ellipsislen ||
13094 if (rb_enc_asciicompat(enc)) {
13096 rb_enc_associate(ret, enc);
13103 else if (ret =
rb_str_subseq(str, 0, e - p), rb_enc_asciicompat(enc)) {
13108 rb_enc_from_encoding(enc), 0,
Qnil);
13119 cr = rb_enc_str_coderange(str);
13121 rb_raise(rb_eArgError,
"replacement must be valid byte sequence '%+"PRIsVALUE
"'", str);
13127 rb_enc_inspect_name(enc), rb_enc_inspect_name(e));
13146 if (enc == STR_ENC_GET(str)) {
13151 return enc_str_scrub(enc, str, repl, cr);
13159 const char *rep, *p, *e, *p1, *sp;
13165 rb_raise(rb_eArgError,
"both of block and replacement given");
13172 if (!
NIL_P(repl)) {
13173 repl = str_compat_and_valid(repl, enc);
13176 if (rb_enc_dummy_p(enc)) {
13179 encidx = rb_enc_to_index(enc);
13181#define DEFAULT_REPLACE_CHAR(str) do { \
13182 RBIMPL_ATTR_NONSTRING() static const char replace[sizeof(str)-1] = str; \
13183 rep = replace; replen = (int)sizeof(replace); \
13186 slen = RSTRING_LEN(str);
13187 p = RSTRING_PTR(str);
13192 if (rb_enc_asciicompat(enc)) {
13198 else if (!
NIL_P(repl)) {
13199 rep = RSTRING_PTR(repl);
13200 replen = RSTRING_LEN(repl);
13203 else if (encidx == rb_utf8_encindex()) {
13204 DEFAULT_REPLACE_CHAR(
"\xEF\xBF\xBD");
13208 DEFAULT_REPLACE_CHAR(
"?");
13213 p = search_nonascii(p, e);
13218 int ret = rb_enc_precise_mbclen(p, e, enc);
13226 p = search_nonascii(p, e);
13243 if (e - p < clen) clen = e - p;
13250 for (; clen > 1; clen--) {
13251 ret = rb_enc_precise_mbclen(q, q + clen, enc);
13262 repl =
rb_yield(rb_enc_str_new(p, clen, enc));
13263 str_mod_check(str, sp, slen);
13264 repl = str_compat_and_valid(repl, enc);
13271 p = search_nonascii(p, e);
13297 repl =
rb_yield(rb_enc_str_new(p, e-p, enc));
13298 str_mod_check(str, sp, slen);
13299 repl = str_compat_and_valid(repl, enc);
13308 long mbminlen = rb_enc_mbminlen(enc);
13312 else if (!
NIL_P(repl)) {
13313 rep = RSTRING_PTR(repl);
13314 replen = RSTRING_LEN(repl);
13316 else if (encidx == ENCINDEX_UTF_16BE) {
13317 DEFAULT_REPLACE_CHAR(
"\xFF\xFD");
13319 else if (encidx == ENCINDEX_UTF_16LE) {
13320 DEFAULT_REPLACE_CHAR(
"\xFD\xFF");
13322 else if (encidx == ENCINDEX_UTF_32BE) {
13323 DEFAULT_REPLACE_CHAR(
"\x00\x00\xFF\xFD");
13325 else if (encidx == ENCINDEX_UTF_32LE) {
13326 DEFAULT_REPLACE_CHAR(
"\xFD\xFF\x00\x00");
13329 DEFAULT_REPLACE_CHAR(
"?");
13333 int ret = rb_enc_precise_mbclen(p, e, enc);
13346 if (e - p < clen) clen = e - p;
13347 if (clen <= mbminlen * 2) {
13352 for (; clen > mbminlen; clen-=mbminlen) {
13353 ret = rb_enc_precise_mbclen(q, q + clen, enc);
13363 repl =
rb_yield(rb_enc_str_new(p, clen, enc));
13364 str_mod_check(str, sp, slen);
13365 repl = str_compat_and_valid(repl, enc);
13390 repl =
rb_yield(rb_enc_str_new(p, e-p, enc));
13391 str_mod_check(str, sp, slen);
13392 repl = str_compat_and_valid(repl, enc);
13432str_scrub_bang(
int argc,
VALUE *argv,
VALUE str)
13440static ID id_normalize;
13441static ID id_normalized_p;
13442static VALUE mUnicodeNormalize;
13445unicode_normalize_common(
int argc,
VALUE *argv,
VALUE str,
ID id)
13447 static int UnicodeNormalizeRequired = 0;
13450 if (!UnicodeNormalizeRequired) {
13451 rb_require(
"unicode_normalize/normalize.rb");
13452 UnicodeNormalizeRequired = 1;
13456 return rb_funcallv(mUnicodeNormalize,
id, argc+1, argv2);
13467rb_str_unicode_normalize(
int argc,
VALUE *argv,
VALUE str)
13469 return unicode_normalize_common(argc, argv, str, id_normalize);
13483rb_str_unicode_normalize_bang(
int argc,
VALUE *argv,
VALUE str)
13485 return rb_str_replace(str, unicode_normalize_common(argc, argv, str, id_normalize));
13512rb_str_unicode_normalized_p(
int argc,
VALUE *argv,
VALUE str)
13514 return unicode_normalize_common(argc, argv, str, id_normalized_p);
13646#define sym_equal rb_obj_equal
13649sym_printable(
const char *s,
const char *send,
rb_encoding *enc)
13653 int c = rb_enc_precise_mbclen(s, send, enc);
13657 c = rb_enc_mbc_to_codepoint(s, send, enc);
13665rb_str_symname_p(
VALUE sym)
13670 rb_encoding *resenc = rb_default_internal_encoding();
13672 if (resenc == NULL) resenc = rb_default_external_encoding();
13673 enc = STR_ENC_GET(sym);
13674 ptr = RSTRING_PTR(sym);
13675 len = RSTRING_LEN(sym);
13676 if ((resenc != enc && !rb_str_is_ascii_only_p(sym)) ||
len != (
long)strlen(ptr) ||
13684rb_str_quote_unprintable(
VALUE str)
13692 resenc = rb_default_internal_encoding();
13693 if (resenc == NULL) resenc = rb_default_external_encoding();
13694 enc = STR_ENC_GET(str);
13695 ptr = RSTRING_PTR(str);
13696 len = RSTRING_LEN(str);
13697 if ((resenc != enc && !rb_str_is_ascii_only_p(str)) ||
13698 !sym_printable(ptr, ptr +
len, enc)) {
13699 return rb_str_escape(str);
13705rb_id_quote_unprintable(
ID id)
13707 VALUE str = rb_id2str(
id);
13708 if (!rb_str_symname_p(str)) {
13709 return rb_str_escape(str);
13727sym_inspect(
VALUE sym)
13734 if (!rb_str_symname_p(str)) {
13736 len = RSTRING_LEN(str);
13737 rb_str_resize(str,
len + 1);
13738 dest = RSTRING_PTR(str);
13739 memmove(dest + 1, dest,
len);
13743 VALUE orig_str = str;
13745 len = RSTRING_LEN(orig_str);
13746 str = rb_enc_str_new(0,
len + 1, enc);
13749 ptr = RSTRING_PTR(orig_str);
13750 dest = RSTRING_PTR(str);
13751 memcpy(dest + 1, ptr,
len);
13769rb_sym_proc_call(
ID mid,
int argc,
const VALUE *argv,
int kw_splat,
VALUE passed_proc)
13774 rb_raise(rb_eArgError,
"no receiver given");
13877 return rb_str_match(
rb_sym2str(sym), other);
13892sym_match_m(
int argc,
VALUE *argv,
VALUE sym)
13894 return rb_str_match_m(argc, argv,
rb_sym2str(sym));
13907sym_match_m_p(
int argc,
VALUE *argv,
VALUE sym)
13909 return rb_str_match_m_p(argc, argv, sym);
13927 return rb_str_aref_m(argc, argv,
rb_sym2str(sym));
13938sym_length(
VALUE sym)
13972sym_downcase(
int argc,
VALUE *argv,
VALUE sym)
13988sym_capitalize(
int argc,
VALUE *argv,
VALUE sym)
14004sym_swapcase(
int argc,
VALUE *argv,
VALUE sym)
14018sym_start_with(
int argc,
VALUE *argv,
VALUE sym)
14020 return rb_str_start_with(argc, argv,
rb_sym2str(sym));
14033sym_end_with(
int argc,
VALUE *argv,
VALUE sym)
14035 return rb_str_end_with(argc, argv,
rb_sym2str(sym));
14047sym_encoding(
VALUE sym)
14053string_for_symbol(
VALUE name)
14058 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a symbol nor a string",
14072 name = string_for_symbol(name);
14073 return rb_intern_str(name);
14082 name = string_for_symbol(name);
14106 return rb_fstring(str);
14112 struct RString fake_str = {RBASIC_INIT};
14113 int encidx = ENCINDEX_US_ASCII;
14116 encidx = ENCINDEX_ASCII_8BIT;
14119 VALUE str = setup_fake_str(&fake_str,
ptr,
len, encidx);
14121 return register_fstring(str,
true,
false);
14133 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
14134 rb_enc_autoload(enc);
14137 struct RString fake_str = {RBASIC_INIT};
14138 return register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
true,
false);
14144 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
14145 rb_enc_autoload(enc);
14148 struct RString fake_str = {RBASIC_INIT};
14149 VALUE str = register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
true,
true);
14160#if USE_YJIT || USE_ZJIT
14162rb_jit_str_concat_codepoint(
VALUE str,
VALUE codepoint)
14167 if (RB_LIKELY(code >= 0 && code < 0xff)) {
14168 rb_str_buf_cat_byte(str, (
char) code);
14178fstring_set_class_i(
VALUE *str,
void *data)
14182 return ST_CONTINUE;
14190 rb_concurrent_set_foreach_with_replace(fstring_table_obj, fstring_set_class_i, NULL);
14358 mUnicodeNormalize = rb_define_module(
"UnicodeNormalize");
14369 rb_gc_register_address(&
rb_fs);
14407#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_cRange
Range class.
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
VALUE rb_obj_is_kind_of(VALUE obj, VALUE klass)
Queries if the given object is an instance (of possibly descendants) of the given class.
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 $~.
int rb_range_values(VALUE range, VALUE *begp, VALUE *endp, int *exclp)
Deconstructs a range into its components.
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_SET_SHAREABLE(obj)
Wrapper of rb_obj_set_shareable().
#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.