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/string.h"
43#include "internal/transcode.h"
50#include "ruby_assert.h"
57#if defined HAVE_CRYPT_R
58# if defined HAVE_CRYPT_H
61#elif !defined HAVE_CRYPT
62# include "missing/crypt.h"
63# define HAVE_CRYPT_R 1
67#undef rb_usascii_str_new
71#undef rb_usascii_str_new_cstr
72#undef rb_utf8_str_new_cstr
73#undef rb_enc_str_new_cstr
74#undef rb_external_str_new_cstr
75#undef rb_locale_str_new_cstr
76#undef rb_str_dup_frozen
77#undef rb_str_buf_new_cstr
128#define RUBY_MAX_CHAR_LEN 16
129#define STR_PRECOMPUTED_HASH FL_USER4
130#define STR_SHARED_ROOT FL_USER5
131#define STR_BORROWED FL_USER6
132#define STR_TMPLOCK FL_USER7
133#define STR_NOFREE FL_USER18
135#define STR_SET_NOEMBED(str) do {\
136 FL_SET((str), STR_NOEMBED);\
137 FL_UNSET((str), STR_SHARED | STR_SHARED_ROOT | STR_BORROWED);\
139#define STR_SET_EMBED(str) FL_UNSET((str), STR_NOEMBED | STR_SHARED | STR_NOFREE)
141#define STR_SET_LEN(str, n) do { \
142 RSTRING(str)->len = (n); \
145#define TERM_LEN(str) (rb_str_enc_fastpath(str) ? 1 : rb_enc_mbminlen(rb_enc_from_index(ENCODING_GET(str))))
146#define TERM_FILL(ptr, termlen) do {\
147 char *const term_fill_ptr = (ptr);\
148 const int term_fill_len = (termlen);\
149 *term_fill_ptr = '\0';\
150 if (UNLIKELY(term_fill_len > 1))\
151 memset(term_fill_ptr, 0, term_fill_len);\
154#define RESIZE_CAPA(str,capacity) do {\
155 const int termlen = TERM_LEN(str);\
156 RESIZE_CAPA_TERM(str,capacity,termlen);\
158#define RESIZE_CAPA_TERM(str,capacity,termlen) do {\
159 if (STR_EMBED_P(str)) {\
160 if (str_embed_capa(str) < capacity + termlen) {\
161 char *const tmp = ALLOC_N(char, (size_t)(capacity) + (termlen));\
162 const long tlen = RSTRING_LEN(str);\
163 memcpy(tmp, RSTRING_PTR(str), str_embed_capa(str));\
164 RSTRING(str)->as.heap.ptr = tmp;\
165 RSTRING(str)->len = tlen;\
166 STR_SET_NOEMBED(str);\
167 RSTRING(str)->as.heap.aux.capa = (capacity);\
171 RUBY_ASSERT(!FL_TEST((str), STR_SHARED)); \
172 SIZED_REALLOC_N(RSTRING(str)->as.heap.ptr, char, \
173 (size_t)(capacity) + (termlen), STR_HEAP_SIZE(str)); \
174 RSTRING(str)->as.heap.aux.capa = (capacity);\
178#define STR_SET_SHARED(str, shared_str) do { \
179 if (!FL_TEST(str, STR_FAKESTR)) { \
180 RUBY_ASSERT(RSTRING_PTR(shared_str) <= RSTRING_PTR(str)); \
181 RUBY_ASSERT(RSTRING_PTR(str) <= RSTRING_PTR(shared_str) + RSTRING_LEN(shared_str)); \
182 RB_OBJ_WRITE((str), &RSTRING(str)->as.heap.aux.shared, (shared_str)); \
183 FL_SET((str), STR_SHARED); \
184 rb_gc_register_pinning_obj(str); \
185 FL_SET((shared_str), STR_SHARED_ROOT); \
186 if (RBASIC_CLASS((shared_str)) == 0) \
187 FL_SET_RAW((shared_str), STR_BORROWED); \
191#define STR_HEAP_PTR(str) (RSTRING(str)->as.heap.ptr)
192#define STR_HEAP_SIZE(str) ((size_t)RSTRING(str)->as.heap.aux.capa + TERM_LEN(str))
195#define STR_ENC_GET(str) get_encoding(str)
198zero_filled(
const char *s,
int n)
201 if (*s++)
return false;
206#if !defined SHARABLE_MIDDLE_SUBSTRING
207# define SHARABLE_MIDDLE_SUBSTRING 0
211SHARABLE_SUBSTRING_P(
VALUE str,
long beg,
long len)
213#if SHARABLE_MIDDLE_SUBSTRING
216 long end = beg +
len;
217 long source_len = RSTRING_LEN(str);
218 return end == source_len || zero_filled(RSTRING_PTR(str) + end, TERM_LEN(str));
223str_embed_capa(
VALUE str)
225 return rb_obj_shape_slot_size(str) - offsetof(
struct RString, as.
embed.ary);
229rb_str_reembeddable_p(
VALUE str)
231 return !
FL_TEST(str, STR_NOFREE|STR_SHARED_ROOT|STR_SHARED);
237rb_str_embedded_shared_root_p(
VALUE str)
239 return STR_EMBED_P(str) &&
FL_TEST(str, STR_SHARED_ROOT);
243rb_str_embed_size(
long capa,
long termlen)
251rb_str_size_as_embedded(
VALUE str)
254 if (STR_EMBED_P(str)) {
256 if (
FL_TEST_RAW(str, STR_PRECOMPUTED_HASH))
capa +=
sizeof(st_index_t);
258 real_size = rb_str_embed_size(
capa, TERM_LEN(str));
262 else if (rb_str_reembeddable_p(str)) {
264 if (
FL_TEST_RAW(str, STR_PRECOMPUTED_HASH))
capa +=
sizeof(st_index_t);
266 real_size = rb_str_embed_size(
capa, TERM_LEN(str));
269 real_size =
sizeof(
struct RString);
276STR_EMBEDDABLE_P(
long len,
long termlen)
278 return rb_gc_size_allocatable_p(rb_str_embed_size(
len, termlen));
285#define STR_COPY_MAX_EMBED_SIZE 256
289static VALUE str_new_frozen_buffer(
VALUE klass,
VALUE orig,
int copy_encoding);
290static VALUE str_new_static(
VALUE klass,
const char *
ptr,
long len,
int encindex);
292static void str_make_independent_expand(
VALUE str,
long len,
long expand,
const int termlen);
293static inline void str_modifiable(
VALUE str);
298str_make_independent(
VALUE str)
300 long len = RSTRING_LEN(str);
301 int termlen = TERM_LEN(str);
302 str_make_independent_expand((str),
len, 0L, termlen);
305static inline int str_dependent_p(
VALUE str);
308rb_str_make_independent(
VALUE str)
310 if (str_dependent_p(str)) {
311 str_make_independent(str);
316rb_str_make_embedded(
VALUE str)
321 int termlen = TERM_LEN(str);
322 char *buf =
RSTRING(str)->as.heap.ptr;
323 long old_capa =
RSTRING(str)->as.heap.aux.capa + termlen;
327 STR_SET_LEN(str,
len);
330 memcpy(RSTRING_PTR(str), buf,
len);
331 SIZED_FREE_N(buf, old_capa);
338rb_debug_rstring_null_ptr(
const char *func)
340 fprintf(stderr,
"%s is returning NULL!! "
341 "SIGSEGV is highly expected to follow immediately.\n"
342 "If you could reproduce, attach your debugger here, "
343 "and look at the passed string.\n",
348static VALUE sym_ascii, sym_turkic, sym_lithuanian, sym_fold;
351get_encoding(
VALUE str)
357mustnot_broken(
VALUE str)
359 if (is_broken_string(str)) {
360 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(STR_ENC_GET(str)));
365mustnot_wchar(
VALUE str)
368 if (rb_enc_mbminlen(enc) > 1) {
369 rb_raise(rb_eArgError,
"wide char encoding: %s", rb_enc_name(enc));
373static VALUE register_fstring(
VALUE str,
bool copy,
bool force_precompute_hash);
375#if SIZEOF_LONG == SIZEOF_VOIDP
376#define PRECOMPUTED_FAKESTR_HASH 1
381BARE_STRING_P(
VALUE str)
386static inline st_index_t
387str_do_hash(
VALUE str)
389 st_index_t h =
rb_memhash((
const void *)RSTRING_PTR(str), RSTRING_LEN(str));
391 if (e && !is_ascii_string(str)) {
398str_store_precomputed_hash(
VALUE str, st_index_t hash)
404 size_t used_bytes = (RSTRING_LEN(str) + TERM_LEN(str));
405 size_t free_bytes = str_embed_capa(str) - used_bytes;
409 memcpy(
RSTRING_END(str) + TERM_LEN(str), &hash,
sizeof(hash));
411 FL_SET(str, STR_PRECOMPUTED_HASH);
424 if (
FL_TEST(str, RSTRING_FSTR))
427 bare = BARE_STRING_P(str);
429 if (STR_EMBED_P(str)) {
434 if (
FL_TEST_RAW(str, STR_SHARED_ROOT | STR_SHARED) == STR_SHARED_ROOT) {
441 rb_str_resize(str, RSTRING_LEN(str));
443 fstr = register_fstring(str,
false,
false);
446 str_replace_shared_without_enc(str, fstr);
453static VALUE fstring_table_obj;
456fstring_concurrent_set_hash(
VALUE str)
458#ifdef PRECOMPUTED_FAKESTR_HASH
462 h = (st_index_t)
RSTRING(str)->as.heap.aux.capa;
479 const char *aptr, *bptr;
486 return (alen == blen &&
488 memcmp(aptr, bptr, alen) == 0);
493 bool force_precompute_hash;
497fstring_concurrent_set_create(
VALUE str,
void *data)
507 long len = RSTRING_LEN(str);
508 long capa =
len +
sizeof(st_index_t);
509 int term_len = TERM_LEN(str);
511 if (arg->force_precompute_hash && STR_EMBEDDABLE_P(
capa, term_len)) {
513 memcpy(RSTRING_PTR(new_str), RSTRING_PTR(str),
len);
514 STR_SET_LEN(new_str, RSTRING_LEN(str));
516 rb_enc_copy(new_str, str);
517 str_store_precomputed_hash(new_str, str_do_hash(str));
521 rb_enc_copy(new_str, str);
522#ifdef PRECOMPUTED_FAKESTR_HASH
523 if (
rb_str_capacity(new_str) >= RSTRING_LEN(str) + term_len +
sizeof(st_index_t)) {
524 str_store_precomputed_hash(new_str, (st_index_t)
RSTRING(str)->as.heap.aux.capa);
538 if (!
OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
541 if (STR_SHARED_P(str)) {
543 str_make_independent(str);
546 if (!BARE_STRING_P(str)) {
552 RBASIC(str)->flags |= RSTRING_FSTR;
554 RB_OBJ_SET_SHAREABLE(str);
568 .hash = fstring_concurrent_set_hash,
569 .cmp = fstring_concurrent_set_cmp,
570 .create = fstring_concurrent_set_create,
575Init_fstring_table(
void)
577 fstring_table_obj = rb_concurrent_set_new(&fstring_concurrent_set_funcs, 8192);
578 rb_gc_register_address(&fstring_table_obj);
582register_fstring(
VALUE str,
bool copy,
bool force_precompute_hash)
586 .force_precompute_hash = force_precompute_hash
589#if SIZEOF_VOIDP == SIZEOF_LONG
593 RSTRING(str)->as.heap.aux.capa = (long)str_do_hash(str);
597 VALUE result = rb_concurrent_set_find_or_insert(&fstring_table_obj, str, &args);
599 RUBY_ASSERT(!rb_objspace_garbage_object_p(result));
611rb_obj_is_fstring_table(
VALUE obj)
615 return obj == fstring_table_obj;
619rb_gc_free_fstring(
VALUE obj)
621 ASSERT_vm_locking_with_barrier();
627 rb_concurrent_set_delete_by_identity(fstring_table_obj, obj);
629 RB_DEBUG_COUNTER_INC(obj_str_fstr);
635rb_fstring_foreach_with_replace(
int (*callback)(
VALUE *str,
void *data),
void *data)
637 if (fstring_table_obj) {
638 rb_concurrent_set_foreach_with_replace(fstring_table_obj, callback, data);
643setup_fake_str(
struct RString *fake_str,
const char *name,
long len,
int encidx)
646 RBASIC_SET_FULL_SHAPE_ID((
VALUE)fake_str, ROOT_SHAPE_ID | SHAPE_ID_LAYOUT_OTHER);
659 return (
VALUE)fake_str;
668 return setup_fake_str(fake_str, name,
len, rb_enc_to_index(enc));
677rb_fstring_new(
const char *ptr,
long len)
679 struct RString fake_str = {RBASIC_INIT};
680 return register_fstring(setup_fake_str(&fake_str,
ptr,
len, ENCINDEX_US_ASCII),
false,
false);
686 struct RString fake_str = {RBASIC_INIT};
687 return register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
false,
false);
691rb_fstring_cstr(
const char *
ptr)
693 return rb_fstring_new(
ptr, strlen(
ptr));
697single_byte_optimizable(
VALUE str)
701 case ENCINDEX_ASCII_8BIT:
702 case ENCINDEX_US_ASCII:
724static inline const char *
725search_nonascii(
const char *p,
const char *e)
733#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
734# if SIZEOF_UINTPTR_T == 8
735# define NONASCII_MASK UINT64_C(0x8080808080808080)
736# elif SIZEOF_UINTPTR_T == 4
737# define NONASCII_MASK UINT32_C(0x80808080)
739# error "don't know what to do."
742# if SIZEOF_UINTPTR_T == 8
743# define NONASCII_MASK ((uintptr_t)0x80808080UL << 32 | (uintptr_t)0x80808080UL)
744# elif SIZEOF_UINTPTR_T == 4
745# define NONASCII_MASK 0x80808080UL
747# error "don't know what to do."
751 if (UNALIGNED_WORD_ACCESS || e - p >= SIZEOF_VOIDP) {
752#if !UNALIGNED_WORD_ACCESS
753 if ((uintptr_t)p % SIZEOF_VOIDP) {
754 int l = SIZEOF_VOIDP - (uintptr_t)p % SIZEOF_VOIDP;
759 case 7:
if (p[-7]&0x80)
return p-7;
760 case 6:
if (p[-6]&0x80)
return p-6;
761 case 5:
if (p[-5]&0x80)
return p-5;
762 case 4:
if (p[-4]&0x80)
return p-4;
764 case 3:
if (p[-3]&0x80)
return p-3;
765 case 2:
if (p[-2]&0x80)
return p-2;
766 case 1:
if (p[-1]&0x80)
return p-1;
771#if defined(HAVE_BUILTIN___BUILTIN_ASSUME_ALIGNED) &&! UNALIGNED_WORD_ACCESS
772#define aligned_ptr(value) \
773 __builtin_assume_aligned((value), sizeof(uintptr_t))
775#define aligned_ptr(value) (value)
778 t = (e - (SIZEOF_VOIDP-1));
780 for (;s < t; s +=
sizeof(uintptr_t)) {
782 memcpy(&word, s,
sizeof(word));
783 if (word & NONASCII_MASK) {
784#ifdef WORDS_BIGENDIAN
785 return (
const char *)s + (nlz_intptr(word&NONASCII_MASK)>>3);
787 return (
const char *)s + (ntz_intptr(word&NONASCII_MASK)>>3);
797 case 7:
if (e[-7]&0x80)
return e-7;
798 case 6:
if (e[-6]&0x80)
return e-6;
799 case 5:
if (e[-5]&0x80)
return e-5;
800 case 4:
if (e[-4]&0x80)
return e-4;
802 case 3:
if (e[-3]&0x80)
return e-3;
803 case 2:
if (e[-2]&0x80)
return e-2;
804 case 1:
if (e[-1]&0x80)
return e-1;
812 const char *e = p +
len;
814 if (rb_enc_to_index(enc) == rb_ascii8bit_encindex()) {
816 p = search_nonascii(p, e);
820 if (rb_enc_asciicompat(enc)) {
821 p = search_nonascii(p, e);
824 int ret = rb_enc_precise_mbclen(p, e, enc);
828 p = search_nonascii(p, e);
834 int ret = rb_enc_precise_mbclen(p, e, enc);
850 if (rb_enc_to_index(enc) == rb_ascii8bit_encindex()) {
853 p = search_nonascii(p, e);
857 else if (rb_enc_asciicompat(enc)) {
858 p = search_nonascii(p, e);
864 int ret = rb_enc_precise_mbclen(p, e, enc);
871 p = search_nonascii(p, e);
877 int ret = rb_enc_precise_mbclen(p, e, enc);
902 rb_enc_set_index(str1, rb_enc_get_index(str2));
910rb_enc_cr_str_copy_for_substr(
VALUE dest,
VALUE src)
915 str_enc_copy(dest, src);
916 if (RSTRING_LEN(dest) == 0) {
917 if (!rb_enc_asciicompat(STR_ENC_GET(src)))
928 if (!rb_enc_asciicompat(STR_ENC_GET(src)) ||
929 search_nonascii(RSTRING_PTR(dest),
RSTRING_END(dest)))
940rb_enc_cr_str_exact_copy(
VALUE dest,
VALUE src)
942 str_enc_copy(dest, src);
949 return coderange_scan(RSTRING_PTR(str), RSTRING_LEN(str), enc);
955 return enc_coderange_scan(str, enc);
959rbimpl_enc_str_coderange_scan(
VALUE str)
961 int cr = enc_coderange_scan(str, get_encoding(str));
966#undef rb_enc_str_coderange
973 cr = rbimpl_enc_str_coderange_scan(str);
977#define rb_enc_str_coderange rb_enc_str_coderange_inline
980rb_enc_str_asciicompat(
VALUE str)
983 return rb_str_encindex_fastpath(encindex) || rb_enc_asciicompat(rb_enc_get_from_index(encindex));
991 return rb_enc_str_asciicompat(str) && is_ascii_string(str);
1000str_mod_check(
VALUE s,
const char *p,
long len)
1002 if (RSTRING_PTR(s) != p || RSTRING_LEN(s) !=
len){
1008str_capacity(
VALUE str,
const int termlen)
1010 if (STR_EMBED_P(str)) {
1011 return str_embed_capa(str) - termlen;
1013 else if (
FL_ANY_RAW(str, STR_SHARED|STR_NOFREE)) {
1017 return RSTRING(str)->as.heap.aux.capa;
1024 return str_capacity(str, TERM_LEN(str));
1028must_not_null(
const char *
ptr)
1031 rb_raise(rb_eArgError,
"NULL pointer given");
1036str_alloc_embed(
VALUE klass,
size_t capa)
1038 size_t size = rb_str_embed_size(
capa, 0);
1045 str->as.embed.ary[0] = 0;
1051str_alloc_heap(
VALUE klass)
1056 str->as.heap.aux.capa = 0;
1057 str->as.heap.ptr = NULL;
1063empty_str_alloc(
VALUE klass)
1065 RUBY_DTRACE_CREATE_HOOK(STRING, 0);
1066 VALUE str = str_alloc_embed(klass, 0);
1067 memset(
RSTRING(str)->
as.embed.ary, 0, str_embed_capa(str));
1078 rb_raise(rb_eArgError,
"negative string size (or size too big)");
1082 enc = rb_ascii8bit_encoding();
1085 RUBY_DTRACE_CREATE_HOOK(STRING,
len);
1087 int termlen = rb_enc_mbminlen(enc);
1089 if (STR_EMBEDDABLE_P(
len, termlen)) {
1090 str = str_alloc_embed(klass,
len + termlen);
1096 str = str_alloc_heap(klass);
1102 rb_xmalloc_mul_add_mul(
sizeof(
char),
len,
sizeof(
char), termlen);
1105 rb_enc_raw_set(str, enc);
1108 memcpy(RSTRING_PTR(str),
ptr,
len);
1111 memset(RSTRING_PTR(str), 0,
len);
1114 STR_SET_LEN(str,
len);
1115 TERM_FILL(RSTRING_PTR(str) +
len, termlen);
1122 return str_enc_new(klass,
ptr,
len, rb_ascii8bit_encoding());
1157 __msan_unpoison_string(
ptr);
1177 if (rb_enc_mbminlen(enc) != 1) {
1178 rb_raise(rb_eArgError,
"wchar encoding given");
1180 return rb_enc_str_new(
ptr, strlen(
ptr), enc);
1184str_new_static(
VALUE klass,
const char *
ptr,
long len,
int encindex)
1189 rb_raise(rb_eArgError,
"negative string size (or size too big)");
1193 str = str_enc_new(klass,
ptr,
len, rb_enc_from_index(encindex));
1196 RUBY_DTRACE_CREATE_HOOK(STRING,
len);
1197 str = str_alloc_heap(klass);
1201 RBASIC(str)->flags |= STR_NOFREE;
1202 rb_enc_associate_index(str, encindex);
1231static VALUE str_cat_conv_enc_opts(
VALUE newstr,
long ofs,
const char *
ptr,
long len,
1233 int ecflags,
VALUE ecopts);
1238 int encidx = rb_enc_to_index(enc);
1239 if (rb_enc_get_index(str) == encidx)
1240 return is_ascii_string(str);
1251 if (!to)
return str;
1252 if (!from) from = rb_enc_get(str);
1253 if (from == to)
return str;
1254 if ((rb_enc_asciicompat(to) && is_enc_ascii_string(str, from)) ||
1255 rb_is_ascii8bit_enc(to)) {
1256 if (STR_ENC_GET(str) != to) {
1258 rb_enc_associate(str, to);
1265 from, to, ecflags, ecopts);
1266 if (
NIL_P(newstr)) {
1274rb_str_cat_conv_enc_opts(
VALUE newstr,
long ofs,
const char *
ptr,
long len,
1279 olen = RSTRING_LEN(newstr);
1280 if (ofs < -olen || olen < ofs)
1282 if (ofs < 0) ofs += olen;
1284 STR_SET_LEN(newstr, ofs);
1288 rb_str_modify(newstr);
1289 return str_cat_conv_enc_opts(newstr, ofs,
ptr,
len, from,
1297 STR_SET_LEN(str, 0);
1298 rb_enc_associate(str, enc);
1304str_cat_conv_enc_opts(
VALUE newstr,
long ofs,
const char *
ptr,
long len,
1306 int ecflags,
VALUE ecopts)
1311 VALUE econv_wrapper;
1312 const unsigned char *start, *sp;
1313 unsigned char *dest, *dp;
1314 size_t converted_output = (size_t)ofs;
1319 RBASIC_CLEAR_CLASS(econv_wrapper);
1321 if (!ec)
return Qnil;
1324 sp = (
unsigned char*)
ptr;
1326 while ((dest = (
unsigned char*)RSTRING_PTR(newstr)),
1327 (dp = dest + converted_output),
1331 size_t converted_input = sp - start;
1332 size_t rest =
len - converted_input;
1333 converted_output = dp - dest;
1335 if (converted_input && converted_output &&
1336 rest < (LONG_MAX / converted_output)) {
1337 rest = (rest * converted_output) / converted_input;
1342 olen += rest < 2 ? 2 : rest;
1343 rb_str_resize(newstr, olen);
1350 len = dp - (
unsigned char*)RSTRING_PTR(newstr);
1352 rb_enc_associate(newstr, to);
1371 const int eidx = rb_enc_to_index(eenc);
1374 return rb_enc_str_new(
ptr,
len, eenc);
1378 if ((eidx == rb_ascii8bit_encindex()) ||
1379 (eidx == rb_usascii_encindex() && search_nonascii(
ptr,
ptr +
len))) {
1383 ienc = rb_default_internal_encoding();
1384 if (!ienc || eenc == ienc) {
1385 return rb_enc_str_new(
ptr,
len, eenc);
1389 if ((eidx == rb_ascii8bit_encindex()) ||
1390 (eidx == rb_usascii_encindex()) ||
1391 (rb_enc_asciicompat(eenc) && !search_nonascii(
ptr,
ptr +
len))) {
1392 return rb_enc_str_new(
ptr,
len, ienc);
1395 str = rb_enc_str_new(NULL, 0, ienc);
1398 if (
NIL_P(rb_str_cat_conv_enc_opts(str, 0,
ptr,
len, eenc, 0,
Qnil))) {
1399 rb_str_initialize(str,
ptr,
len, eenc);
1407 int eidx = rb_enc_to_index(eenc);
1408 if (eidx == rb_usascii_encindex() &&
1409 !is_ascii_string(str)) {
1410 rb_enc_associate_index(str, rb_ascii8bit_encindex());
1413 rb_enc_associate_index(str, eidx);
1472str_replace_shared_without_enc(
VALUE str2,
VALUE str)
1474 const int termlen = TERM_LEN(str);
1479 if (str_embed_capa(str2) >=
len + termlen) {
1480 char *ptr2 =
RSTRING(str2)->as.embed.ary;
1481 STR_SET_EMBED(str2);
1482 memcpy(ptr2, RSTRING_PTR(str),
len);
1483 TERM_FILL(ptr2+
len, termlen);
1487 if (STR_SHARED_P(str)) {
1488 root =
RSTRING(str)->as.heap.aux.shared;
1497 if (!STR_EMBED_P(str2) && !
FL_TEST_RAW(str2, STR_SHARED|STR_NOFREE)) {
1499 rb_fatal(
"about to free a possible shared root");
1501 char *ptr2 = STR_HEAP_PTR(str2);
1503 SIZED_FREE_N(ptr2, STR_HEAP_SIZE(str2));
1506 FL_SET(str2, STR_NOEMBED);
1508 STR_SET_SHARED(str2, root);
1511 STR_SET_LEN(str2,
len);
1519 str_replace_shared_without_enc(str2, str);
1520 rb_enc_cr_str_exact_copy(str2, str);
1527 return str_replace_shared(str_alloc_heap(klass), str);
1544rb_str_new_frozen_String(
VALUE orig)
1552rb_str_frozen_bare_string(
VALUE orig)
1554 if (RB_LIKELY(BARE_STRING_P(orig) &&
OBJ_FROZEN_RAW(orig)))
return orig;
1559rb_str_tmp_frozen_acquire(
VALUE orig)
1562 return str_new_frozen_buffer(0, orig, FALSE);
1566rb_str_tmp_frozen_no_embed_acquire(
VALUE orig)
1568 if (
OBJ_FROZEN_RAW(orig) && !STR_EMBED_P(orig) && !rb_str_reembeddable_p(orig))
return orig;
1569 if (STR_SHARED_P(orig) && !STR_EMBED_P(
RSTRING(orig)->
as.heap.aux.shared))
return rb_str_tmp_frozen_acquire(orig);
1571 VALUE str = str_alloc_heap(0);
1574 FL_SET(str, STR_SHARED_ROOT);
1576 size_t capa = str_capacity(orig, TERM_LEN(orig));
1582 if (STR_EMBED_P(orig) ||
FL_TEST_RAW(orig, STR_SHARED | STR_SHARED_ROOT | RSTRING_FSTR)) {
1583 RSTRING(str)->as.heap.ptr = rb_xmalloc_mul_add_mul(
sizeof(
char),
capa,
sizeof(
char), TERM_LEN(orig));
1590 RBASIC(str)->flags |=
RBASIC(orig)->flags & STR_NOFREE;
1591 RBASIC(orig)->flags &= ~STR_NOFREE;
1592 STR_SET_SHARED(orig, str);
1594 RB_OBJ_SET_SHAREABLE(str);
1600 RSTRING(str)->as.heap.aux.capa =
capa + (TERM_LEN(orig) - TERM_LEN(str));
1606rb_str_tmp_frozen_release(
VALUE orig,
VALUE tmp)
1611 if (STR_EMBED_P(tmp)) {
1614 else if (
FL_TEST_RAW(orig, STR_SHARED | STR_TMPLOCK) == STR_TMPLOCK &&
1620 RUBY_ASSERT(RSTRING_LEN(orig) == RSTRING_LEN(tmp));
1624 RSTRING(orig)->as.heap.aux.capa =
RSTRING(tmp)->as.heap.aux.capa;
1625 RBASIC(orig)->flags |=
RBASIC(tmp)->flags & STR_NOFREE;
1630 STR_SET_LEN(tmp, 0);
1638 return str_new_frozen_buffer(klass, orig, TRUE);
1648 VALUE str = str_alloc_heap(klass);
1649 STR_SET_LEN(str, RSTRING_LEN(orig));
1650 RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig);
1651 RSTRING(str)->as.heap.aux.capa =
RSTRING(orig)->as.heap.aux.capa;
1652 RBASIC(str)->flags |=
RBASIC(orig)->flags & STR_NOFREE;
1653 RBASIC(orig)->flags &= ~STR_NOFREE;
1654 STR_SET_SHARED(orig, str);
1661str_new_frozen_buffer(
VALUE klass,
VALUE orig,
int copy_encoding)
1665 long len = RSTRING_LEN(orig);
1666 rb_encoding *enc = copy_encoding ? STR_ENC_GET(orig) : rb_ascii8bit_encoding();
1667 int termlen = copy_encoding ? TERM_LEN(orig) : 1;
1669 if (STR_EMBED_P(orig) || STR_EMBEDDABLE_P(
len, termlen)) {
1670 str = str_enc_new(klass, RSTRING_PTR(orig),
len, enc);
1676 long ofs =
RSTRING(orig)->as.heap.ptr - RSTRING_PTR(
shared);
1677 long rest = RSTRING_LEN(
shared) - ofs - RSTRING_LEN(orig);
1683 if ((ofs > 0) || (rest > 0) ||
1686 str = str_new_shared(klass,
shared);
1688 RSTRING(str)->as.heap.ptr += ofs;
1689 STR_SET_LEN(str, RSTRING_LEN(str) - (ofs + rest));
1697 else if (STR_EMBEDDABLE_P(RSTRING_LEN(orig), TERM_LEN(orig))) {
1698 str = str_alloc_embed(klass, RSTRING_LEN(orig) + TERM_LEN(orig));
1700 memcpy(RSTRING_PTR(str), RSTRING_PTR(orig), RSTRING_LEN(orig));
1701 STR_SET_LEN(str, RSTRING_LEN(orig));
1707 str = str_new(klass, RSTRING_PTR(orig), RSTRING_LEN(orig));
1710 str = heap_str_make_shared(klass, orig);
1715 if (copy_encoding) rb_enc_cr_str_exact_copy(str, orig);
1727str_new_empty_String(
VALUE str)
1730 rb_enc_copy(v, str);
1734#define STR_BUF_MIN_SIZE 63
1739 if (STR_EMBEDDABLE_P(
capa, 1)) {
1747 RSTRING(str)->as.heap.ptr[0] =
'\0';
1767 return str_new(0, 0,
len);
1773 if (STR_EMBED_P(str)) {
1774 RB_DEBUG_COUNTER_INC(obj_str_embed);
1776 else if (
FL_TEST(str, STR_SHARED | STR_NOFREE)) {
1777 (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared,
FL_TEST(str, STR_SHARED));
1778 (void)RB_DEBUG_COUNTER_INC_IF(obj_str_shared,
FL_TEST(str, STR_NOFREE));
1781 RB_DEBUG_COUNTER_INC(obj_str_ptr);
1782 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
1787rb_str_memsize(
VALUE str)
1789 if (
FL_TEST(str, STR_NOEMBED|STR_SHARED|STR_NOFREE) == STR_NOEMBED) {
1790 return STR_HEAP_SIZE(str);
1800 return rb_convert_type_with_id(str,
T_STRING,
"String", idTo_str);
1803static inline void str_discard(
VALUE str);
1804static void str_shared_replace(
VALUE str,
VALUE str2);
1809 if (str != str2) str_shared_replace(str, str2);
1820 enc = STR_ENC_GET(str2);
1823 termlen = rb_enc_mbminlen(enc);
1825 STR_SET_LEN(str, RSTRING_LEN(str2));
1827 if (str_embed_capa(str) >= RSTRING_LEN(str2) + termlen) {
1829 memcpy(RSTRING_PTR(str), RSTRING_PTR(str2), (
size_t)RSTRING_LEN(str2) + termlen);
1830 rb_enc_associate(str, enc);
1834 if (STR_EMBED_P(str2)) {
1836 long len = RSTRING_LEN(str2);
1839 char *new_ptr =
ALLOC_N(
char,
len + termlen);
1840 memcpy(new_ptr,
RSTRING(str2)->
as.embed.ary,
len + termlen);
1841 RSTRING(str2)->as.heap.ptr = new_ptr;
1842 STR_SET_LEN(str2,
len);
1844 STR_SET_NOEMBED(str2);
1847 STR_SET_NOEMBED(str);
1849 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
1851 if (
FL_TEST(str2, STR_SHARED)) {
1853 STR_SET_SHARED(str,
shared);
1856 RSTRING(str)->as.heap.aux.capa =
RSTRING(str2)->as.heap.aux.capa;
1860 STR_SET_EMBED(str2);
1861 RSTRING_PTR(str2)[0] = 0;
1862 STR_SET_LEN(str2, 0);
1863 rb_enc_associate(str, enc);
1877 return rb_obj_as_string_result(str, obj);
1893 len = RSTRING_LEN(str2);
1894 if (STR_SHARED_P(str2)) {
1897 STR_SET_NOEMBED(str);
1898 STR_SET_LEN(str,
len);
1899 RSTRING(str)->as.heap.ptr = RSTRING_PTR(str2);
1900 STR_SET_SHARED(str,
shared);
1901 rb_enc_cr_str_exact_copy(str, str2);
1904 str_replace_shared(str, str2);
1913 size_t size = rb_str_embed_size(
capa, 0);
1929 str->as.heap.aux.capa = 0;
1930 str->as.heap.ptr = NULL;
1940 encidx = rb_enc_get_index(str);
1941 flags &= ~ENCODING_MASK;
1944 if (encidx) rb_enc_associate_index(dup, encidx);
1953 long len = RSTRING_LEN(str);
1958 STR_SET_LEN(dup, RSTRING_LEN(str));
1959 str_duplicate_setup_encoding(str, dup, flags);
1968 root =
RSTRING(str)->as.heap.aux.shared;
1971 root = str = str_new_frozen(klass, str);
1977 RSTRING(dup)->as.heap.ptr = RSTRING_PTR(str);
1979 STR_SET_SHARED(dup, root);
1980 flags |= RSTRING_NOEMBED | STR_SHARED;
1982 STR_SET_LEN(dup, RSTRING_LEN(str));
1983 str_duplicate_setup_encoding(str, dup, flags);
1990 if (STR_EMBED_P(str) && rb_str_embed_size(RSTRING_LEN(str), 1) <= STR_COPY_MAX_EMBED_SIZE) {
1991 dup = str_alloc_embed(klass, RSTRING_LEN(str) + TERM_LEN(str));
1993 str_duplicate_setup_embed(klass, str, dup);
1996 dup = str_alloc_heap(klass);
1998 str_duplicate_setup_heap(klass, str, dup);
2012rb_str_dup_m(
VALUE str)
2014 if (LIKELY(BARE_STRING_P(str))) {
2025 RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
2032 RUBY_DTRACE_CREATE_HOOK(STRING, RSTRING_LEN(str));
2036 new_str = ec_str_alloc_embed(ec, klass, RSTRING_LEN(str) + TERM_LEN(str));
2037 str_duplicate_setup_embed(klass, str, new_str);
2040 new_str = ec_str_alloc_heap(ec, klass);
2041 str_duplicate_setup_heap(klass, str, new_str);
2051rb_zjit_str_resurrect_fastpath(
VALUE str,
bool chilled,
size_t *size_out,
2053 long *len_out,
size_t *byte_size_out)
2057 if (!STR_EMBED_P(str))
return false;
2059 long len = RSTRING_LEN(str);
2060 long termlen = TERM_LEN(str);
2061 size_t size = rb_str_embed_size(
len + termlen, 0);
2062 if (!rb_gc_size_allocatable_p(size))
return false;
2070 flags &= ~FL_FREEZE;
2072 if (chilled) flags |= STR_CHILLED;
2077 *byte_size_out = (size_t)(
len + termlen);
2083rb_str_with_debug_created_info(
VALUE str,
VALUE path,
int line)
2085 VALUE debug_info = rb_ary_new_from_args(2, path,
INT2FIX(line));
2109 static ID keyword_ids[2];
2110 VALUE orig, opt, venc, vcapa;
2115 if (!keyword_ids[0]) {
2116 keyword_ids[0] = rb_id_encoding();
2117 CONST_ID(keyword_ids[1],
"capacity");
2125 if (!UNDEF_P(venc) && !
NIL_P(venc)) {
2126 enc = rb_to_encoding(venc);
2128 if (!UNDEF_P(vcapa) && !
NIL_P(vcapa)) {
2131 int termlen = enc ? rb_enc_mbminlen(enc) : 1;
2133 if (
capa < STR_BUF_MIN_SIZE) {
2134 capa = STR_BUF_MIN_SIZE;
2138 len = RSTRING_LEN(orig);
2142 if (orig == str) n = 0;
2144 str_modifiable(str);
2145 if (STR_EMBED_P(str) ||
FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2147 const size_t size = (size_t)
capa + termlen;
2148 const char *
const old_ptr = RSTRING_PTR(str);
2149 const size_t osize = RSTRING_LEN(str) + TERM_LEN(str);
2150 char *new_ptr =
ALLOC_N(
char, size);
2151 if (STR_EMBED_P(str))
RUBY_ASSERT((
long)osize <= str_embed_capa(str));
2152 memcpy(new_ptr, old_ptr, osize < size ? osize : size);
2154 RSTRING(str)->as.heap.ptr = new_ptr;
2156 else if (STR_HEAP_SIZE(str) != (
size_t)
capa + termlen) {
2157 SIZED_REALLOC_N(
RSTRING(str)->
as.heap.ptr,
char,
2158 (
size_t)
capa + termlen, STR_HEAP_SIZE(str));
2160 STR_SET_LEN(str,
len);
2163 memcpy(
RSTRING(str)->
as.heap.ptr, RSTRING_PTR(orig),
len);
2164 rb_enc_cr_str_exact_copy(str, orig);
2166 FL_SET(str, STR_NOEMBED);
2173 rb_enc_associate(str, enc);
2185rb_str_s_new(
int argc,
VALUE *argv,
VALUE klass)
2191 static ID keyword_ids[2];
2201 keyword_ids[0] = rb_id_encoding();
2202 CONST_ID(keyword_ids[1],
"capacity");
2204 encoding = kwargs[0];
2205 capacity = kwargs[1];
2214 if (UNDEF_P(encoding)) {
2216 encoding = rb_obj_encoding(orig);
2220 if (!UNDEF_P(encoding)) {
2221 enc = rb_to_encoding(encoding);
2225 if (UNDEF_P(capacity)) {
2227 VALUE empty_str = str_new(klass,
"", 0);
2229 rb_enc_associate(empty_str, enc);
2233 VALUE copy = str_duplicate(klass, orig);
2234 rb_enc_associate(copy, enc);
2247 if (orig_capa >
capa) {
2252 VALUE str = str_enc_new(klass, NULL,
capa, enc);
2253 STR_SET_LEN(str, 0);
2264#define is_utf8_lead_byte(c) (((c)&0xC0) != 0x80)
2279static inline uintptr_t
2280count_utf8_lead_bytes_with_word(
const uintptr_t *s)
2285 d = (d>>6) | (~d>>7);
2286 d &= NONASCII_MASK >> 7;
2289#if defined(HAVE_BUILTIN___BUILTIN_POPCOUNT) && defined(__POPCNT__)
2291 return rb_popcount_intptr(d);
2295# if SIZEOF_VOIDP == 8
2304enc_strlen(
const char *p,
const char *e,
rb_encoding *enc,
int cr)
2310 long diff = (long)(e - p);
2311 return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
2316 if ((
int)
sizeof(uintptr_t) * 2 < e - p) {
2317 const uintptr_t *s, *t;
2318 const uintptr_t lowbits =
sizeof(uintptr_t) - 1;
2319 s = (
const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
2320 t = (
const uintptr_t*)(~lowbits & (uintptr_t)e);
2321 while (p < (
const char *)s) {
2322 if (is_utf8_lead_byte(*p))
len++;
2326 len += count_utf8_lead_bytes_with_word(s);
2329 p = (
const char *)s;
2332 if (is_utf8_lead_byte(*p))
len++;
2338 else if (rb_enc_asciicompat(enc)) {
2342 q = search_nonascii(p, e);
2347 p += rb_enc_fast_mbclen(p, e, enc);
2353 q = search_nonascii(p, e);
2358 p += rb_enc_mbclen(p, e, enc);
2365 for (c=0; p<e; c++) {
2366 p += rb_enc_mbclen(p, e, enc);
2381rb_enc_strlen_cr(
const char *p,
const char *e,
rb_encoding *enc,
int *cr)
2389 long diff = (long)(e - p);
2390 return diff / rb_enc_mbminlen(enc) + !!(diff % rb_enc_mbminlen(enc));
2392 else if (rb_enc_asciicompat(enc)) {
2395 q = search_nonascii(p, e);
2402 ret = rb_enc_precise_mbclen(p, e, enc);
2417 for (c=0; p<e; c++) {
2418 ret = rb_enc_precise_mbclen(p, e, enc);
2425 if (p + rb_enc_mbminlen(enc) <= e)
2426 p += rb_enc_mbminlen(enc);
2442 if (single_byte_optimizable(str))
return RSTRING_LEN(str);
2443 if (!enc) enc = STR_ENC_GET(str);
2444 p = RSTRING_PTR(str);
2449 long n = rb_enc_strlen_cr(p, e, enc, &cr);
2454 return enc_strlen(p, e, enc, cr);
2461 return str_strlen(str, NULL);
2475 return LONG2NUM(str_strlen(str, NULL));
2487rb_str_bytesize(
VALUE str)
2506rb_str_empty(
VALUE str)
2508 return RBOOL(RSTRING_LEN(str) == 0);
2527 const char *ptr1, *ptr2;
2533 enc = rb_enc_check_str(str1, str2);
2536 termlen = rb_enc_mbminlen(enc);
2537 if (len1 > LONG_MAX - len2) {
2538 rb_raise(rb_eArgError,
"string size too big");
2540 str3 = str_enc_new(
rb_cString, 0, len1+len2, enc);
2541 ptr3 = RSTRING_PTR(str3);
2542 memcpy(ptr3, ptr1, len1);
2543 memcpy(ptr3+len1, ptr2, len2);
2544 TERM_FILL(&ptr3[len1+len2], termlen);
2560 MAYBE_UNUSED(
char) *ptr1, *ptr2;
2563 int enc1 = rb_enc_get_index(str1);
2564 int enc2 = rb_enc_get_index(str2);
2569 else if (enc2 < 0) {
2572 else if (enc1 != enc2) {
2575 else if (len1 > LONG_MAX - len2) {
2609 rb_enc_copy(str2, str);
2614 rb_raise(rb_eArgError,
"negative argument");
2616 if (RSTRING_LEN(str) == 1 && RSTRING_PTR(str)[0] == 0) {
2617 if (STR_EMBEDDABLE_P(
len, 1)) {
2619 memset(RSTRING_PTR(str2), 0,
len + 1);
2626 STR_SET_LEN(str2,
len);
2627 rb_enc_copy(str2, str);
2630 if (
len && LONG_MAX/
len < RSTRING_LEN(str)) {
2631 rb_raise(rb_eArgError,
"argument too big");
2634 len *= RSTRING_LEN(str);
2635 termlen = TERM_LEN(str);
2637 ptr2 = RSTRING_PTR(str2);
2639 n = RSTRING_LEN(str);
2640 memcpy(ptr2, RSTRING_PTR(str), n);
2641 while (n <=
len/2) {
2642 memcpy(ptr2 + n, ptr2, n);
2645 memcpy(ptr2 + n, ptr2,
len-n);
2647 STR_SET_LEN(str2,
len);
2648 TERM_FILL(&ptr2[
len], termlen);
2649 rb_enc_cr_str_copy_for_substr(str2, str);
2688rb_check_lockedtmp(
VALUE str)
2690 if (
FL_TEST(str, STR_TMPLOCK)) {
2697#define STR_UNMODIFIABLE_MASK (FL_FREEZE | STR_TMPLOCK | STR_CHILLED)
2699str_modifiable(
VALUE str)
2703 if (RB_UNLIKELY(
FL_ANY_RAW(str, STR_UNMODIFIABLE_MASK))) {
2704 if (CHILLED_STRING_P(str)) {
2705 CHILLED_STRING_MUTATED(str);
2707 rb_check_lockedtmp(str);
2708 rb_check_frozen(str);
2713str_dependent_p(
VALUE str)
2715 if (STR_EMBED_P(str) || !
FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2725#define STR_DEPENDANT_MASK (STR_UNMODIFIABLE_MASK | STR_SHARED | STR_NOFREE)
2727str_independent(
VALUE str)
2731 if (RB_UNLIKELY(
FL_ANY_RAW(str, STR_DEPENDANT_MASK))) {
2732 str_modifiable(str);
2733 return !str_dependent_p(str);
2739str_make_independent_expand(
VALUE str,
long len,
long expand,
const int termlen)
2749 if (!STR_EMBED_P(str) && str_embed_capa(str) >=
capa + termlen) {
2754 STR_SET_LEN(str,
len);
2759 oldptr = RSTRING_PTR(str);
2761 memcpy(
ptr, oldptr,
len);
2763 if (
FL_TEST_RAW(str, STR_NOEMBED|STR_NOFREE|STR_SHARED) == STR_NOEMBED) {
2764 SIZED_FREE_N(oldptr, STR_HEAP_SIZE(str));
2766 STR_SET_NOEMBED(str);
2767 FL_UNSET(str, STR_SHARED|STR_NOFREE);
2768 TERM_FILL(
ptr +
len, termlen);
2770 STR_SET_LEN(str,
len);
2777 if (!str_independent(str))
2778 str_make_independent(str);
2787 int termlen = TERM_LEN(str);
2788 long len = RSTRING_LEN(str);
2791 rb_raise(rb_eArgError,
"negative expanding string size");
2793 if (expand >= LONG_MAX -
len) {
2794 rb_raise(rb_eArgError,
"string size too big");
2797 if (!str_independent(str)) {
2798 str_make_independent_expand(str,
len, expand, termlen);
2800 else if (expand > 0) {
2801 RESIZE_CAPA_TERM(str,
len + expand, termlen);
2808str_modify_keep_cr(
VALUE str)
2810 if (!str_independent(str))
2811 str_make_independent(str);
2818str_discard(
VALUE str)
2820 str_modifiable(str);
2821 if (!STR_EMBED_P(str) && !
FL_TEST(str, STR_SHARED|STR_NOFREE)) {
2822 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
2823 RSTRING(str)->as.heap.ptr = 0;
2824 STR_SET_LEN(str, 0);
2831 int encindex = rb_enc_get_index(str);
2833 if (RB_UNLIKELY(encindex == -1)) {
2837 if (RB_LIKELY(rb_str_encindex_fastpath(encindex))) {
2842 if (!rb_enc_asciicompat(enc)) {
2864 return RSTRING_PTR(str);
2868str_null_char(
const char *s,
long len,
const int minlen,
rb_encoding *enc)
2870 const char *e = s +
len;
2872 for (; s + minlen <= e; s += rb_enc_mbclen(s, e, enc)) {
2873 if (zero_filled(s, minlen))
return s;
2879str_fill_term(
VALUE str,
char *s,
long len,
int termlen)
2884 if (str_dependent_p(str)) {
2885 if (!zero_filled(s +
len, termlen))
2886 str_make_independent_expand(str,
len, 0L, termlen);
2889 TERM_FILL(s +
len, termlen);
2892 return RSTRING_PTR(str);
2896rb_str_change_terminator_length(
VALUE str,
const int oldtermlen,
const int termlen)
2898 long capa = str_capacity(str, oldtermlen) + oldtermlen;
2899 long len = RSTRING_LEN(str);
2903 rb_check_lockedtmp(str);
2904 str_make_independent_expand(str,
len, 0L, termlen);
2906 else if (str_dependent_p(str)) {
2907 if (termlen > oldtermlen)
2908 str_make_independent_expand(str,
len, 0L, termlen);
2911 if (!STR_EMBED_P(str)) {
2916 if (termlen > oldtermlen) {
2917 TERM_FILL(RSTRING_PTR(str) +
len, termlen);
2925str_null_check(
VALUE str,
int *w)
2927 char *s = RSTRING_PTR(str);
2928 long len = RSTRING_LEN(str);
2931 if (RB_UNLIKELY(!rb_str_enc_fastpath(str))) {
2933 minlen = rb_enc_mbminlen(enc);
2937 if (str_null_char(s,
len, minlen, enc)) {
2940 return str_fill_term(str, s,
len, minlen);
2945 if (!s || memchr(s, 0,
len)) {
2949 s = str_fill_term(str, s,
len, minlen);
2954static char *str_to_cstr(
VALUE str);
2957rb_str_null_check(
VALUE str)
2965 if (RB_LIKELY(rb_str_enc_fastpath(str))) {
2966 if (!s || memchr(s, 0,
len)) {
2967 rb_raise(rb_eArgError,
"string contains null byte");
2978rb_str_to_cstr(
VALUE str)
2981 return str_null_check(str, &w);
2988 return str_to_cstr(str);
2992str_to_cstr(
VALUE str)
2995 char *s = str_null_check(str, &w);
2998 rb_raise(rb_eArgError,
"string contains null char");
3000 rb_raise(rb_eArgError,
"string contains null byte");
3006rb_str_fill_terminator(
VALUE str,
const int newminlen)
3008 char *s = RSTRING_PTR(str);
3009 long len = RSTRING_LEN(str);
3010 return str_fill_term(str, s,
len, newminlen);
3016 str = rb_check_convert_type_with_id(str,
T_STRING,
"String", idTo_str);
3042str_nth_len(
const char *p,
const char *e,
long *nthp,
rb_encoding *enc)
3051 else if (rb_enc_asciicompat(enc)) {
3052 const char *p2, *e2;
3055 while (p < e && 0 < nth) {
3061 p2 = search_nonascii(p, e2);
3069 n = rb_enc_mbclen(p, e, enc);
3080 while (p < e && nth--) {
3081 p += rb_enc_mbclen(p, e, enc);
3092 return str_nth_len(p, e, &nth, enc);
3096str_nth(
const char *p,
const char *e,
long nth,
rb_encoding *enc,
int singlebyte)
3101 p = str_nth_len(p, e, &nth, enc);
3110str_offset(
const char *p,
const char *e,
long nth,
rb_encoding *enc,
int singlebyte)
3112 const char *pp = str_nth(p, e, nth, enc, singlebyte);
3113 if (!pp)
return e - p;
3120 return str_offset(RSTRING_PTR(str),
RSTRING_END(str), pos,
3121 STR_ENC_GET(str), single_byte_optimizable(str));
3126str_utf8_nth(
const char *p,
const char *e,
long *nthp)
3129 if ((
int)SIZEOF_VOIDP * 2 < e - p && (
int)SIZEOF_VOIDP * 2 < nth) {
3130 const uintptr_t *s, *t;
3131 const uintptr_t lowbits = SIZEOF_VOIDP - 1;
3132 s = (
const uintptr_t*)(~lowbits & ((uintptr_t)p + lowbits));
3133 t = (
const uintptr_t*)(~lowbits & (uintptr_t)e);
3134 while (p < (
const char *)s) {
3135 if (is_utf8_lead_byte(*p)) nth--;
3139 nth -= count_utf8_lead_bytes_with_word(s);
3141 }
while (s < t && (
int)SIZEOF_VOIDP <= nth);
3145 if (is_utf8_lead_byte(*p)) {
3146 if (nth == 0)
break;
3156str_utf8_offset(
const char *p,
const char *e,
long nth)
3158 const char *pp = str_utf8_nth(p, e, &nth);
3167 if (single_byte_optimizable(str) || pos < 0)
3170 const char *p = RSTRING_PTR(str);
3171 return enc_strlen(p, p + pos, STR_ENC_GET(str),
ENC_CODERANGE(str));
3176str_subseq(
VALUE str,
long beg,
long len)
3184 const int termlen = TERM_LEN(str);
3185 if (!SHARABLE_SUBSTRING_P(str, beg,
len)) {
3186 str2 = rb_enc_str_new(RSTRING_PTR(str) + beg,
len, rb_str_enc_get(str));
3196 const bool root_available = STR_SHARED_P(str) ||
3198 const size_t max_embed_size = root_available ?
3199 rb_gc_size_slot_size(
sizeof(
struct RString)) : STR_COPY_MAX_EMBED_SIZE;
3200 const size_t embed_size = rb_str_embed_size(
len, termlen);
3202 if (embed_size <= max_embed_size && rb_gc_size_allocatable_p(embed_size)) {
3204 char *ptr2 =
RSTRING(str2)->as.embed.ary;
3205 memcpy(ptr2, RSTRING_PTR(str) + beg,
len);
3206 TERM_FILL(ptr2 +
len, termlen);
3208 STR_SET_LEN(str2,
len);
3217 str_replace_shared(str2, str);
3223 RSTRING(str2)->as.heap.ptr += beg;
3224 if (RSTRING_LEN(str2) >
len) {
3225 STR_SET_LEN(str2,
len);
3235 VALUE str2 = str_subseq(str, beg,
len);
3236 rb_enc_cr_str_copy_for_substr(str2, str);
3245 const long blen = RSTRING_LEN(str);
3247 const char *p, *s = RSTRING_PTR(str), *e = s + blen;
3249 if (
len < 0)
return 0;
3250 if (beg < 0 && -beg < 0)
return 0;
3254 if (single_byte_optimizable(str)) {
3255 if (beg > blen)
return 0;
3258 if (beg < 0)
return 0;
3260 if (
len > blen - beg)
3262 if (
len < 0)
return 0;
3267 if (
len > -beg)
len = -beg;
3271 while (beg-- >
len && (e = rb_enc_prev_char(s, e, e, enc)) != 0);
3274 while (
len-- > 0 && (p = rb_enc_prev_char(s, p, e, enc)) != 0);
3280 slen = str_strlen(str, enc);
3282 if (beg < 0)
return 0;
3284 if (
len == 0)
goto end;
3287 else if (beg > 0 && beg > blen) {
3291 if (beg > str_strlen(str, enc))
return 0;
3296 enc == rb_utf8_encoding()) {
3297 p = str_utf8_nth(s, e, &beg);
3298 if (beg > 0)
return 0;
3299 len = str_utf8_offset(p, e,
len);
3305 p = s + beg * char_sz;
3309 else if (
len * char_sz > e - p)
3314 else if ((p = str_nth_len(s, e, &beg, enc)) == e) {
3315 if (beg > 0)
return 0;
3319 len = str_offset(p, e,
len, enc, 0);
3327static VALUE str_substr(
VALUE str,
long beg,
long len,
int empty);
3332 return str_substr(str, beg,
len, TRUE);
3342str_substr(
VALUE str,
long beg,
long len,
int empty)
3346 if (!p)
return Qnil;
3347 if (!
len && !empty)
return Qnil;
3349 beg = p - RSTRING_PTR(str);
3351 VALUE str2 = str_subseq(str, beg,
len);
3352 rb_enc_cr_str_copy_for_substr(str2, str);
3360 if (CHILLED_STRING_P(str)) {
3365 rb_str_resize(str, RSTRING_LEN(str));
3383 if (
OBJ_FROZEN(str) || CHILLED_STRING_P(str)) {
3426str_uminus(
VALUE str)
3431 return rb_fstring(str);
3435#define rb_str_dup_frozen rb_str_new_frozen
3440 rb_check_frozen(str);
3441 if (
FL_TEST(str, STR_TMPLOCK)) {
3444 FL_SET(str, STR_TMPLOCK);
3451 rb_check_frozen(str);
3452 if (!
FL_TEST(str, STR_TMPLOCK)) {
3472 const int termlen = TERM_LEN(str);
3474 str_modifiable(str);
3475 if (STR_SHARED_P(str)) {
3478 if (
len > (
capa = (
long)str_capacity(str, termlen)) ||
len < 0) {
3479 rb_bug(
"probable buffer overflow: %ld for %ld",
len,
capa);
3490 else if (
len > RSTRING_LEN(str)) {
3494 const char *
const new_end = RSTRING_PTR(str) +
len;
3504 else if (
len < RSTRING_LEN(str)) {
3512 STR_SET_LEN(str,
len);
3513 TERM_FILL(&RSTRING_PTR(str)[
len], termlen);
3520 rb_raise(rb_eArgError,
"negative string size (or size too big)");
3523 int independent = str_independent(str);
3524 long slen = RSTRING_LEN(str);
3525 const int termlen = TERM_LEN(str);
3527 if (slen >
len || (termlen != 1 && slen <
len)) {
3533 if (STR_EMBED_P(str)) {
3534 if (
len == slen)
return str;
3535 if (str_embed_capa(str) >=
len + termlen) {
3536 STR_SET_LEN(str,
len);
3540 str_make_independent_expand(str, slen,
len - slen, termlen);
3542 else if (str_embed_capa(str) >=
len + termlen) {
3544 char *
ptr = STR_HEAP_PTR(str);
3546 if (slen >
len) slen =
len;
3549 STR_SET_LEN(str,
len);
3551 SIZED_FREE_N(
ptr,
capa + termlen);
3555 else if (!independent) {
3556 if (
len == slen)
return str;
3557 str_make_independent_expand(str, slen,
len - slen, termlen);
3561 SIZED_REALLOC_N(
RSTRING(str)->
as.heap.ptr,
char,
3562 (
size_t)
len + termlen, STR_HEAP_SIZE(str));
3565 else if (
len == slen)
return str;
3566 STR_SET_LEN(str,
len);
3573str_ensure_available_capa(
VALUE str,
long len)
3575 str_modify_keep_cr(str);
3577 const int termlen = TERM_LEN(str);
3578 long olen = RSTRING_LEN(str);
3580 if (RB_UNLIKELY(olen > LONG_MAX -
len)) {
3581 rb_raise(rb_eArgError,
"string sizes too big");
3584 long total = olen +
len;
3585 long capa = str_capacity(str, termlen);
3588 if (total >= LONG_MAX / 2) {
3591 while (total >
capa) {
3594 RESIZE_CAPA_TERM(str,
capa, termlen);
3599str_buf_cat4(
VALUE str,
const char *
ptr,
long len,
bool keep_cr)
3602 str_modify_keep_cr(str);
3607 if (
len == 0)
return 0;
3609 long total, olen,
off = -1;
3611 const int termlen = TERM_LEN(str);
3614 if (
ptr >= sptr &&
ptr <= sptr + olen) {
3618 long capa = str_capacity(str, termlen);
3620 if (olen > LONG_MAX -
len) {
3621 rb_raise(rb_eArgError,
"string sizes too big");
3625 if (total >= LONG_MAX / 2) {
3628 while (total >
capa) {
3631 RESIZE_CAPA_TERM(str,
capa, termlen);
3632 sptr = RSTRING_PTR(str);
3637 memcpy(sptr + olen,
ptr,
len);
3638 STR_SET_LEN(str, total);
3639 TERM_FILL(sptr + total, termlen);
3644#define str_buf_cat(str, ptr, len) str_buf_cat4((str), (ptr), len, false)
3645#define str_buf_cat2(str, ptr) str_buf_cat4((str), (ptr), rb_strlen_lit(ptr), false)
3650 if (
len == 0)
return str;
3652 rb_raise(rb_eArgError,
"negative string size (or size too big)");
3654 return str_buf_cat(str,
ptr,
len);
3665rb_str_buf_cat_byte(
VALUE str,
unsigned char byte)
3670 if (UNLIKELY(!str_independent(str))) {
3671 str_make_independent(str);
3674 long string_length = -1;
3675 const int null_terminator_length = 1;
3680 if (UNLIKELY(string_length > LONG_MAX - 1)) {
3681 rb_raise(rb_eArgError,
"string sizes too big");
3684 long string_capacity = str_capacity(str, null_terminator_length);
3690 if (LIKELY(string_capacity >= string_length + 1)) {
3692 sptr[string_length] = byte;
3693 STR_SET_LEN(str, string_length + 1);
3694 TERM_FILL(sptr + string_length + 1, null_terminator_length);
3698 str_buf_cat(str, (
char *)&
byte, 1);
3714 rb_enc_associate_index(str, ENCINDEX_ASCII_8BIT);
3725rb_enc_cr_str_buf_cat(
VALUE str,
const char *
ptr,
long len,
3726 int ptr_encindex,
int ptr_cr,
int *ptr_cr_ret)
3735 if (str_encindex == ptr_encindex) {
3737 ptr_cr = coderange_scan(
ptr,
len, rb_enc_from_index(ptr_encindex));
3741 str_enc = rb_enc_from_index(str_encindex);
3742 ptr_enc = rb_enc_from_index(ptr_encindex);
3743 if (!rb_enc_asciicompat(str_enc) || !rb_enc_asciicompat(ptr_enc)) {
3746 if (RSTRING_LEN(str) == 0) {
3749 rb_str_change_terminator_length(str, rb_enc_mbminlen(str_enc), rb_enc_mbminlen(ptr_enc));
3755 ptr_cr = coderange_scan(
ptr,
len, ptr_enc);
3759 str_cr = rb_enc_str_coderange(str);
3764 *ptr_cr_ret = ptr_cr;
3766 if (str_encindex != ptr_encindex &&
3769 str_enc = rb_enc_from_index(str_encindex);
3770 ptr_enc = rb_enc_from_index(ptr_encindex);
3775 res_encindex = str_encindex;
3780 res_encindex = str_encindex;
3784 res_encindex = ptr_encindex;
3789 res_encindex = str_encindex;
3796 res_encindex = str_encindex;
3802 rb_raise(rb_eArgError,
"negative string size (or size too big)");
3804 str_buf_cat(str,
ptr,
len);
3810 rb_enc_inspect_name(str_enc), rb_enc_inspect_name(ptr_enc));
3817 return rb_enc_cr_str_buf_cat(str,
ptr,
len,
3827 if (rb_enc_asciicompat(enc)) {
3828 return rb_enc_cr_str_buf_cat(str,
ptr, strlen(
ptr),
3834 unsigned int c = (
unsigned char)*
ptr;
3835 int len = rb_enc_codelen(c, enc);
3836 rb_enc_mbcput(c, buf, enc);
3837 rb_enc_cr_str_buf_cat(str, buf,
len,
3848 int str2_cr = rb_enc_str_coderange(str2);
3850 if (rb_str_enc_fastpath(str)) {
3854 str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
true);
3860 str_buf_cat4(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
true);
3871 rb_enc_cr_str_buf_cat(str, RSTRING_PTR(str2), RSTRING_LEN(str2),
3887rb_str_concat_literals(
size_t num,
const VALUE *strary)
3891 unsigned long len = 1;
3896 for (i = 0; i < num; ++i) {
len += RSTRING_LEN(strary[i]); }
3898 str_enc_copy_direct(str, strary[0]);
3900 for (i = s; i < num; ++i) {
3901 const VALUE v = strary[i];
3905 if (encidx != ENCINDEX_US_ASCII) {
3907 rb_enc_set_index(str, encidx);
3920rb_str_concat_multi(
int argc,
VALUE *argv,
VALUE str)
3922 str_modifiable(str);
3927 else if (argc > 1) {
3930 rb_enc_copy(arg_str, str);
3931 for (i = 0; i < argc; i++) {
3966rb_str_append_as_bytes(
int argc,
VALUE *argv,
VALUE str)
3968 long needed_capacity = 0;
3972 for (
int index = 0; index < argc; index++) {
3973 VALUE obj = argv[index];
3981 needed_capacity += RSTRING_LEN(obj);
3986 "wrong argument type %"PRIsVALUE
" (expected String or Integer)",
3993 str_ensure_available_capa(str, needed_capacity);
3996 for (
int index = 0; index < argc; index++) {
3997 VALUE obj = argv[index];
4002 argv[index] = obj = rb_int_and(obj,
INT2FIX(0xff));
4003 char byte = (char)(
NUM2INT(obj) & 0xFF);
4017 rb_bug(
"append_as_bytes arguments should have been validated");
4021 STR_SET_LEN(str, RSTRING_LEN(str) + needed_capacity);
4022 TERM_FILL(sptr, TERM_LEN(str));
4027 for (
int index = 0; index < argc; index++) {
4028 VALUE obj = argv[index];
4045 rb_bug(
"append_as_bytes arguments should have been validated");
4124 if (rb_num_to_uint(str2, &code) == 0) {
4137 encidx = rb_ascii8bit_appendable_encoding_index(enc, code);
4140 rb_str_buf_cat_byte(str1, (
unsigned char)code);
4143 long pos = RSTRING_LEN(str1);
4148 switch (
len = rb_enc_codelen(code, enc)) {
4149 case ONIGERR_INVALID_CODE_POINT_VALUE:
4150 rb_raise(
rb_eRangeError,
"invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
4152 case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
4158 rb_enc_mbcput(code, buf, enc);
4159 if (rb_enc_precise_mbclen(buf, buf +
len + 1, enc) !=
len) {
4160 rb_raise(
rb_eRangeError,
"invalid codepoint 0x%X in %s", code, rb_enc_name(enc));
4162 rb_str_resize(str1, pos+
len);
4163 memcpy(RSTRING_PTR(str1) + pos, buf,
len);
4176rb_ascii8bit_appendable_encoding_index(
rb_encoding *enc,
unsigned int code)
4178 int encidx = rb_enc_to_index(enc);
4180 if (encidx == ENCINDEX_ASCII_8BIT || encidx == ENCINDEX_US_ASCII) {
4185 if (encidx == ENCINDEX_US_ASCII && code > 127) {
4186 return ENCINDEX_ASCII_8BIT;
4208rb_str_prepend_multi(
int argc,
VALUE *argv,
VALUE str)
4210 str_modifiable(str);
4215 else if (argc > 1) {
4218 rb_enc_copy(arg_str, str);
4219 for (i = 0; i < argc; i++) {
4232 st_index_t precomputed_hash;
4233 memcpy(&precomputed_hash,
RSTRING_END(str) + TERM_LEN(str),
sizeof(precomputed_hash));
4235 RUBY_ASSERT(precomputed_hash == str_do_hash(str));
4236 return precomputed_hash;
4239 return str_do_hash(str);
4246 const char *ptr1, *ptr2;
4249 return (len1 != len2 ||
4251 memcmp(ptr1, ptr2, len1) != 0);
4263rb_str_hash_m(
VALUE str)
4269#define lesser(a,b) (((a)>(b))?(b):(a))
4277 if (RSTRING_LEN(str1) == 0)
return TRUE;
4278 if (RSTRING_LEN(str2) == 0)
return TRUE;
4281 if (idx1 == idx2)
return TRUE;
4282 rc1 = rb_enc_str_coderange(str1);
4283 rc2 = rb_enc_str_coderange(str2);
4286 if (rb_enc_asciicompat(rb_enc_from_index(idx2)))
4290 if (rb_enc_asciicompat(rb_enc_from_index(idx1)))
4300 const char *ptr1, *ptr2;
4303 if (str1 == str2)
return 0;
4306 if (ptr1 == ptr2 || (retval = memcmp(ptr1, ptr2, lesser(len1, len2))) == 0) {
4315 if (len1 > len2)
return 1;
4318 if (retval > 0)
return 1;
4352 if (str1 == str2)
return Qtrue;
4359 return rb_str_eql_internal(str1, str2);
4373 if (str1 == str2)
return Qtrue;
4375 return rb_str_eql_internal(str1, str2);
4413 return rb_invcmp(str1, str2);
4455 return str_casecmp(str1, s);
4463 const char *p1, *p1end, *p2, *p2end;
4465 enc = rb_enc_compatible(str1, str2);
4470 p1 = RSTRING_PTR(str1); p1end =
RSTRING_END(str1);
4471 p2 = RSTRING_PTR(str2); p2end =
RSTRING_END(str2);
4472 if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
4473 while (p1 < p1end && p2 < p2end) {
4475 unsigned int c1 =
TOLOWER(*p1 & 0xff);
4476 unsigned int c2 =
TOLOWER(*p2 & 0xff);
4478 return INT2FIX(c1 < c2 ? -1 : 1);
4485 while (p1 < p1end && p2 < p2end) {
4486 int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
4487 int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);
4489 if (0 <= c1 && 0 <= c2) {
4493 return INT2FIX(c1 < c2 ? -1 : 1);
4497 l1 = rb_enc_mbclen(p1, p1end, enc);
4498 l2 = rb_enc_mbclen(p2, p2end, enc);
4499 len = l1 < l2 ? l1 : l2;
4500 r = memcmp(p1, p2,
len);
4502 return INT2FIX(r < 0 ? -1 : 1);
4504 return INT2FIX(l1 < l2 ? -1 : 1);
4510 if (p1 == p1end && p2 == p2end)
return INT2FIX(0);
4511 if (p1 == p1end)
return INT2FIX(-1);
4544 return str_casecmp_p(str1, s);
4551 VALUE folded_str1, folded_str2;
4552 VALUE fold_opt = sym_fold;
4554 enc = rb_enc_compatible(str1, str2);
4559 if (is_ascii_string(str1) && is_ascii_string(str2)) {
4560 if (RSTRING_LEN(str1) != RSTRING_LEN(str2))
return Qfalse;
4561 const char *p1 = RSTRING_PTR(str1), *p1end =
RSTRING_END(str1);
4562 const char *p2 = RSTRING_PTR(str2);
4563 while (p1 < p1end) {
4564 if (*p1 != *p2 &&
TOLOWER((
unsigned char)*p1) !=
TOLOWER((
unsigned char)*p2)) {
4573 folded_str1 = rb_str_downcase(1, &fold_opt, str1);
4574 folded_str2 = rb_str_downcase(1, &fold_opt, str2);
4576 return rb_str_eql(folded_str1, folded_str2);
4580strseq_core(
const char *str_ptr,
const char *str_ptr_end,
long str_len,
4581 const char *sub_ptr,
long sub_len,
long offset,
rb_encoding *enc)
4583 const char *search_start = str_ptr;
4584 long pos, search_len = str_len - offset;
4588 pos =
rb_memsearch(sub_ptr, sub_len, search_start, search_len, enc);
4589 if (pos < 0)
return pos;
4591 if (t == search_start + pos)
break;
4592 search_len -= t - search_start;
4593 if (search_len <= 0)
return -1;
4594 offset += t - search_start;
4597 return pos + offset;
4601#define rb_str_index(str, sub, offset) rb_strseq_index(str, sub, offset, 0)
4602#define rb_str_byteindex(str, sub, offset) rb_strseq_index(str, sub, offset, 1)
4605rb_strseq_index(
VALUE str,
VALUE sub,
long offset,
int in_byte)
4607 const char *str_ptr, *str_ptr_end, *sub_ptr;
4608 long str_len, sub_len;
4611 enc = rb_enc_check(str, sub);
4612 if (is_broken_string(sub))
return -1;
4614 str_ptr = RSTRING_PTR(str);
4616 str_len = RSTRING_LEN(str);
4617 sub_ptr = RSTRING_PTR(sub);
4618 sub_len = RSTRING_LEN(sub);
4620 if (str_len < sub_len)
return -1;
4623 long str_len_char, sub_len_char;
4624 int single_byte = single_byte_optimizable(str);
4625 str_len_char = (in_byte || single_byte) ? str_len : str_strlen(str, enc);
4626 sub_len_char = in_byte ? sub_len : str_strlen(sub, enc);
4628 offset += str_len_char;
4629 if (offset < 0)
return -1;
4631 if (str_len_char - offset < sub_len_char)
return -1;
4632 if (!in_byte) offset = str_offset(str_ptr, str_ptr_end, offset, enc, single_byte);
4635 if (sub_len == 0)
return offset;
4638 return strseq_core(str_ptr, str_ptr_end, str_len, sub_ptr, sub_len, offset, enc);
4651rb_str_index_m(
int argc,
VALUE *argv,
VALUE str)
4658 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4659 long slen = str_strlen(str, enc);
4661 if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
4673 pos = str_offset(RSTRING_PTR(str),
RSTRING_END(str), pos,
4674 enc, single_byte_optimizable(str));
4684 pos = rb_str_index(str, sub, pos);
4698str_ensure_byte_pos(
VALUE str,
long pos)
4700 if (!single_byte_optimizable(str)) {
4701 const char *s = RSTRING_PTR(str);
4703 const char *p = s + pos;
4704 if (!at_char_boundary(s, p, e, rb_enc_get(str))) {
4706 "offset %ld does not land on character boundary", pos);
4779rb_str_byteindex_m(
int argc,
VALUE *argv,
VALUE str)
4785 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4786 long slen = RSTRING_LEN(str);
4788 if (pos < 0 ? (pos += slen) < 0 : pos > slen) {
4799 str_ensure_byte_pos(str, pos);
4804 pos = RMATCH_BEG(match, 0);
4810 pos = rb_str_byteindex(str, sub, pos);
4811 if (pos >= 0)
return LONG2NUM(pos);
4819 const char *hit, *adjusted, *sbeg, *e, *t;
4821 long slen, searchlen;
4823 sbeg = RSTRING_PTR(str);
4824 slen = RSTRING_LEN(sub);
4825 if (slen == 0)
return s - sbeg;
4827 t = RSTRING_PTR(sub);
4829 searchlen = s - sbeg + 1;
4831 if (memcmp(s, t, slen) == 0) {
4836 hit = memrchr(sbeg, c, searchlen);
4839 if (hit != adjusted) {
4840 searchlen = adjusted - sbeg;
4843 if (memcmp(hit, t, slen) == 0)
4845 searchlen = adjusted - sbeg;
4846 }
while (searchlen > 0);
4856 const char *sbeg, *s;
4860 enc = rb_enc_check(str, sub);
4861 if (is_broken_string(sub))
return -1;
4862 singlebyte = single_byte_optimizable(str);
4863 len = singlebyte ? RSTRING_LEN(str) : str_strlen(str, enc);
4864 slen = str_strlen(sub, enc);
4867 if (
len < slen)
return -1;
4868 if (
len - pos < slen) pos =
len - slen;
4869 if (
len == 0)
return pos;
4871 sbeg = RSTRING_PTR(str);
4874 if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
4880 s = str_nth(sbeg,
RSTRING_END(str), pos, enc, singlebyte);
4881 return str_rindex(str, sub, s, enc);
4893rb_str_rindex_m(
int argc,
VALUE *argv,
VALUE str)
4898 long pos,
len = str_strlen(str, enc);
4900 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
4902 if (pos < 0 && (pos +=
len) < 0) {
4908 if (pos >
len) pos =
len;
4916 pos = str_offset(RSTRING_PTR(str),
RSTRING_END(str), pos,
4917 enc, single_byte_optimizable(str));
4927 pos = rb_str_rindex(str, sub, pos);
4937rb_str_byterindex(
VALUE str,
VALUE sub,
long pos)
4940 const char *sbeg, *s;
4943 enc = rb_enc_check(str, sub);
4944 if (is_broken_string(sub))
return -1;
4945 len = RSTRING_LEN(str);
4946 slen = RSTRING_LEN(sub);
4949 if (
len < slen)
return -1;
4950 if (
len - pos < slen) pos =
len - slen;
4951 if (
len == 0)
return pos;
4953 sbeg = RSTRING_PTR(str);
4956 if (memcmp(sbeg, RSTRING_PTR(sub), RSTRING_LEN(sub)) == 0)
4963 return str_rindex(str, sub, s, enc);
5053rb_str_byterindex_m(
int argc,
VALUE *argv,
VALUE str)
5057 long pos,
len = RSTRING_LEN(str);
5059 if (
rb_scan_args(argc, argv,
"11", &sub, &initpos) == 2) {
5061 if (pos < 0 && (pos +=
len) < 0) {
5067 if (pos >
len) pos =
len;
5073 str_ensure_byte_pos(str, pos);
5078 pos = RMATCH_BEG(match, 0);
5084 pos = rb_str_byterindex(str, sub, pos);
5085 if (pos >= 0)
return LONG2NUM(pos);
5127 switch (OBJ_BUILTIN_TYPE(y)) {
5179rb_str_match_m(
int argc,
VALUE *argv,
VALUE str)
5186 result =
rb_funcallv(get_pat(re), rb_intern(
"match"), argc, argv);
5217rb_str_match_m_p(
int argc,
VALUE *argv,
VALUE str)
5221 re = get_pat(argv[0]);
5222 return rb_reg_match_p(re, str, argc > 1 ?
NUM2LONG(argv[1]) : 0);
5231static enum neighbor_char
5237 if (rb_enc_mbminlen(enc) > 1) {
5239 int r = rb_enc_precise_mbclen(p, p +
len, enc), c;
5241 return NEIGHBOR_NOT_CHAR;
5243 c = rb_enc_mbc_to_codepoint(p, p +
len, enc) + 1;
5245 if (!l)
return NEIGHBOR_NOT_CHAR;
5246 if (l !=
len)
return NEIGHBOR_WRAPPED;
5247 rb_enc_mbcput(c, p, enc);
5248 r = rb_enc_precise_mbclen(p, p +
len, enc);
5250 return NEIGHBOR_NOT_CHAR;
5252 return NEIGHBOR_FOUND;
5255 for (i =
len-1; 0 <= i && (
unsigned char)p[i] == 0xff; i--)
5258 return NEIGHBOR_WRAPPED;
5259 ++((
unsigned char*)p)[i];
5260 l = rb_enc_precise_mbclen(p, p+
len, enc);
5264 return NEIGHBOR_FOUND;
5267 memset(p+l, 0xff,
len-l);
5273 for (len2 =
len-1; 0 < len2; len2--) {
5274 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5278 memset(p+len2+1, 0xff,
len-(len2+1));
5283static enum neighbor_char
5288 if (rb_enc_mbminlen(enc) > 1) {
5290 int r = rb_enc_precise_mbclen(p, p +
len, enc), c;
5292 return NEIGHBOR_NOT_CHAR;
5294 c = rb_enc_mbc_to_codepoint(p, p +
len, enc);
5295 if (!c)
return NEIGHBOR_NOT_CHAR;
5298 if (!l)
return NEIGHBOR_NOT_CHAR;
5299 if (l !=
len)
return NEIGHBOR_WRAPPED;
5300 rb_enc_mbcput(c, p, enc);
5301 r = rb_enc_precise_mbclen(p, p +
len, enc);
5303 return NEIGHBOR_NOT_CHAR;
5305 return NEIGHBOR_FOUND;
5308 for (i =
len-1; 0 <= i && (
unsigned char)p[i] == 0; i--)
5311 return NEIGHBOR_WRAPPED;
5312 --((
unsigned char*)p)[i];
5313 l = rb_enc_precise_mbclen(p, p+
len, enc);
5317 return NEIGHBOR_FOUND;
5320 memset(p+l, 0,
len-l);
5326 for (len2 =
len-1; 0 < len2; len2--) {
5327 l2 = rb_enc_precise_mbclen(p, p+len2, enc);
5331 memset(p+len2+1, 0,
len-(len2+1));
5345static enum neighbor_char
5346enc_succ_alnum_char(
char *p,
long len,
rb_encoding *enc,
char *carry)
5348 enum neighbor_char ret;
5352 char save[ONIGENC_CODE_TO_MBC_MAXLEN];
5356 const int max_gaps = 1;
5358 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5360 ctype = ONIGENC_CTYPE_DIGIT;
5362 ctype = ONIGENC_CTYPE_ALPHA;
5364 return NEIGHBOR_NOT_CHAR;
5367 for (
try = 0;
try <= max_gaps; ++
try) {
5368 ret = enc_succ_char(p,
len, enc);
5369 if (ret == NEIGHBOR_FOUND) {
5370 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5372 return NEIGHBOR_FOUND;
5379 ret = enc_pred_char(p,
len, enc);
5380 if (ret == NEIGHBOR_FOUND) {
5381 c = rb_enc_mbc_to_codepoint(p, p+
len, enc);
5394 return NEIGHBOR_NOT_CHAR;
5397 if (ctype != ONIGENC_CTYPE_DIGIT) {
5399 return NEIGHBOR_WRAPPED;
5403 enc_succ_char(carry,
len, enc);
5404 return NEIGHBOR_WRAPPED;
5422 str =
rb_str_new(RSTRING_PTR(orig), RSTRING_LEN(orig));
5423 rb_enc_cr_str_copy_for_substr(str, orig);
5424 return str_succ(str);
5431 char *sbeg, *s, *e, *last_alnum = 0;
5432 int found_alnum = 0;
5434 char carry[ONIGENC_CODE_TO_MBC_MAXLEN] =
"\1";
5435 long carry_pos = 0, carry_len = 1;
5436 enum neighbor_char neighbor = NEIGHBOR_FOUND;
5438 slen = RSTRING_LEN(str);
5439 if (slen == 0)
return str;
5441 enc = STR_ENC_GET(str);
5442 sbeg = RSTRING_PTR(str);
5443 s = e = sbeg + slen;
5445 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5446 if (neighbor == NEIGHBOR_NOT_CHAR && last_alnum) {
5452 l = rb_enc_precise_mbclen(s, e, enc);
5453 if (!ONIGENC_MBCLEN_CHARFOUND_P(l))
continue;
5454 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5455 neighbor = enc_succ_alnum_char(s, l, enc, carry);
5457 case NEIGHBOR_NOT_CHAR:
5459 case NEIGHBOR_FOUND:
5461 case NEIGHBOR_WRAPPED:
5466 carry_pos = s - sbeg;
5471 while ((s = rb_enc_prev_char(sbeg, s, e, enc)) != 0) {
5472 enum neighbor_char neighbor;
5473 char tmp[ONIGENC_CODE_TO_MBC_MAXLEN];
5474 l = rb_enc_precise_mbclen(s, e, enc);
5475 if (!ONIGENC_MBCLEN_CHARFOUND_P(l))
continue;
5476 l = ONIGENC_MBCLEN_CHARFOUND_LEN(l);
5478 neighbor = enc_succ_char(tmp, l, enc);
5480 case NEIGHBOR_FOUND:
5484 case NEIGHBOR_WRAPPED:
5487 case NEIGHBOR_NOT_CHAR:
5490 if (rb_enc_precise_mbclen(s, s+l, enc) != l) {
5492 enc_succ_char(s, l, enc);
5494 if (!rb_enc_asciicompat(enc)) {
5495 MEMCPY(carry, s,
char, l);
5498 carry_pos = s - sbeg;
5502 RESIZE_CAPA(str, slen + carry_len);
5503 sbeg = RSTRING_PTR(str);
5504 s = sbeg + carry_pos;
5505 memmove(s + carry_len, s, slen - carry_pos);
5506 memmove(s, carry, carry_len);
5508 STR_SET_LEN(str, slen);
5509 TERM_FILL(&sbeg[slen], rb_enc_mbminlen(enc));
5510 rb_enc_str_coderange(str);
5525rb_str_succ_bang(
VALUE str)
5533all_digits_p(
const char *s,
long len)
5561 VALUE end, exclusive;
5565 return rb_str_upto_each(beg, end,
RTEST(exclusive), str_upto_i,
Qnil);
5571 VALUE current, after_end;
5578 enc = rb_enc_check(beg, end);
5579 ascii = (is_ascii_string(beg) && is_ascii_string(end));
5581 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1 && ascii) {
5582 char c = RSTRING_PTR(beg)[0];
5583 char e = RSTRING_PTR(end)[0];
5585 if (c > e || (excl && c == e))
return beg;
5587 VALUE str = rb_enc_str_new(&c, 1, enc);
5589 if ((*each)(str, arg))
break;
5590 if (!excl && c == e)
break;
5592 if (excl && c == e)
break;
5597 if (ascii &&
ISDIGIT(RSTRING_PTR(beg)[0]) &&
ISDIGIT(RSTRING_PTR(end)[0]) &&
5598 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg)) &&
5599 all_digits_p(RSTRING_PTR(end), RSTRING_LEN(end))) {
5604 b = rb_str_to_inum(beg, 10, FALSE);
5605 e = rb_str_to_inum(end, 10, FALSE);
5612 if (excl && bi == ei)
break;
5613 if ((*each)(
rb_enc_sprintf(usascii,
"%.*ld", width, bi), arg))
break;
5618 ID op = excl ?
'<' : idLE;
5619 VALUE args[2], fmt = rb_fstring_lit(
"%.*d");
5624 if ((*each)(
rb_str_format(numberof(args), args, fmt), arg))
break;
5632 if (n > 0 || (excl && n == 0))
return beg;
5640 if ((*each)(current, arg))
break;
5641 if (
NIL_P(next))
break;
5645 if (RSTRING_LEN(current) > RSTRING_LEN(end) || RSTRING_LEN(current) == 0)
5660 if (is_ascii_string(beg) &&
ISDIGIT(RSTRING_PTR(beg)[0]) &&
5661 all_digits_p(RSTRING_PTR(beg), RSTRING_LEN(beg))) {
5662 VALUE b, args[2], fmt = rb_fstring_lit(
"%.*d");
5664 b = rb_str_to_inum(beg, 10, FALSE);
5670 if ((*each)(
rb_enc_sprintf(usascii,
"%.*ld", width, bi), arg))
break;
5678 if ((*each)(
rb_str_format(numberof(args), args, fmt), arg))
break;
5686 if ((*each)(current, arg))
break;
5689 if (RSTRING_LEN(current) == 0)
5700 if (!
rb_equal(str, *argp))
return 0;
5714 if (rb_enc_asciicompat(STR_ENC_GET(beg)) &&
5715 rb_enc_asciicompat(STR_ENC_GET(end)) &&
5716 rb_enc_asciicompat(STR_ENC_GET(val))) {
5717 const char *bp = RSTRING_PTR(beg);
5718 const char *ep = RSTRING_PTR(end);
5719 const char *vp = RSTRING_PTR(val);
5720 if (RSTRING_LEN(beg) == 1 && RSTRING_LEN(end) == 1) {
5721 if (RSTRING_LEN(val) == 0 || RSTRING_LEN(val) > 1)
5729 if (b <= v && v < e)
return Qtrue;
5730 return RBOOL(!
RTEST(exclusive) && v == e);
5737 all_digits_p(bp, RSTRING_LEN(beg)) &&
5738 all_digits_p(ep, RSTRING_LEN(end))) {
5743 rb_str_upto_each(beg, end,
RTEST(exclusive), include_range_i, (
VALUE)&val);
5745 return RBOOL(
NIL_P(val));
5768 return rb_str_subpat(str, indx,
INT2FIX(0));
5771 if (rb_str_index(str, indx, 0) != -1)
5777 long beg,
len = str_strlen(str, NULL);
5789 return str_substr(str, idx, 1, FALSE);
5806rb_str_aref_m(
int argc,
VALUE *argv,
VALUE str)
5810 return rb_str_subpat(str, argv[0], argv[1]);
5813 return rb_str_substr_two_fixnums(str, argv[0], argv[1], TRUE);
5817 return rb_str_aref(str, argv[0]);
5823 char *
ptr = RSTRING_PTR(str);
5824 long olen = RSTRING_LEN(str), nlen;
5826 str_modifiable(str);
5827 if (
len > olen)
len = olen;
5829 if (str_embed_capa(str) >= nlen + TERM_LEN(str)) {
5831 size_t old_capa =
RSTRING(str)->as.heap.aux.capa + TERM_LEN(str);
5832 int fl = (int)(
RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED|STR_NOFREE));
5835 memmove(
ptr, oldptr +
len, nlen);
5836 if (fl == STR_NOEMBED) {
5837 SIZED_FREE_N(oldptr, old_capa);
5841 if (!STR_SHARED_P(str)) {
5843 rb_enc_cr_str_exact_copy(
shared, str);
5848 STR_SET_LEN(str, nlen);
5850 if (!SHARABLE_MIDDLE_SUBSTRING) {
5851 TERM_FILL(
ptr + nlen, TERM_LEN(str));
5858rb_str_update_1(
VALUE str,
long beg,
long len,
VALUE val,
long vbeg,
long vlen)
5864 if (beg == 0 && vlen == 0) {
5869 str_modify_keep_cr(str);
5873 RESIZE_CAPA(str, slen + vlen -
len);
5874 sptr = RSTRING_PTR(str);
5878 cr = rb_enc_str_coderange(val);
5883 memmove(sptr + beg + vlen,
5885 slen - (beg +
len));
5887 if (vlen < beg &&
len < 0) {
5891 memmove(sptr + beg, RSTRING_PTR(val) + vbeg, vlen);
5894 STR_SET_LEN(str, slen);
5895 TERM_FILL(&sptr[slen], TERM_LEN(str));
5902 rb_str_update_1(str, beg,
len, val, 0, RSTRING_LEN(val));
5911 int singlebyte = single_byte_optimizable(str);
5917 enc = rb_enc_check(str, val);
5918 slen = str_strlen(str, enc);
5920 if ((slen < beg) || ((beg < 0) && (beg + slen < 0))) {
5929 if (
len > slen - beg) {
5932 p = str_nth(RSTRING_PTR(str),
RSTRING_END(str), beg, enc, singlebyte);
5937 beg = p - RSTRING_PTR(str);
5939 rb_str_update_0(str, beg,
len, val);
5940 rb_enc_associate(str, enc);
5951 long start, end,
len;
5959 int num_regs = RMATCH_NREGS(match);
5960 if ((nth >= num_regs) || ((nth < 0) && (-nth >= num_regs))) {
5967 start = RMATCH_BEG(match, nth);
5971 end = RMATCH_END(match, nth);
5974 enc = rb_enc_check_str(str, val);
5975 rb_str_update_0(str, start,
len, val);
5976 rb_enc_associate(str, enc);
5984 switch (
TYPE(indx)) {
5986 rb_str_subpat_set(str, indx,
INT2FIX(0), val);
5990 beg = rb_str_index(str, indx, 0);
6029rb_str_aset_m(
int argc,
VALUE *argv,
VALUE str)
6033 rb_str_subpat_set(str, argv[0], argv[1], argv[2]);
6041 return rb_str_aset(str, argv[0], argv[1]);
6093rb_str_slice_bang(
int argc,
VALUE *argv,
VALUE str)
6101 str_modify_keep_cr(str);
6106 int num_regs = RMATCH_NREGS(match);
6109 if ((nth += num_regs) <= 0)
return Qnil;
6111 else if (nth >= num_regs)
return Qnil;
6112 beg = RMATCH_BEG(match, nth);
6113 len = RMATCH_END(match, nth) - beg;
6116 else if (argc == 2) {
6125 beg = p - RSTRING_PTR(str);
6129 beg = rb_str_index(str, indx, 0);
6130 if (beg == -1)
return Qnil;
6131 len = RSTRING_LEN(indx);
6143 beg = p - RSTRING_PTR(str);
6152 beg = p - RSTRING_PTR(str);
6156 rb_enc_cr_str_copy_for_substr(result, str);
6164 char *sptr = RSTRING_PTR(str);
6165 long slen = RSTRING_LEN(str);
6166 if (beg +
len > slen)
6170 slen - (beg +
len));
6172 STR_SET_LEN(str, slen);
6173 TERM_FILL(&sptr[slen], TERM_LEN(str));
6184 switch (OBJ_BUILTIN_TYPE(pat)) {
6203get_pat_quoted(
VALUE pat,
int check)
6207 switch (OBJ_BUILTIN_TYPE(pat)) {
6221 if (check && is_broken_string(pat)) {
6228rb_pat_search0(
VALUE pat,
VALUE str,
long pos,
int set_backref_str,
VALUE *match)
6231 pos = rb_str_byteindex(str, pat, pos);
6232 if (set_backref_str) {
6234 str = rb_str_new_frozen_String(str);
6235 VALUE match_data = rb_backref_set_string(str, pos, RSTRING_LEN(pat));
6237 *match = match_data;
6247 return rb_reg_search0(pat, str, pos, 0, set_backref_str, match);
6252rb_pat_search(
VALUE pat,
VALUE str,
long pos,
int set_backref_str)
6254 return rb_pat_search0(pat, str, pos, set_backref_str, NULL);
6272rb_str_sub_bang(
int argc,
VALUE *argv,
VALUE str)
6287 hash = rb_check_hash_type(repl);
6294 pat = get_pat_quoted(argv[0], 1);
6296 str_modifiable(str);
6297 beg = rb_pat_search(pat, str, 0, 1);
6309 end0 = beg0 + RSTRING_LEN(pat);
6313 beg0 = RMATCH_BEG(match, 0);
6314 end0 = RMATCH_END(match, 0);
6318 if (iter || !
NIL_P(hash)) {
6319 p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
6325 repl = rb_hash_aref(hash,
rb_str_subseq(str, beg0, end0 - beg0));
6328 str_mod_check(str, p,
len);
6329 rb_check_frozen(str);
6332 repl = rb_reg_regsub_match(repl, str, match);
6335 enc = rb_enc_compatible(str, repl);
6338 p = RSTRING_PTR(str);
len = RSTRING_LEN(str);
6342 rb_enc_inspect_name(str_enc),
6343 rb_enc_inspect_name(STR_ENC_GET(repl)));
6345 enc = STR_ENC_GET(repl);
6348 rb_enc_associate(str, enc);
6358 rlen = RSTRING_LEN(repl);
6359 len = RSTRING_LEN(str);
6361 RESIZE_CAPA(str,
len + rlen - plen);
6363 p = RSTRING_PTR(str);
6365 memmove(p + beg0 + rlen, p + beg0 + plen,
len - beg0 - plen);
6367 rp = RSTRING_PTR(repl);
6368 memmove(p + beg0, rp, rlen);
6370 STR_SET_LEN(str,
len);
6371 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
6394 rb_str_sub_bang(argc, argv, str);
6399str_gsub(
int argc,
VALUE *argv,
VALUE str,
int bang)
6402 long beg, beg0, end0;
6403 long offset, blen, slen,
len, last;
6404 enum {STR, ITER, FAST_MAP, MAP} mode = STR;
6406 int need_backref_str = -1;
6417 hash = rb_check_hash_type(repl);
6421 else if (rb_hash_default_unredefined(hash) && !
FL_TEST_RAW(hash, RHASH_PROC_DEFAULT)) {
6430 rb_error_arity(argc, 1, 2);
6433 pat = get_pat_quoted(argv[0], 1);
6434 beg = rb_pat_search0(pat, str, 0, need_backref_str, &match);
6437 if (bang)
return Qnil;
6440 if (bang) str_modify_keep_cr(str);
6443 blen = RSTRING_LEN(str) + 30;
6445 sp = RSTRING_PTR(str);
6446 slen = RSTRING_LEN(str);
6448 str_enc = STR_ENC_GET(str);
6449 rb_enc_associate(dest, str_enc);
6455 end0 = beg0 + RSTRING_LEN(pat);
6459 beg0 = RMATCH_BEG(match, 0);
6460 end0 = RMATCH_END(match, 0);
6469 struct RString fake_str = {RBASIC_INIT};
6471 if (mode == FAST_MAP) {
6480 val = rb_hash_aref(hash, key);
6483 str_mod_check(str, sp, slen);
6488 else if (need_backref_str) {
6489 val = rb_reg_regsub_match(repl, str, match);
6490 if (need_backref_str < 0) {
6491 need_backref_str = val != repl;
6498 len = beg0 - offset;
6512 if (RSTRING_LEN(str) <= end0)
break;
6513 len = rb_enc_fast_mbclen(RSTRING_PTR(str)+end0,
RSTRING_END(str), str_enc);
6515 offset = end0 +
len;
6517 cp = RSTRING_PTR(str) + offset;
6518 if (offset > RSTRING_LEN(str))
break;
6521 if (mode != FAST_MAP && mode != STR) {
6524 beg = rb_pat_search0(pat, str, offset, need_backref_str, &match);
6529 if (RSTRING_LEN(str) > offset) {
6532 rb_pat_search0(pat, str, last, 1, &match);
6534 str_shared_replace(str, dest);
6559rb_str_gsub_bang(
int argc,
VALUE *argv,
VALUE str)
6561 str_modifiable(str);
6562 return str_gsub(argc, argv, str, 1);
6612 return str_gsub(argc, argv, str, 0);
6632 str_modifiable(str);
6633 if (str == str2)
return str;
6637 return str_replace(str, str2);
6654rb_str_clear(
VALUE str)
6658 STR_SET_LEN(str, 0);
6659 RSTRING_PTR(str)[0] = 0;
6660 if (rb_enc_asciicompat(STR_ENC_GET(str)))
6676rb_str_chr(
VALUE str)
6694 pos += RSTRING_LEN(str);
6695 if (pos < 0 || RSTRING_LEN(str) <= pos)
6698 return INT2FIX((
unsigned char)RSTRING_PTR(str)[pos]);
6718 long len = RSTRING_LEN(str);
6719 char *
ptr, *head, *left = 0;
6723 if (pos < -
len ||
len <= pos)
6730 char byte = (char)(
NUM2INT(w) & 0xFF);
6732 if (!str_independent(str))
6733 str_make_independent(str);
6734 enc = STR_ENC_GET(str);
6735 head = RSTRING_PTR(str);
6737 if (!STR_EMBED_P(str)) {
6744 nlen = rb_enc_precise_mbclen(left, head+
len, enc);
6752 width = rb_enc_precise_mbclen(left, head+
len, enc);
6754 nlen = rb_enc_precise_mbclen(left, head+
len, enc);
6770str_bit_offset_out_of_range(
long byte_len, uint64_t bit_offset)
6773 return bit_offset / CHAR_BIT >= (uint64_t)byte_len;
6789str_bit_offset_from_index(
VALUE index)
6801 offset.long_value =
FIX2LONG(integer);
6802 if (offset.long_value < 0) {
6805 offset.value = (uint64_t)offset.long_value;
6806 offset.fits_long =
true;
6811 if (rb_int_negative_p(integer)) {
6814 if (rb_cmpint(rb_int_cmp(integer,
ULL2NUM(UINT64_MAX)), integer,
ULL2NUM(UINT64_MAX)) > 0) {
6815 rb_raise(rb_eArgError,
"bit index out of representable range");
6818 offset.value = (uint64_t)
NUM2ULL(integer);
6819 if (offset.value <= (uint64_t)LONG_MAX) {
6820 offset.long_value = (long)offset.value;
6821 offset.fits_long =
true;
6824 offset.long_value = 0;
6825 offset.fits_long =
false;
6831str_lsb_first(
int argc,
VALUE *argv,
VALUE *index)
6833 static ID keywords[1];
6834 VALUE opts, vlsb_first;
6842 if (vlsb_first ==
Qundef || vlsb_first ==
Qtrue) {
6845 if (vlsb_first ==
Qfalse) {
6848 rb_raise(rb_eArgError,
"lsb_first must be true or false");
6852static inline uint64_t
6853str_logical_to_physical_bit64(uint64_t logical,
bool lsb_first)
6855 return lsb_first ? logical : ((logical & ~(uint64_t)7) | (7 - (logical & 7)));
6859str_logical_to_physical_bit(
long logical,
bool lsb_first)
6861 return lsb_first ? logical : ((logical & ~7L) | (7 - (logical & 7L)));
6866 unsigned int bit_offset;
6870str_bit_location_from_offset(uint64_t logical, bool lsb_first)
6876 uint64_t physical = str_logical_to_physical_bit64(logical, lsb_first);
6878 location.byte_index = (long)(physical / CHAR_BIT);
6879 location.bit_offset = (
unsigned int)(physical % CHAR_BIT);
6884str_get_bit(
const char *ptr,
long bit_index)
6886 return (((
unsigned char)ptr[bit_index / CHAR_BIT]) >> (bit_index % CHAR_BIT)) & 1;
6892 return (((
unsigned char)ptr[location.byte_index]) >> location.bit_offset) & 1;
6899 bool lsb_first = str_lsb_first(argc, argv, &index);
6902 if (str_bit_offset_out_of_range(RSTRING_LEN(str), offset.value)) {
6906 if (offset.fits_long) {
6907 return str_get_bit(RSTRING_PTR(str), str_logical_to_physical_bit(offset.long_value, lsb_first));
6910 return str_get_bit_location(RSTRING_PTR(str), str_bit_location_from_offset(offset.value, lsb_first));
6922rb_str_bit_get(
int argc,
VALUE *argv,
VALUE str)
6924 int bit = str_bit_get(argc, argv, str);
6936rb_str_bit_set_p(
int argc,
VALUE *argv,
VALUE str)
6938 int bit = str_bit_get(argc, argv, str);
6939 return bit < 0 ?
Qnil : RBOOL(bit);
6942enum str_bit_mutation {
6949str_mutate_bit(
int argc,
VALUE *argv,
VALUE str,
enum str_bit_mutation mutation)
6952 bool lsb_first = str_lsb_first(argc, argv, &index);
6959 if (str_bit_offset_out_of_range(RSTRING_LEN(str), offset.value)) {
6964 ptr = (
unsigned char *)RSTRING_PTR(str);
6965 if (offset.fits_long) {
6966 bit_index = str_logical_to_physical_bit(offset.long_value, lsb_first);
6967 mask = (
unsigned char)(1u << (bit_index % CHAR_BIT));
6968 location.byte_index = bit_index / CHAR_BIT;
6971 location = str_bit_location_from_offset(offset.value, lsb_first);
6972 mask = (
unsigned char)(1u << location.bit_offset);
6977 ptr[location.byte_index] |= mask;
6980 ptr[location.byte_index] &= (
unsigned char)~mask;
6983 ptr[location.byte_index] ^= mask;
6998rb_str_bit_set(
int argc,
VALUE *argv,
VALUE str)
7000 return str_mutate_bit(argc, argv, str, STR_BIT_SET);
7011rb_str_bit_clear(
int argc,
VALUE *argv,
VALUE str)
7013 return str_mutate_bit(argc, argv, str, STR_BIT_CLEAR);
7024rb_str_bit_flip(
int argc,
VALUE *argv,
VALUE str)
7026 return str_mutate_bit(argc, argv, str, STR_BIT_FLIP);
7030str_count_bits(
const unsigned char *ptr,
long len)
7034 long unrolled_end =
len & ~31L;
7035 long aligned_end =
len & ~7L;
7038 for (;
off < unrolled_end;
off += 32) {
7039 uint64_t w0, w1, w2, w3;
7040 memcpy(&w0, ptr +
off, 8);
7041 memcpy(&w1, ptr +
off + 8, 8);
7042 memcpy(&w2, ptr +
off + 16, 8);
7043 memcpy(&w3, ptr +
off + 24, 8);
7044 count += rb_popcount64(w0);
7045 count += rb_popcount64(w1);
7046 count += rb_popcount64(w2);
7047 count += rb_popcount64(w3);
7051 for (;
off < aligned_end;
off += 8) {
7053 memcpy(&word, ptr +
off, 8);
7054 count += rb_popcount64(word);
7061 for (;
off <
len;
off++, shift += CHAR_BIT) {
7062 word |= (uint64_t)ptr[
off] << shift;
7064 count += rb_popcount64(word);
7078rb_str_bit_count(
VALUE str)
7080 return ULL2NUM(str_count_bits((
const unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str)));
7084str_check_bitwise_length(
VALUE str,
VALUE other)
7086 if (RSTRING_LEN(str) != RSTRING_LEN(other)) {
7087 rb_raise(rb_eArgError,
"operands must have the same length (%ld vs %ld)",
7088 RSTRING_LEN(str), RSTRING_LEN(other));
7093str_bitwise_result(
VALUE str)
7095 long len = RSTRING_LEN(str);
7097 rb_str_resize(result,
len);
7098 rb_enc_associate(result, rb_ascii8bit_encoding());
7103#define STR_DEFINE_UNARY_BITWISE_KERNEL(name, expr_word, expr_byte) \
7105 name(unsigned char *dst, const unsigned char *src, long len) \
7108 long unrolled_end = len & ~31L; \
7109 long aligned_end = len & ~7L; \
7110 for (; off < unrolled_end; off += 32) { \
7111 uint64_t s0, s1, s2, s3; \
7112 memcpy(&s0, src + off, 8); \
7113 memcpy(&s1, src + off + 8, 8); \
7114 memcpy(&s2, src + off + 16, 8); \
7115 memcpy(&s3, src + off + 24, 8); \
7116 s0 = (expr_word(s0)); \
7117 s1 = (expr_word(s1)); \
7118 s2 = (expr_word(s2)); \
7119 s3 = (expr_word(s3)); \
7120 memcpy(dst + off, &s0, 8); \
7121 memcpy(dst + off + 8, &s1, 8); \
7122 memcpy(dst + off + 16, &s2, 8); \
7123 memcpy(dst + off + 24, &s3, 8); \
7125 for (; off < aligned_end; off += 8) { \
7127 memcpy(&word, src + off, 8); \
7128 word = (expr_word(word)); \
7129 memcpy(dst + off, &word, 8); \
7131 for (; off < len; off++) dst[off] = (expr_byte(src[off])); \
7134#define STR_DEFINE_BINARY_BITWISE_KERNEL(name, expr_word, expr_byte) \
7136 name(unsigned char *dst, const unsigned char *lhs, \
7137 const unsigned char *rhs, long len) \
7140 long unrolled_end = len & ~31L; \
7141 long aligned_end = len & ~7L; \
7142 for (; off < unrolled_end; off += 32) { \
7143 uint64_t l0, l1, l2, l3, r0, r1, r2, r3; \
7144 memcpy(&l0, lhs + off, 8); memcpy(&r0, rhs + off, 8); \
7145 memcpy(&l1, lhs + off + 8, 8); memcpy(&r1, rhs + off + 8, 8); \
7146 memcpy(&l2, lhs + off + 16, 8); memcpy(&r2, rhs + off + 16, 8); \
7147 memcpy(&l3, lhs + off + 24, 8); memcpy(&r3, rhs + off + 24, 8); \
7148 l0 = expr_word(l0, r0); \
7149 l1 = expr_word(l1, r1); \
7150 l2 = expr_word(l2, r2); \
7151 l3 = expr_word(l3, r3); \
7152 memcpy(dst + off, &l0, 8); \
7153 memcpy(dst + off + 8, &l1, 8); \
7154 memcpy(dst + off + 16, &l2, 8); \
7155 memcpy(dst + off + 24, &l3, 8); \
7157 for (; off < aligned_end; off += 8) { \
7158 uint64_t lhs_word, rhs_word; \
7159 memcpy(&lhs_word, lhs + off, 8); \
7160 memcpy(&rhs_word, rhs + off, 8); \
7161 lhs_word = expr_word(lhs_word, rhs_word); \
7162 memcpy(dst + off, &lhs_word, 8); \
7164 for (; off < len; off++) dst[off] = expr_byte(lhs[off], rhs[off]); \
7167#define STR_BITWISE_NOT_WORD(x) (~(x))
7168#define STR_BITWISE_NOT_BYTE(x) ((unsigned char)~(x))
7169#define STR_BITWISE_AND_WORD(x, y) ((x) & (y))
7170#define STR_BITWISE_AND_BYTE(x, y) ((unsigned char)((x) & (y)))
7171#define STR_BITWISE_OR_WORD(x, y) ((x) | (y))
7172#define STR_BITWISE_OR_BYTE(x, y) ((unsigned char)((x) | (y)))
7173#define STR_BITWISE_XOR_WORD(x, y) ((x) ^ (y))
7174#define STR_BITWISE_XOR_BYTE(x, y) ((unsigned char)((x) ^ (y)))
7176STR_DEFINE_UNARY_BITWISE_KERNEL(str_bitwise_not, STR_BITWISE_NOT_WORD, STR_BITWISE_NOT_BYTE)
7177STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_and, STR_BITWISE_AND_WORD, STR_BITWISE_AND_BYTE)
7178STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_or, STR_BITWISE_OR_WORD, STR_BITWISE_OR_BYTE)
7179STR_DEFINE_BINARY_BITWISE_KERNEL(str_bitwise_xor, STR_BITWISE_XOR_WORD, STR_BITWISE_XOR_BYTE)
7189rb_str_bitwise_not(
VALUE str)
7191 long len = RSTRING_LEN(str);
7192 VALUE result = str_bitwise_result(str);
7193 str_bitwise_not((
unsigned char *)RSTRING_PTR(result),
7194 (
const unsigned char *)RSTRING_PTR(str),
len);
7206rb_str_bitwise_not_bang(
VALUE str)
7212 len = RSTRING_LEN(str);
7213 ptr = (
unsigned char *)RSTRING_PTR(str);
7214 str_bitwise_not(ptr, ptr,
len);
7218#define STR_DEFINE_BINARY_BITWISE_METHOD(name) \
7220 rb_str_bitwise_##name(VALUE str, VALUE other) \
7224 StringValue(other); \
7225 str_check_bitwise_length(str, other); \
7226 len = RSTRING_LEN(str); \
7227 result = str_bitwise_result(str); \
7228 str_bitwise_##name((unsigned char *)RSTRING_PTR(result), \
7229 (const unsigned char *)RSTRING_PTR(str), \
7230 (const unsigned char *)RSTRING_PTR(other), len); \
7234 rb_str_bitwise_##name##_bang(VALUE str, VALUE other) \
7237 unsigned char *ptr; \
7238 StringValue(other); \
7239 str_check_bitwise_length(str, other); \
7240 rb_str_modify(str); \
7241 len = RSTRING_LEN(str); \
7242 ptr = (unsigned char *)RSTRING_PTR(str); \
7243 str_bitwise_##name(ptr, ptr, \
7244 (const unsigned char *)RSTRING_PTR(other), len); \
7248STR_DEFINE_BINARY_BITWISE_METHOD(and)
7249STR_DEFINE_BINARY_BITWISE_METHOD(or)
7250STR_DEFINE_BINARY_BITWISE_METHOD(xor)
7253str_byte_substr(
VALUE str,
long beg,
long len,
int empty)
7255 long n = RSTRING_LEN(str);
7257 if (beg > n ||
len < 0)
return Qnil;
7260 if (beg < 0)
return Qnil;
7265 if (!empty)
return Qnil;
7269 VALUE str2 = str_subseq(str, beg,
len);
7271 str_enc_copy_direct(str2, str);
7273 if (RSTRING_LEN(str2) == 0) {
7274 if (!rb_enc_asciicompat(STR_ENC_GET(str)))
7308 long beg,
len = RSTRING_LEN(str);
7316 return str_byte_substr(str, beg,
len, TRUE);
7321 return str_byte_substr(str, idx, 1, FALSE);
7333rb_str_byteslice(
int argc,
VALUE *argv,
VALUE str)
7338 return str_byte_substr(str, beg,
len, TRUE);
7341 return str_byte_aref(str, argv[0]);
7345str_check_beg_len(
VALUE str,
long *beg,
long *
len)
7347 long end, slen = RSTRING_LEN(str);
7350 if ((slen < *beg) || ((*beg < 0) && (*beg + slen < 0))) {
7359 if (*
len > slen - *beg) {
7363 str_ensure_byte_pos(str, *beg);
7364 str_ensure_byte_pos(str, end);
7378rb_str_bytesplice(
int argc,
VALUE *argv,
VALUE str)
7380 long beg,
len, vbeg, vlen;
7385 if (!(argc == 2 || argc == 3 || argc == 5)) {
7386 rb_raise(rb_eArgError,
"wrong number of arguments (given %d, expected 2, 3, or 5)", argc);
7390 rb_raise(
rb_eTypeError,
"wrong argument type %s (expected Range)",
7391 rb_builtin_class_name(argv[0]));
7398 vlen = RSTRING_LEN(val);
7403 rb_raise(
rb_eTypeError,
"wrong argument type %s (expected Range)",
7404 rb_builtin_class_name(argv[2]));
7416 vlen = RSTRING_LEN(val);
7424 str_check_beg_len(str, &beg, &
len);
7425 str_check_beg_len(val, &vbeg, &vlen);
7426 str_modify_keep_cr(str);
7429 rb_enc_associate(str, rb_enc_check(str, val));
7432 rb_str_update_1(str, beg,
len, val, vbeg, vlen);
7454rb_str_reverse(
VALUE str)
7461 if (RSTRING_LEN(str) <= 1)
return str_duplicate(
rb_cString, str);
7462 enc = STR_ENC_GET(str);
7468 if (RSTRING_LEN(str) > 1) {
7469 if (single_byte_optimizable(str)) {
7476 int clen = rb_enc_fast_mbclen(s, e, enc);
7484 cr = rb_enc_asciicompat(enc) ?
7487 int clen = rb_enc_mbclen(s, e, enc);
7496 STR_SET_LEN(rev, RSTRING_LEN(str));
7497 str_enc_copy_direct(rev, str);
7519rb_str_reverse_bang(
VALUE str)
7521 if (RSTRING_LEN(str) > 1) {
7522 if (single_byte_optimizable(str)) {
7525 str_modify_keep_cr(str);
7526 s = RSTRING_PTR(str);
7535 str_shared_replace(str, rb_str_reverse(str));
7539 str_modify_keep_cr(str);
7568 i = rb_str_index(str, arg, 0);
7570 return RBOOL(i != -1);
7614 rb_raise(rb_eArgError,
"invalid radix %d", base);
7616 return rb_str_to_inum(str, base, FALSE);
7641rb_str_to_f(
VALUE str)
7658rb_str_to_s(
VALUE str)
7670 char s[RUBY_MAX_CHAR_LEN];
7671 int n = rb_enc_codelen(c, enc);
7673 rb_enc_mbcput(c, s, enc);
7678#define CHAR_ESC_LEN 13
7681rb_str_buf_cat_escaped_char(
VALUE result,
unsigned int c,
int unicode_p)
7683 char buf[CHAR_ESC_LEN + 1];
7691 snprintf(buf, CHAR_ESC_LEN,
"%c", c);
7693 else if (c < 0x10000) {
7694 snprintf(buf, CHAR_ESC_LEN,
"\\u%04X", c);
7697 snprintf(buf, CHAR_ESC_LEN,
"\\u{%X}", c);
7702 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", c);
7705 snprintf(buf, CHAR_ESC_LEN,
"\\x{%X}", c);
7708 l = (int)strlen(buf);
7714ruby_escaped_char(
int c)
7717 case '\0':
return "\\0";
7718 case '\n':
return "\\n";
7719 case '\r':
return "\\r";
7720 case '\t':
return "\\t";
7721 case '\f':
return "\\f";
7722 case '\013':
return "\\v";
7723 case '\010':
return "\\b";
7724 case '\007':
return "\\a";
7725 case '\033':
return "\\e";
7726 case '\x7f':
return "\\c?";
7732rb_str_escape(
VALUE str)
7736 const char *p = RSTRING_PTR(str);
7738 const char *prev = p;
7739 char buf[CHAR_ESC_LEN + 1];
7741 int unicode_p = rb_enc_unicode_p(enc);
7742 int asciicompat = rb_enc_asciicompat(enc);
7747 int n = rb_enc_precise_mbclen(p, pend, enc);
7749 if (p > prev) str_buf_cat(result, prev, p - prev);
7750 n = rb_enc_mbminlen(enc);
7752 n = (int)(pend - p);
7754 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", *p & 0377);
7755 str_buf_cat(result, buf, strlen(buf));
7761 c = rb_enc_mbc_to_codepoint(p, pend, enc);
7763 cc = ruby_escaped_char(c);
7765 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7766 str_buf_cat(result, cc, strlen(cc));
7769 else if (asciicompat && rb_enc_isascii(c, enc) &&
ISPRINT(c)) {
7772 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7773 rb_str_buf_cat_escaped_char(result, c, unicode_p);
7777 if (p > prev) str_buf_cat(result, prev, p - prev);
7787static const bool inspect_no_escape[256] = {
7788 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7789 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
7790 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7791 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7792 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7793 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
7794 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
7795 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
7811 const char *p, *pend, *prev;
7812 char buf[CHAR_ESC_LEN + 1];
7814 rb_encoding *resenc = rb_default_internal_encoding();
7815 int unicode_p = rb_enc_unicode_p(enc);
7816 int asciicompat = rb_enc_asciicompat(enc);
7817 int cr = rb_enc_str_coderange(str);
7819 if (resenc == NULL) resenc = rb_default_external_encoding();
7820 if (!rb_enc_asciicompat(resenc)) resenc = rb_usascii_encoding();
7821 rb_enc_associate(result, resenc);
7822 str_buf_cat2(result,
"\"");
7835 while (p < pend && inspect_no_escape[(
unsigned char)*p]) p++;
7836 if (p >= pend)
break;
7839 n = rb_enc_precise_mbclen(p, pend, enc);
7841 if (p > prev) str_buf_cat(result, prev, p - prev);
7842 n = rb_enc_mbminlen(enc);
7844 n = (int)(pend - p);
7846 snprintf(buf, CHAR_ESC_LEN,
"\\x%02X", *p & 0377);
7847 str_buf_cat(result, buf, strlen(buf));
7853 c = rb_enc_mbc_to_codepoint(p, pend, enc);
7855 if ((asciicompat || unicode_p) &&
7856 (c ==
'"'|| c ==
'\\' ||
7861 (cc ==
'$' || cc ==
'@' || cc ==
'{'))))) {
7862 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7863 str_buf_cat2(result,
"\\");
7864 if (asciicompat || enc == resenc) {
7870 case '\n': cc =
'n';
break;
7871 case '\r': cc =
'r';
break;
7872 case '\t': cc =
't';
break;
7873 case '\f': cc =
'f';
break;
7874 case '\013': cc =
'v';
break;
7875 case '\010': cc =
'b';
break;
7876 case '\007': cc =
'a';
break;
7877 case 033: cc =
'e';
break;
7878 default: cc = 0;
break;
7881 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7884 str_buf_cat(result, buf, 2);
7897 (asciicompat && rb_enc_isascii(c, enc) &&
ISPRINT(c))) {
7901 if (p - n > prev) str_buf_cat(result, prev, p - n - prev);
7902 rb_str_buf_cat_escaped_char(result, c, unicode_p);
7907 if (p > prev) str_buf_cat(result, prev, p - prev);
7908 str_buf_cat2(result,
"\"");
7913#define IS_EVSTR(p,e) ((p) < (e) && (*(p) == '$' || *(p) == '@' || *(p) == '{'))
7926 int encidx = rb_enc_get_index(str);
7929 const char *p, *pend;
7932 int u8 = (encidx == rb_utf8_encindex());
7933 static const char nonascii_suffix[] =
".dup.force_encoding(\"%s\")";
7936 if (!rb_enc_asciicompat(enc)) {
7938 len += strlen(enc->name);
7941 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
7944 unsigned char c = *p++;
7947 case '"':
case '\\':
7948 case '\n':
case '\r':
7949 case '\t':
case '\f':
7950 case '\013':
case '\010':
case '\007':
case '\033':
7955 clen = IS_EVSTR(p, pend) ? 2 : 1;
7963 if (u8 && c > 0x7F) {
7964 int n = rb_enc_precise_mbclen(p-1, pend, enc);
7966 unsigned int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
7969 else if (cc <= 0xFFFFF)
7982 if (clen > LONG_MAX -
len) {
7989 p = RSTRING_PTR(str); pend = p + RSTRING_LEN(str);
7990 q = RSTRING_PTR(result); qend = q +
len + 1;
7994 unsigned char c = *p++;
7996 if (c ==
'"' || c ==
'\\') {
8000 else if (c ==
'#') {
8001 if (IS_EVSTR(p, pend)) *q++ =
'\\';
8004 else if (c ==
'\n') {
8008 else if (c ==
'\r') {
8012 else if (c ==
'\t') {
8016 else if (c ==
'\f') {
8020 else if (c ==
'\013') {
8024 else if (c ==
'\010') {
8028 else if (c ==
'\007') {
8032 else if (c ==
'\033') {
8042 int n = rb_enc_precise_mbclen(p-1, pend, enc) - 1;
8044 int cc = rb_enc_mbc_to_codepoint(p-1, pend, enc);
8047 snprintf(q, qend-q,
"u%04X", cc);
8049 snprintf(q, qend-q,
"u{%X}", cc);
8054 snprintf(q, qend-q,
"x%02X", c);
8060 if (!rb_enc_asciicompat(enc)) {
8061 snprintf(q, qend-q, nonascii_suffix, enc->name);
8062 encidx = rb_ascii8bit_encindex();
8065 rb_enc_associate_index(result, encidx);
8071unescape_ascii(
unsigned int c)
8095undump_after_backslash(
VALUE undumped,
const char **ss,
const char *s_end,
rb_encoding **penc,
bool *utf8,
bool *binary)
8097 const char *s = *ss;
8101 unsigned char buf[6];
8119 *buf = unescape_ascii(*s);
8131 if (enc_utf8 == NULL) enc_utf8 = rb_utf8_encoding();
8132 if (*penc != enc_utf8) {
8134 rb_enc_associate(undumped, enc_utf8);
8151 if (hexlen == 0 || hexlen > 6) {
8157 if (0xd800 <= c && c <= 0xdfff) {
8160 codelen = rb_enc_mbcput(c, (
char *)buf, *penc);
8170 if (0xd800 <= c && c <= 0xdfff) {
8173 codelen = rb_enc_mbcput(c, (
char *)buf, *penc);
8203static VALUE rb_str_is_ascii_only_p(
VALUE str);
8215str_undump(
VALUE str)
8217 const char *s = RSTRING_PTR(str);
8220 VALUE undumped = rb_enc_str_new(s, 0L, enc);
8222 bool binary =
false;
8226 if (rb_str_is_ascii_only_p(str) ==
Qfalse) {
8229 if (!str_null_check(str, &w)) {
8232 if (RSTRING_LEN(str) < 2)
goto invalid_format;
8233 if (*s !=
'"')
goto invalid_format;
8251 static const char force_encoding_suffix[] =
".force_encoding(\"";
8252 static const char dup_suffix[] =
".dup";
8253 const char *encname;
8258 size =
sizeof(dup_suffix) - 1;
8259 if (s_end - s > size && memcmp(s, dup_suffix, size) == 0) s += size;
8261 size =
sizeof(force_encoding_suffix) - 1;
8262 if (s_end - s <= size)
goto invalid_format;
8263 if (memcmp(s, force_encoding_suffix, size) != 0)
goto invalid_format;
8267 rb_raise(
rb_eRuntimeError,
"dumped string contained Unicode escape but used force_encoding");
8271 s = memchr(s,
'"', s_end-s);
8273 if (!s)
goto invalid_format;
8274 if (s_end - s != 2)
goto invalid_format;
8275 if (s[0] !=
'"' || s[1] !=
')')
goto invalid_format;
8277 encidx = rb_enc_find_index2(encname, (
long)size);
8281 rb_enc_associate_index(undumped, encidx);
8291 undump_after_backslash(undumped, &s, s_end, &enc, &utf8, &binary);
8302 rb_raise(
rb_eRuntimeError,
"invalid dumped string; not wrapped with '\"' nor '\"...\".force_encoding(\"...\")' form");
8308 if (rb_enc_dummy_p(enc)) {
8315str_true_enc(
VALUE str)
8318 rb_str_check_dummy_enc(enc);
8322static OnigCaseFoldType
8323check_case_options(
int argc,
VALUE *argv, OnigCaseFoldType flags)
8328 rb_raise(rb_eArgError,
"too many options");
8329 if (argv[0]==sym_turkic) {
8330 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
8332 if (argv[1]==sym_lithuanian)
8333 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
8335 rb_raise(rb_eArgError,
"invalid second option");
8338 else if (argv[0]==sym_lithuanian) {
8339 flags |= ONIGENC_CASE_FOLD_LITHUANIAN;
8341 if (argv[1]==sym_turkic)
8342 flags |= ONIGENC_CASE_FOLD_TURKISH_AZERI;
8344 rb_raise(rb_eArgError,
"invalid second option");
8348 rb_raise(rb_eArgError,
"too many options");
8349 else if (argv[0]==sym_ascii)
8350 flags |= ONIGENC_CASE_ASCII_ONLY;
8351 else if (argv[0]==sym_fold) {
8352 if ((flags & (ONIGENC_CASE_UPCASE|ONIGENC_CASE_DOWNCASE)) == ONIGENC_CASE_DOWNCASE)
8353 flags ^= ONIGENC_CASE_FOLD|ONIGENC_CASE_DOWNCASE;
8355 rb_raise(rb_eArgError,
"option :fold only allowed for downcasing");
8358 rb_raise(rb_eArgError,
"invalid option");
8365 if ((flags & ONIGENC_CASE_ASCII_ONLY) && (enc==rb_utf8_encoding() ||
rb_enc_mbmaxlen(enc) == 1))
8367 return !(flags & ONIGENC_CASE_FOLD_TURKISH_AZERI) &&
8372#define CASE_MAPPING_ADDITIONAL_LENGTH 20
8373#ifndef CASEMAP_DEBUG
8374# define CASEMAP_DEBUG 0
8382 OnigUChar space[FLEX_ARY_LEN];
8386mapping_buffer_free(
void *p)
8390 while (current_buffer) {
8391 previous_buffer = current_buffer;
8392 current_buffer = current_buffer->next;
8393 ruby_xfree_sized(previous_buffer, offsetof(
mapping_buffer, space) + previous_buffer->capa);
8399 {0, mapping_buffer_free,},
8400 0, 0, RUBY_TYPED_THREAD_SAFE_FREE | RUBY_TYPED_WB_PROTECTED
8408 const OnigUChar *source_current, *source_end;
8409 int target_length = 0;
8410 VALUE buffer_anchor;
8413 size_t buffer_count = 0;
8414 int buffer_length_or_invalid;
8416 if (RSTRING_LEN(source) == 0)
return str_duplicate(
rb_cString, source);
8418 source_current = (OnigUChar*)RSTRING_PTR(source);
8423 while (source_current < source_end) {
8425 size_t capa = (size_t)(source_end-source_current)*++buffer_count + CASE_MAPPING_ADDITIONAL_LENGTH;
8426 if (CASEMAP_DEBUG) {
8427 fprintf(stderr,
"Buffer allocation, capa is %"PRIuSIZE
"\n",
capa);
8430 *pre_buffer = current_buffer;
8431 pre_buffer = ¤t_buffer->next;
8432 current_buffer->next = NULL;
8433 current_buffer->capa =
capa;
8434 buffer_length_or_invalid = enc->case_map(flags,
8435 &source_current, source_end,
8436 current_buffer->space,
8437 current_buffer->space+current_buffer->capa,
8439 if (buffer_length_or_invalid < 0) {
8440 current_buffer =
DATA_PTR(buffer_anchor);
8442 mapping_buffer_free(current_buffer);
8443 rb_raise(rb_eArgError,
"input string invalid");
8445 target_length += current_buffer->used = buffer_length_or_invalid;
8447 if (CASEMAP_DEBUG) {
8448 fprintf(stderr,
"Buffer count is %"PRIuSIZE
"\n", buffer_count);
8451 if (buffer_count==1) {
8452 target =
rb_str_new((
const char*)current_buffer->space, target_length);
8455 char *target_current;
8458 target_current = RSTRING_PTR(target);
8459 current_buffer =
DATA_PTR(buffer_anchor);
8460 while (current_buffer) {
8461 memcpy(target_current, current_buffer->space, current_buffer->used);
8462 target_current += current_buffer->used;
8463 current_buffer = current_buffer->next;
8466 current_buffer =
DATA_PTR(buffer_anchor);
8468 mapping_buffer_free(current_buffer);
8473 str_enc_copy_direct(target, source);
8482 const OnigUChar *source_current, *source_end;
8483 OnigUChar *target_current, *target_end;
8484 long old_length = RSTRING_LEN(source);
8485 int length_or_invalid;
8487 if (old_length == 0)
return Qnil;
8489 source_current = (OnigUChar*)RSTRING_PTR(source);
8491 if (source == target) {
8492 target_current = (OnigUChar*)source_current;
8493 target_end = (OnigUChar*)source_end;
8496 target_current = (OnigUChar*)RSTRING_PTR(target);
8500 length_or_invalid = onigenc_ascii_only_case_map(flags,
8501 &source_current, source_end,
8502 target_current, target_end, enc);
8503 if (length_or_invalid < 0)
8504 rb_raise(rb_eArgError,
"input string invalid");
8505 if (CASEMAP_DEBUG && length_or_invalid != old_length) {
8506 fprintf(stderr,
"problem with rb_str_ascii_casemap"
8507 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
8508 rb_raise(rb_eArgError,
"internal problem with rb_str_ascii_casemap"
8509 "; old_length=%ld, new_length=%d\n", old_length, length_or_invalid);
8512 str_enc_copy(target, source);
8518upcase_single(
VALUE str)
8520 char *s = RSTRING_PTR(str), *send =
RSTRING_END(str);
8521 bool modified =
false;
8524 unsigned int c = *(
unsigned char*)s;
8526 if (
'a' <= c && c <=
'z') {
8527 *s =
'A' + (c -
'a');
8548rb_str_upcase_bang(
int argc,
VALUE *argv,
VALUE str)
8551 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
8553 flags = check_case_options(argc, argv, flags);
8554 str_modify_keep_cr(str);
8555 enc = str_true_enc(str);
8556 if (case_option_single_p(flags, enc, str)) {
8557 if (upcase_single(str))
8558 flags |= ONIGENC_CASE_MODIFIED;
8560 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8561 rb_str_ascii_casemap(str, str, &flags, enc);
8563 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8565 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8578rb_str_upcase(
int argc,
VALUE *argv,
VALUE str)
8581 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE;
8584 flags = check_case_options(argc, argv, flags);
8585 enc = str_true_enc(str);
8586 if (case_option_single_p(flags, enc, str)) {
8587 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8588 str_enc_copy_direct(ret, str);
8591 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8593 rb_str_ascii_casemap(str, ret, &flags, enc);
8596 ret = rb_str_casemap(str, &flags, enc);
8603downcase_single(
VALUE str)
8605 char *s = RSTRING_PTR(str), *send =
RSTRING_END(str);
8606 bool modified =
false;
8609 unsigned int c = *(
unsigned char*)s;
8611 if (
'A' <= c && c <=
'Z') {
8612 *s =
'a' + (c -
'A');
8634rb_str_downcase_bang(
int argc,
VALUE *argv,
VALUE str)
8637 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8639 flags = check_case_options(argc, argv, flags);
8640 str_modify_keep_cr(str);
8641 enc = str_true_enc(str);
8642 if (case_option_single_p(flags, enc, str)) {
8643 if (downcase_single(str))
8644 flags |= ONIGENC_CASE_MODIFIED;
8646 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8647 rb_str_ascii_casemap(str, str, &flags, enc);
8649 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8651 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8665rb_str_downcase(
int argc,
VALUE *argv,
VALUE str)
8668 OnigCaseFoldType flags = ONIGENC_CASE_DOWNCASE;
8671 flags = check_case_options(argc, argv, flags);
8672 enc = str_true_enc(str);
8673 if (case_option_single_p(flags, enc, str)) {
8674 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8675 str_enc_copy_direct(ret, str);
8676 downcase_single(ret);
8678 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8680 rb_str_ascii_casemap(str, ret, &flags, enc);
8683 ret = rb_str_casemap(str, &flags, enc);
8690capitalize_single(
VALUE str)
8692 char *s = RSTRING_PTR(str), *send =
RSTRING_END(str);
8693 bool modified =
false;
8696 unsigned int c = (
unsigned char)*s;
8698 if (
'a' <= c && c <=
'z') {
8699 *s =
'A' + (c -
'a');
8705 unsigned int c = (
unsigned char)*s;
8707 if (
'A' <= c && c <=
'Z') {
8708 *s =
'a' + (c -
'A');
8730rb_str_capitalize_bang(
int argc,
VALUE *argv,
VALUE str)
8733 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
8735 flags = check_case_options(argc, argv, flags);
8736 str_modify_keep_cr(str);
8737 enc = str_true_enc(str);
8738 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
8739 if (case_option_single_p(flags, enc, str)) {
8740 if (capitalize_single(str))
8741 flags |= ONIGENC_CASE_MODIFIED;
8743 else if (flags&ONIGENC_CASE_ASCII_ONLY)
8744 rb_str_ascii_casemap(str, str, &flags, enc);
8746 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8748 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8762rb_str_capitalize(
int argc,
VALUE *argv,
VALUE str)
8765 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_TITLECASE;
8768 flags = check_case_options(argc, argv, flags);
8769 enc = str_true_enc(str);
8770 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return str;
8771 if (case_option_single_p(flags, enc, str)) {
8772 ret =
rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str));
8773 str_enc_copy_direct(ret, str);
8774 capitalize_single(ret);
8776 else if (flags&ONIGENC_CASE_ASCII_ONLY) {
8778 rb_str_ascii_casemap(str, ret, &flags, enc);
8781 ret = rb_str_casemap(str, &flags, enc);
8800rb_str_swapcase_bang(
int argc,
VALUE *argv,
VALUE str)
8803 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
8805 flags = check_case_options(argc, argv, flags);
8806 str_modify_keep_cr(str);
8807 enc = str_true_enc(str);
8808 if (flags&ONIGENC_CASE_ASCII_ONLY)
8809 rb_str_ascii_casemap(str, str, &flags, enc);
8811 str_shared_replace(str, rb_str_casemap(str, &flags, enc));
8813 if (ONIGENC_CASE_MODIFIED&flags)
return str;
8827rb_str_swapcase(
int argc,
VALUE *argv,
VALUE str)
8830 OnigCaseFoldType flags = ONIGENC_CASE_UPCASE | ONIGENC_CASE_DOWNCASE;
8833 flags = check_case_options(argc, argv, flags);
8834 enc = str_true_enc(str);
8835 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return str_duplicate(
rb_cString, str);
8836 if (flags&ONIGENC_CASE_ASCII_ONLY) {
8838 rb_str_ascii_casemap(str, ret, &flags, enc);
8841 ret = rb_str_casemap(str, &flags, enc);
8846typedef unsigned char *USTR;
8850 unsigned int now, max;
8851 const char *p, *pend;
8862 if (t->p == t->pend)
return -1;
8863 if (rb_enc_ascget(t->p, t->pend, &n, enc) ==
'\\' && t->p + n < t->pend) {
8866 t->now = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
8868 if (rb_enc_ascget(t->p, t->pend, &n, enc) ==
'-' && t->p + n < t->pend) {
8870 if (t->p < t->pend) {
8871 unsigned int c = rb_enc_codepoint_len(t->p, t->pend, &n, enc);
8874 if (t->now < 0x80 && c < 0x80) {
8875 rb_raise(rb_eArgError,
8876 "invalid range \"%c-%c\" in string transliteration",
8880 rb_raise(rb_eArgError,
"invalid range in string transliteration");
8884 else if (t->now < c) {
8893 while (ONIGENC_CODE_TO_MBCLEN(enc, ++t->now) <= 0) {
8894 if (t->now == t->max) {
8899 if (t->now < t->max) {
8915 const unsigned int errc = -1;
8916 unsigned int trans[256];
8918 struct tr trsrc, trrepl;
8920 unsigned int c, c0, last = 0;
8921 int modify = 0, i, l;
8922 unsigned char *s, *send;
8924 int singlebyte = single_byte_optimizable(str);
8928#define CHECK_IF_ASCII(c) \
8929 (void)((cr == ENC_CODERANGE_7BIT && !rb_isascii(c)) ? \
8930 (cr = ENC_CODERANGE_VALID) : 0)
8934 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
8935 if (RSTRING_LEN(repl) == 0) {
8936 return rb_str_delete_bang(1, &src, str);
8940 e1 = rb_enc_check(str, src);
8941 e2 = rb_enc_check(str, repl);
8946 enc = rb_enc_check(src, repl);
8948 trsrc.p = RSTRING_PTR(src); trsrc.pend = trsrc.p + RSTRING_LEN(src);
8949 if (RSTRING_LEN(src) > 1 &&
8950 rb_enc_ascget(trsrc.p, trsrc.pend, &l, enc) ==
'^' &&
8951 trsrc.p + l < trsrc.pend) {
8955 trrepl.p = RSTRING_PTR(repl);
8956 trrepl.pend = trrepl.p + RSTRING_LEN(repl);
8957 trsrc.gen = trrepl.gen = 0;
8958 trsrc.now = trrepl.now = 0;
8959 trsrc.max = trrepl.max = 0;
8962 for (i=0; i<256; i++) {
8965 while ((c = trnext(&trsrc, enc)) != errc) {
8970 if (!hash) hash = rb_hash_new();
8974 while ((c = trnext(&trrepl, enc)) != errc)
8977 for (i=0; i<256; i++) {
8978 if (trans[i] != errc) {
8986 for (i=0; i<256; i++) {
8989 while ((c = trnext(&trsrc, enc)) != errc) {
8990 r = trnext(&trrepl, enc);
8991 if (r == errc) r = trrepl.now;
8994 if (rb_enc_codelen(r, enc) != 1) singlebyte = 0;
8997 if (!hash) hash = rb_hash_new();
9005 str_modify_keep_cr(str);
9006 s = (
unsigned char *)RSTRING_PTR(str); send = (
unsigned char *)
RSTRING_END(str);
9007 termlen = rb_enc_mbminlen(enc);
9010 long offset, max = RSTRING_LEN(str);
9011 unsigned int save = -1;
9012 unsigned char *buf =
ALLOC_N(
unsigned char, max + termlen), *t = buf;
9017 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
9019 SIZED_FREE_N(buf, max + termlen);
9020 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
9023 c0 = c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
9025 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9034 if (cflag) c = last;
9037 else if (cflag) c = errc;
9043 if (c != (
unsigned int)-1) {
9049 tlen = rb_enc_codelen(c, enc);
9055 if (enc != e1) may_modify = 1;
9057 if ((offset = t - buf) + tlen > max) {
9058 size_t MAYBE_UNUSED(old) = max + termlen;
9059 max = offset + tlen + (send - s);
9060 SIZED_REALLOC_N(buf,
unsigned char, max + termlen, old);
9063 rb_enc_mbcput(c, t, enc);
9064 if (may_modify && memcmp(s, t, tlen) != 0) {
9070 if (!STR_EMBED_P(str)) {
9071 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9073 TERM_FILL((
char *)t, termlen);
9074 RSTRING(str)->as.heap.ptr = (
char *)buf;
9075 STR_SET_LEN(str, t - buf);
9076 STR_SET_NOEMBED(str);
9077 RSTRING(str)->as.heap.aux.capa = max;
9081 c = (
unsigned char)*s;
9082 if (trans[c] != errc) {
9099 long offset, max = (long)((send - s) * 1.2);
9100 unsigned char *buf =
ALLOC_N(
unsigned char, max + termlen), *t = buf;
9105 int r = rb_enc_precise_mbclen((
char *)s, (
char *)send, e1);
9107 SIZED_FREE_N(buf, max + termlen);
9108 rb_raise(rb_eArgError,
"invalid byte sequence in %s", rb_enc_name(e1));
9111 c0 = c = rb_enc_mbc_to_codepoint((
char *)s, (
char *)send, e1);
9113 tlen = enc == e1 ? clen : rb_enc_codelen(c, enc);
9121 if (cflag) c = last;
9124 else if (cflag) c = errc;
9128 c = cflag ? last : errc;
9131 tlen = rb_enc_codelen(c, enc);
9136 if (enc != e1) may_modify = 1;
9138 if ((offset = t - buf) + tlen > max) {
9139 size_t MAYBE_UNUSED(old) = max + termlen;
9140 max = offset + tlen + (long)((send - s) * 1.2);
9141 SIZED_REALLOC_N(buf,
unsigned char, max + termlen, old);
9145 rb_enc_mbcput(c, t, enc);
9146 if (may_modify && memcmp(s, t, tlen) != 0) {
9154 if (!STR_EMBED_P(str)) {
9155 SIZED_FREE_N(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
9157 TERM_FILL((
char *)t, termlen);
9158 RSTRING(str)->as.heap.ptr = (
char *)buf;
9159 STR_SET_LEN(str, t - buf);
9160 STR_SET_NOEMBED(str);
9161 RSTRING(str)->as.heap.aux.capa = max;
9167 rb_enc_associate(str, enc);
9189 return tr_trans(str, src, repl, 0);
9234 tr_trans(str, src, repl, 0);
9238#define TR_TABLE_MAX (UCHAR_MAX+1)
9239#define TR_TABLE_SIZE (TR_TABLE_MAX+1)
9241tr_setup_table(
VALUE str,
char stable[TR_TABLE_SIZE],
int first,
9244 const unsigned int errc = -1;
9245 char buf[TR_TABLE_MAX];
9248 VALUE table = 0, ptable = 0;
9249 int i, l, cflag = 0;
9251 tr.p = RSTRING_PTR(str);
tr.pend =
tr.p + RSTRING_LEN(str);
9252 tr.gen =
tr.now =
tr.max = 0;
9254 if (RSTRING_LEN(str) > 1 && rb_enc_ascget(
tr.p,
tr.pend, &l, enc) ==
'^') {
9259 for (i=0; i<TR_TABLE_MAX; i++) {
9262 stable[TR_TABLE_MAX] = cflag;
9264 else if (stable[TR_TABLE_MAX] && !cflag) {
9265 stable[TR_TABLE_MAX] = 0;
9267 for (i=0; i<TR_TABLE_MAX; i++) {
9271 while ((c = trnext(&
tr, enc)) != errc) {
9272 if (c < TR_TABLE_MAX) {
9273 buf[(
unsigned char)c] = !cflag;
9278 if (!table && (first || *tablep || stable[TR_TABLE_MAX])) {
9281 table = ptable ? ptable : rb_hash_new();
9285 table = rb_hash_new();
9290 if (table && (!ptable || (cflag ^ !
NIL_P(rb_hash_aref(ptable, key))))) {
9291 rb_hash_aset(table, key,
Qtrue);
9295 for (i=0; i<TR_TABLE_MAX; i++) {
9296 stable[i] = stable[i] && buf[i];
9298 if (!table && !cflag) {
9305tr_find(
unsigned int c,
const char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
9307 if (c < TR_TABLE_MAX) {
9308 return table[c] != 0;
9314 if (!
NIL_P(rb_hash_lookup(del, v)) &&
9315 (!nodel ||
NIL_P(rb_hash_lookup(nodel, v)))) {
9319 else if (nodel && !
NIL_P(rb_hash_lookup(nodel, v))) {
9322 return table[TR_TABLE_MAX] ? TRUE : FALSE;
9337rb_str_delete_bang(
int argc,
VALUE *argv,
VALUE str)
9339 char squeez[TR_TABLE_SIZE];
9342 VALUE del = 0, nodel = 0;
9344 int i, ascompat, cr;
9346 if (RSTRING_LEN(str) == 0 || !RSTRING_PTR(str))
return Qnil;
9348 for (i=0; i<argc; i++) {
9352 enc = rb_enc_check(str, s);
9353 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
9356 str_modify_keep_cr(str);
9357 ascompat = rb_enc_asciicompat(enc);
9358 s = t = RSTRING_PTR(str);
9365 if (ascompat && (c = *(
unsigned char*)s) < 0x80) {
9376 c = rb_enc_codepoint_len(s, send, &clen, enc);
9378 if (tr_find(c, squeez, del, nodel)) {
9382 if (t != s) rb_enc_mbcput(c, t, enc);
9389 TERM_FILL(t, TERM_LEN(str));
9390 STR_SET_LEN(str, t - RSTRING_PTR(str));
9393 if (modify)
return str;
9407rb_str_delete(
int argc,
VALUE *argv,
VALUE str)
9410 rb_str_delete_bang(argc, argv, str);
9428rb_str_squeeze_bang(
int argc,
VALUE *argv,
VALUE str)
9430 char squeez[TR_TABLE_SIZE];
9432 VALUE del = 0, nodel = 0;
9433 unsigned char *s, *send, *t;
9435 int ascompat, singlebyte = single_byte_optimizable(str);
9439 enc = STR_ENC_GET(str);
9442 for (i=0; i<argc; i++) {
9446 enc = rb_enc_check(str, s);
9447 if (singlebyte && !single_byte_optimizable(s))
9449 tr_setup_table(s, squeez, i==0, &del, &nodel, enc);
9453 str_modify_keep_cr(str);
9454 s = t = (
unsigned char *)RSTRING_PTR(str);
9455 if (!s || RSTRING_LEN(str) == 0)
return Qnil;
9458 ascompat = rb_enc_asciicompat(enc);
9462 unsigned int c = *s++;
9463 if (c != save || (argc > 0 && !squeez[c])) {
9473 if (ascompat && (c = *s) < 0x80) {
9474 if (c != save || (argc > 0 && !squeez[c])) {
9480 c = rb_enc_codepoint_len((
char *)s, (
char *)send, &clen, enc);
9482 if (c != save || (argc > 0 && !tr_find(c, squeez, del, nodel))) {
9483 if (t != s) rb_enc_mbcput(c, t, enc);
9492 TERM_FILL((
char *)t, TERM_LEN(str));
9493 if ((
char *)t - RSTRING_PTR(str) != RSTRING_LEN(str)) {
9494 STR_SET_LEN(str, (
char *)t - RSTRING_PTR(str));
9498 if (modify)
return str;
9512rb_str_squeeze(
int argc,
VALUE *argv,
VALUE str)
9515 rb_str_squeeze_bang(argc, argv, str);
9535 return tr_trans(str, src, repl, 1);
9563 tr_trans(str, src, repl, 1);
9576rb_str_count(
int argc,
VALUE *argv,
VALUE str)
9578 char table[TR_TABLE_SIZE];
9580 VALUE del = 0, nodel = 0, tstr;
9581 const char *s, *send;
9590 enc = rb_enc_check(str, tstr);
9593 if (RSTRING_LEN(tstr) == 1 && rb_enc_asciicompat(enc) &&
9594 (ptstr = RSTRING_PTR(tstr),
9595 ONIGENC_IS_ALLOWED_REVERSE_MATCH(enc, (
const unsigned char *)ptstr, (
const unsigned char *)ptstr+1)) &&
9596 !is_broken_string(str)) {
9598 unsigned char c = rb_enc_codepoint_len(ptstr, ptstr+1, &clen, enc);
9600 s = RSTRING_PTR(str);
9601 if (!s || RSTRING_LEN(str) == 0)
return INT2FIX(0);
9604 if (*(
unsigned char*)s++ == c) n++;
9610 tr_setup_table(tstr, table, TRUE, &del, &nodel, enc);
9611 for (i=1; i<argc; i++) {
9614 enc = rb_enc_check(str, tstr);
9615 tr_setup_table(tstr, table, FALSE, &del, &nodel, enc);
9618 s = RSTRING_PTR(str);
9619 if (!s || RSTRING_LEN(str) == 0)
return INT2FIX(0);
9621 ascompat = rb_enc_asciicompat(enc);
9625 if (ascompat && (c = *(
unsigned char*)s) < 0x80) {
9633 c = rb_enc_codepoint_len(s, send, &clen, enc);
9634 if (tr_find(c, table, del, nodel)) {
9645rb_fs_check(
VALUE val)
9649 if (
NIL_P(val))
return 0;
9654static const char isspacetable[256] = {
9655 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
9656 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9657 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9658 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9659 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9660 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9661 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9662 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9663 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9664 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9665 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9666 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9667 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9668 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9669 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
9670 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
9673#define ascii_isspace(c) isspacetable[(unsigned char)(c)]
9676split_string(
VALUE result,
VALUE str,
long beg,
long len,
long empty_count)
9678 if (empty_count >= 0 &&
len == 0) {
9679 return empty_count + 1;
9681 if (empty_count > 0) {
9686 }
while (--empty_count > 0);
9690 rb_yield(str_new_empty_String(str));
9691 }
while (--empty_count > 0);
9705 SPLIT_TYPE_AWK, SPLIT_TYPE_STRING, SPLIT_TYPE_REGEXP, SPLIT_TYPE_CHARS
9709literal_split_pattern(
VALUE spat, split_type_t default_type)
9717 return SPLIT_TYPE_CHARS;
9719 else if (rb_enc_asciicompat(enc)) {
9720 if (
len == 1 && ptr[0] ==
' ') {
9721 return SPLIT_TYPE_AWK;
9726 if (rb_enc_ascget(ptr, ptr +
len, &l, enc) ==
' ' &&
len == l) {
9727 return SPLIT_TYPE_AWK;
9730 return default_type;
9743rb_str_split_m(
int argc,
VALUE *argv,
VALUE str)
9748 split_type_t split_type;
9749 long beg, end, i = 0, empty_count = -1;
9754 if (
rb_scan_args(argc, argv,
"02", &spat, &limit) == 2) {
9756 if (lim <= 0) limit =
Qnil;
9757 else if (lim == 1) {
9758 if (RSTRING_LEN(str) == 0)
9769 if (
NIL_P(limit) && !lim) empty_count = 0;
9771 enc = STR_ENC_GET(str);
9772 split_type = SPLIT_TYPE_REGEXP;
9774 spat = get_pat_quoted(spat, 0);
9776 else if (
NIL_P(spat = rb_fs)) {
9777 split_type = SPLIT_TYPE_AWK;
9779 else if (!(spat = rb_fs_check(spat))) {
9780 rb_raise(
rb_eTypeError,
"value of $; must be String or Regexp");
9785 if (split_type != SPLIT_TYPE_AWK) {
9790 split_type = literal_split_pattern(tmp, SPLIT_TYPE_REGEXP);
9791 if (split_type == SPLIT_TYPE_AWK) {
9793 split_type = SPLIT_TYPE_STRING;
9798 mustnot_broken(spat);
9799 split_type = literal_split_pattern(spat, SPLIT_TYPE_STRING);
9807#define SPLIT_STR(beg, len) ( \
9808 empty_count = split_string(result, str, beg, len, empty_count), \
9809 str_mod_check(str, str_start, str_len))
9812 const char *ptr = RSTRING_PTR(str);
9813 const char *
const str_start = ptr;
9814 const long str_len = RSTRING_LEN(str);
9815 const char *
const eptr = str_start + str_len;
9816 if (split_type == SPLIT_TYPE_AWK) {
9817 const char *bptr = ptr;
9823 if (is_ascii_string(str)) {
9824 while (ptr < eptr) {
9825 c = (
unsigned char)*ptr++;
9827 if (ascii_isspace(c)) {
9833 if (!
NIL_P(limit) && lim <= i)
break;
9836 else if (ascii_isspace(c)) {
9837 SPLIT_STR(beg, end-beg);
9840 if (!
NIL_P(limit)) ++i;
9848 while (ptr < eptr) {
9851 c = rb_enc_codepoint_len(ptr, eptr, &n, enc);
9860 if (!
NIL_P(limit) && lim <= i)
break;
9864 SPLIT_STR(beg, end-beg);
9867 if (!
NIL_P(limit)) ++i;
9875 else if (split_type == SPLIT_TYPE_STRING) {
9876 const char *substr_start = ptr;
9877 const char *sptr = RSTRING_PTR(spat);
9878 long slen = RSTRING_LEN(spat);
9881 mustnot_broken(str);
9882 enc = rb_enc_check(str, spat);
9883 while (ptr < eptr &&
9884 (end =
rb_memsearch(sptr, slen, ptr, eptr - ptr, enc)) >= 0) {
9887 if (t != ptr + end) {
9891 SPLIT_STR(substr_start - str_start, (ptr+end) - substr_start);
9892 str_mod_check(spat, sptr, slen);
9895 if (!
NIL_P(limit) && lim <= ++i)
break;
9897 beg = ptr - str_start;
9899 else if (split_type == SPLIT_TYPE_CHARS) {
9903 mustnot_broken(str);
9904 enc = rb_enc_get(str);
9905 while (ptr < eptr &&
9906 (n = rb_enc_precise_mbclen(ptr, eptr, enc)) > 0) {
9907 SPLIT_STR(ptr - str_start, n);
9909 if (!
NIL_P(limit) && lim <= ++i)
break;
9911 beg = ptr - str_start;
9915 long len = RSTRING_LEN(str);
9922 (match ? (rb_match_unbusy(match),
rb_backref_set(match)) : (void)0)) {
9925 end = RMATCH_BEG(match, 0);
9926 if (start == end && RMATCH_BEG(match, 0) == RMATCH_END(match, 0)) {
9931 else if (last_null == 1) {
9932 SPLIT_STR(beg, rb_enc_fast_mbclen(ptr+beg, eptr, enc));
9939 start += rb_enc_fast_mbclen(ptr+start,eptr,enc);
9945 SPLIT_STR(beg, end-beg);
9946 beg = start = RMATCH_END(match, 0);
9950 for (idx = 1; idx < RMATCH_NREGS(match); idx++) {
9951 if (RMATCH_BEG(match, idx) == -1)
continue;
9952 SPLIT_STR(RMATCH_BEG(match, idx), RMATCH_END(match, idx) - RMATCH_BEG(match, idx));
9954 if (!
NIL_P(limit) && lim <= ++i)
break;
9956 if (match) rb_match_unbusy(match);
9958 if (RSTRING_LEN(str) > 0 && (!
NIL_P(limit) || RSTRING_LEN(str) > beg || lim < 0)) {
9959 SPLIT_STR(beg, RSTRING_LEN(str)-beg);
9962 return result ? result : str;
9972 return rb_str_split_m(1, &sep, str);
9975#define WANTARRAY(m, size) (!rb_block_given_p() ? rb_ary_new_capa(size) : 0)
9990#define ENUM_ELEM(ary, e) enumerator_element(ary, e)
9993chomp_newline(
const char *p,
const char *e,
rb_encoding *enc)
9995 const char *prev = rb_enc_prev_char(p, e, e, enc);
9998 prev = rb_enc_prev_char(p, e, e, enc);
9999 if (prev && rb_enc_ascget(prev, e, NULL, enc) ==
'\r')
10011 RSTRING_LEN(rs) != 1 ||
10012 RSTRING_PTR(rs)[0] !=
'\n')) {
10018#define rb_rs get_rs()
10025 const char *pend, *subptr, *subend, *rsptr, *hit, *adjusted;
10031 if (!
NIL_P(opts)) {
10032 static ID keywords[1];
10033 if (!keywords[0]) {
10037 chomp = (!UNDEF_P(chomp) &&
RTEST(chomp));
10041 if (!ENUM_ELEM(ary, str)) {
10049 if (!RSTRING_LEN(str))
goto end;
10051 const char *
const ptr = subptr = RSTRING_PTR(str);
10052 const long len = RSTRING_LEN(str);
10055 rslen = RSTRING_LEN(rs);
10058 enc = rb_enc_get(str);
10060 enc = rb_enc_check(str, rs);
10065 const char *eol = NULL;
10067 while (subend < pend) {
10068 long chomp_rslen = 0;
10070 if (rb_enc_ascget(subend, pend, &n, enc) !=
'\r')
10072 rslen = n + rb_enc_mbclen(subend + n, pend, enc);
10074 if (eol == subend)
break;
10078 chomp_rslen = -rslen;
10082 if (!subptr) subptr = subend;
10086 }
while (subend < pend);
10087 if (!subptr)
break;
10088 if (rslen == 0) chomp_rslen = 0;
10090 subend - subptr + (chomp ? chomp_rslen : rslen));
10091 if (ENUM_ELEM(ary, line)) {
10092 str_mod_check(str, ptr,
len);
10094 subptr = eol = NULL;
10099 rsptr = RSTRING_PTR(rs);
10100 if (RSTRING_LEN(rs) == rb_enc_mbminlen(enc) &&
10109 rsptr = RSTRING_PTR(rs);
10110 rslen = RSTRING_LEN(rs);
10113 while (subptr < pend) {
10114 pos =
rb_memsearch(rsptr, rslen, subptr, pend - subptr, enc);
10115 if (pos < 0)
break;
10116 hit = subptr + pos;
10118 if (hit != adjusted) {
10122 subend = hit += rslen;
10125 subend = chomp_newline(subptr, subend, enc);
10132 if (ENUM_ELEM(ary, line)) {
10133 str_mod_check(str, ptr,
len);
10138 if (subptr != pend) {
10141 pend = chomp_newline(subptr, pend, enc);
10143 else if (pend - subptr >= rslen &&
10144 memcmp(pend - rslen, rsptr, rslen) == 0) {
10149 ENUM_ELEM(ary, line);
10170rb_str_each_line(
int argc,
VALUE *argv,
VALUE str)
10173 return rb_str_enumerate_lines(argc, argv, str, 0);
10228rb_str_lines(
int argc,
VALUE *argv,
VALUE str)
10230 VALUE ary = WANTARRAY(
"lines", 0);
10231 return rb_str_enumerate_lines(argc, argv, str, ary);
10237 return LONG2FIX(RSTRING_LEN(str));
10245 for (i=0; i<RSTRING_LEN(str); i++) {
10246 ENUM_ELEM(ary,
INT2FIX((
unsigned char)RSTRING_PTR(str)[i]));
10264rb_str_each_byte(
VALUE str)
10267 return rb_str_enumerate_bytes(str, 0);
10279rb_str_bytes(
VALUE str)
10281 VALUE ary = WANTARRAY(
"bytes", RSTRING_LEN(str));
10282 return rb_str_enumerate_bytes(str, ary);
10300 ptr = RSTRING_PTR(str);
10301 len = RSTRING_LEN(str);
10302 enc = rb_enc_get(str);
10305 for (i = 0; i <
len; i += n) {
10306 n = rb_enc_fast_mbclen(ptr + i, ptr +
len, enc);
10311 for (i = 0; i <
len; i += n) {
10312 n = rb_enc_mbclen(ptr + i, ptr +
len, enc);
10333rb_str_each_char(
VALUE str)
10336 return rb_str_enumerate_chars(str, 0);
10348rb_str_chars(
VALUE str)
10351 return rb_str_enumerate_chars(str, ary);
10355rb_str_enumerate_codepoints(
VALUE str,
VALUE ary)
10360 const char *ptr, *end;
10362 int enc_asciicompat;
10364 if (single_byte_optimizable(str))
10365 return rb_str_enumerate_bytes(str, ary);
10368 ptr = RSTRING_PTR(str);
10370 enc = STR_ENC_GET(str);
10371 enc_asciicompat = rb_enc_asciicompat(enc);
10373 while (ptr < end) {
10378 c = (enc_asciicompat &&
ISASCII(*ptr)) ?
10379 (
unsigned char)*ptr : rb_enc_codepoint_len(ptr, end, &n, enc);
10400rb_str_each_codepoint(
VALUE str)
10403 return rb_str_enumerate_codepoints(str, 0);
10415rb_str_codepoints(
VALUE str)
10418 return rb_str_enumerate_codepoints(str, ary);
10424 int encidx = rb_enc_to_index(enc);
10426 const OnigUChar source_ascii[] =
"\\X";
10427 const OnigUChar *source = source_ascii;
10428 size_t source_len =
sizeof(source_ascii) - 1;
10431#define CHARS_16BE(x) (OnigUChar)((x)>>8), (OnigUChar)(x)
10432#define CHARS_16LE(x) (OnigUChar)(x), (OnigUChar)((x)>>8)
10433#define CHARS_32BE(x) CHARS_16BE((x)>>16), CHARS_16BE(x)
10434#define CHARS_32LE(x) CHARS_16LE(x), CHARS_16LE((x)>>16)
10435#define CASE_UTF(e) \
10436 case ENCINDEX_UTF_##e: { \
10437 static const OnigUChar source_UTF_##e[] = {CHARS_##e('\\'), CHARS_##e('X')}; \
10438 source = source_UTF_##e; \
10439 source_len = sizeof(source_UTF_##e); \
10442 CASE_UTF(16BE); CASE_UTF(16LE); CASE_UTF(32BE); CASE_UTF(32LE);
10450 regex_t *reg_grapheme_cluster;
10452 int r = onig_new(®_grapheme_cluster, source, source + source_len,
10453 ONIG_OPTION_DEFAULT, enc, OnigDefaultSyntax, &einfo);
10455 UChar message[ONIG_MAX_ERROR_MESSAGE_LEN];
10456 onig_error_code_to_str(message, r, &einfo);
10457 rb_fatal(
"cannot compile grapheme cluster regexp: %s", (
char *)message);
10460 return reg_grapheme_cluster;
10466 int encidx = rb_enc_to_index(enc);
10467 static regex_t *reg_grapheme_cluster_utf8 = NULL;
10469 if (encidx == rb_utf8_encindex()) {
10470 if (!reg_grapheme_cluster_utf8) {
10471 reg_grapheme_cluster_utf8 = get_reg_grapheme_cluster(enc);
10474 return reg_grapheme_cluster_utf8;
10483 size_t grapheme_cluster_count = 0;
10485 const char *ptr, *end;
10487 if (!rb_enc_unicode_p(enc)) {
10491 bool cached_reg_grapheme_cluster =
true;
10492 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
10493 if (!reg_grapheme_cluster) {
10494 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
10495 cached_reg_grapheme_cluster =
false;
10498 ptr = RSTRING_PTR(str);
10501 while (ptr < end) {
10502 OnigPosition
len = onig_match(reg_grapheme_cluster,
10503 (
const OnigUChar *)ptr, (
const OnigUChar *)end,
10504 (
const OnigUChar *)ptr, NULL, 0);
10505 if (
len <= 0)
break;
10506 grapheme_cluster_count++;
10510 if (!cached_reg_grapheme_cluster) {
10511 onig_free(reg_grapheme_cluster);
10514 return SIZET2NUM(grapheme_cluster_count);
10518rb_str_enumerate_grapheme_clusters(
VALUE str,
VALUE ary)
10522 const char *ptr0, *ptr, *end;
10524 if (!rb_enc_unicode_p(enc)) {
10525 return rb_str_enumerate_chars(str, ary);
10530 bool cached_reg_grapheme_cluster =
true;
10531 regex_t *reg_grapheme_cluster = get_cached_reg_grapheme_cluster(enc);
10532 if (!reg_grapheme_cluster) {
10533 reg_grapheme_cluster = get_reg_grapheme_cluster(enc);
10534 cached_reg_grapheme_cluster =
false;
10537 ptr0 = ptr = RSTRING_PTR(str);
10540 while (ptr < end) {
10541 OnigPosition
len = onig_match(reg_grapheme_cluster,
10542 (
const OnigUChar *)ptr, (
const OnigUChar *)end,
10543 (
const OnigUChar *)ptr, NULL, 0);
10544 if (
len <= 0)
break;
10549 if (!cached_reg_grapheme_cluster) {
10550 onig_free(reg_grapheme_cluster);
10570rb_str_each_grapheme_cluster(
VALUE str)
10573 return rb_str_enumerate_grapheme_clusters(str, 0);
10585rb_str_grapheme_clusters(
VALUE str)
10588 return rb_str_enumerate_grapheme_clusters(str, ary);
10592chopped_length(
VALUE str)
10595 const char *p, *p2, *beg, *end;
10597 beg = RSTRING_PTR(str);
10598 end = beg + RSTRING_LEN(str);
10599 if (beg >= end)
return 0;
10600 p = rb_enc_prev_char(beg, end, end, enc);
10602 if (p > beg && rb_enc_ascget(p, end, 0, enc) ==
'\n') {
10603 p2 = rb_enc_prev_char(beg, p, end, enc);
10604 if (p2 && rb_enc_ascget(p2, end, 0, enc) ==
'\r') p = p2;
10622rb_str_chop_bang(
VALUE str)
10624 str_modify_keep_cr(str);
10625 if (RSTRING_LEN(str) > 0) {
10627 len = chopped_length(str);
10628 STR_SET_LEN(str,
len);
10629 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
10648rb_str_chop(
VALUE str)
10654smart_chomp(
VALUE str,
const char *e,
const char *p)
10657 if (rb_enc_mbminlen(enc) > 1) {
10662 pp = e - rb_enc_mbminlen(enc);
10665 if (rb_enc_ascget(pp, e, 0, enc) ==
'\r') {
10673 if (--e > p && *(e-1) ==
'\r') {
10690 const char *pp, *e, *rsptr;
10692 const char *
const p = RSTRING_PTR(str);
10693 long len = RSTRING_LEN(str);
10695 if (
len == 0)
return 0;
10698 return smart_chomp(str, e, p);
10701 enc = rb_enc_get(str);
10704 if (rb_enc_mbminlen(enc) > 1) {
10709 pp -= rb_enc_mbminlen(enc);
10712 if (rb_enc_ascget(pp, e, 0, enc) ==
'\r') {
10719 while (e > p && *(e-1) ==
'\n') {
10721 if (e > p && *(e-1) ==
'\r')
10727 if (rslen >
len)
return len;
10729 enc = rb_enc_get(rs);
10730 newline = rsptr[rslen-1];
10731 if (rslen == rb_enc_mbminlen(enc)) {
10733 if (newline ==
'\n')
10734 return smart_chomp(str, e, p);
10738 return smart_chomp(str, e, p);
10742 enc = rb_enc_check(str, rs);
10743 if (is_broken_string(rs)) {
10747 if (p[
len-1] == newline &&
10749 memcmp(rsptr, pp, rslen) == 0)) {
10750 if (at_char_boundary(p, pp, e, enc))
10751 return len - rslen;
10763chomp_rs(
int argc,
const VALUE *argv)
10767 VALUE rs = argv[0];
10779 long olen = RSTRING_LEN(str);
10780 long len = chompped_length(str, rs);
10781 if (
len >= olen)
return Qnil;
10782 str_modify_keep_cr(str);
10783 STR_SET_LEN(str,
len);
10784 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
10804rb_str_chomp_bang(
int argc,
VALUE *argv,
VALUE str)
10807 str_modifiable(str);
10808 if (RSTRING_LEN(str) == 0 && argc < 2)
return Qnil;
10809 rs = chomp_rs(argc, argv);
10811 return rb_str_chomp_string(str, rs);
10824rb_str_chomp(
int argc,
VALUE *argv,
VALUE str)
10826 VALUE rs = chomp_rs(argc, argv);
10832tr_setup_table_multi(
char table[TR_TABLE_SIZE],
VALUE *tablep,
VALUE *ctablep,
10833 VALUE str,
int num_selectors,
VALUE *selectors)
10837 for (i=0; i<num_selectors; i++) {
10838 VALUE selector = selectors[i];
10842 enc = rb_enc_check(str, selector);
10843 tr_setup_table(selector, table, i==0, tablep, ctablep, enc);
10850 const char *
const start = s;
10852 if (!s || s >= e)
return 0;
10855 if (single_byte_optimizable(str)) {
10856 while (s < e && (*s ==
'\0' || ascii_isspace(*s))) s++;
10861 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
10871lstrip_offset_table(
VALUE str,
const char *s,
const char *e,
rb_encoding *enc,
10872 char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
10874 const char *
const start = s;
10876 if (!s || s >= e)
return 0;
10881 unsigned int cc = rb_enc_codepoint_len(s, e, &n, enc);
10883 if (!tr_find(cc, table, del, nodel))
break;
10902rb_str_lstrip_bang(
int argc,
VALUE *argv,
VALUE str)
10906 long olen, loffset;
10908 str_modify_keep_cr(str);
10909 enc = STR_ENC_GET(str);
10912 char table[TR_TABLE_SIZE];
10913 VALUE del = 0, nodel = 0;
10915 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10916 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
10919 loffset = lstrip_offset(str, start, start+olen, enc);
10923 long len = olen-loffset;
10924 memmove(start, start + loffset,
len);
10925 STR_SET_LEN(str,
len);
10926 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
10961rb_str_lstrip(
int argc,
VALUE *argv,
VALUE str)
10968 char table[TR_TABLE_SIZE];
10969 VALUE del = 0, nodel = 0;
10971 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
10972 loffset = lstrip_offset_table(str, start, start+
len, STR_ENC_GET(str), table, del, nodel);
10975 loffset = lstrip_offset(str, start, start+
len, STR_ENC_GET(str));
10977 if (loffset <= 0)
return str_duplicate(
rb_cString, str);
10986 rb_str_check_dummy_enc(enc);
10990 if (!s || s >= e)
return 0;
10994 if (single_byte_optimizable(str)) {
10996 while (s < t && ((c = *(t-1)) ==
'\0' || ascii_isspace(c))) t--;
11001 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
11011rstrip_offset_table(
VALUE str,
const char *s,
const char *e,
rb_encoding *enc,
11012 char table[TR_TABLE_SIZE],
VALUE del,
VALUE nodel)
11014 const char *t, *tp;
11016 rb_str_check_dummy_enc(enc);
11020 if (!s || s >= e)
return 0;
11024 while ((tp = rb_enc_prev_char(s, t, e, enc)) != NULL) {
11026 if (!tr_find(c, table, del, nodel))
break;
11046rb_str_rstrip_bang(
int argc,
VALUE *argv,
VALUE str)
11050 long olen, roffset;
11052 str_modify_keep_cr(str);
11053 enc = STR_ENC_GET(str);
11056 char table[TR_TABLE_SIZE];
11057 VALUE del = 0, nodel = 0;
11059 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11060 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11063 roffset = rstrip_offset(str, start, start+olen, enc);
11066 long len = olen - roffset;
11068 STR_SET_LEN(str,
len);
11069 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
11103rb_str_rstrip(
int argc,
VALUE *argv,
VALUE str)
11107 long olen, roffset;
11109 enc = STR_ENC_GET(str);
11112 char table[TR_TABLE_SIZE];
11113 VALUE del = 0, nodel = 0;
11115 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11116 roffset = rstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11119 roffset = rstrip_offset(str, start, start+olen, enc);
11121 if (roffset <= 0)
return str_duplicate(
rb_cString, str);
11139rb_str_strip_bang(
int argc,
VALUE *argv,
VALUE str)
11142 long olen, loffset, roffset;
11145 str_modify_keep_cr(str);
11146 enc = STR_ENC_GET(str);
11150 char table[TR_TABLE_SIZE];
11151 VALUE del = 0, nodel = 0;
11153 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11154 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11155 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
11158 loffset = lstrip_offset(str, start, start+olen, enc);
11159 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
11162 if (loffset > 0 || roffset > 0) {
11163 long len = olen-roffset;
11166 memmove(start, start + loffset,
len);
11168 STR_SET_LEN(str,
len);
11169 TERM_FILL(start+
len, rb_enc_mbminlen(enc));
11204rb_str_strip(
int argc,
VALUE *argv,
VALUE str)
11207 long olen, loffset, roffset;
11213 char table[TR_TABLE_SIZE];
11214 VALUE del = 0, nodel = 0;
11216 tr_setup_table_multi(table, &del, &nodel, str, argc, argv);
11217 loffset = lstrip_offset_table(str, start, start+olen, enc, table, del, nodel);
11218 roffset = rstrip_offset_table(str, start+loffset, start+olen, enc, table, del, nodel);
11221 loffset = lstrip_offset(str, start, start+olen, enc);
11222 roffset = rstrip_offset(str, start+loffset, start+olen, enc);
11225 if (loffset <= 0 && roffset <= 0)
return str_duplicate(
rb_cString, str);
11230scan_once(
VALUE str,
VALUE pat,
long *start,
int set_backref_str)
11233 long end, pos = rb_pat_search(pat, str, *start, set_backref_str);
11237 end = pos + RSTRING_LEN(pat);
11241 pos = RMATCH_BEG(match, 0);
11242 end = RMATCH_END(match, 0);
11250 if (RSTRING_LEN(str) > end)
11251 *start = end + rb_enc_fast_mbclen(RSTRING_PTR(str) + end,
11260 if (
NIL_P(match) || RMATCH_NREGS(match) == 1) {
11265 int num_regs = RMATCH_NREGS(match);
11267 for (
int i = 1; i < num_regs; i++) {
11269 if (RMATCH_BEG(match, i) >= 0) {
11270 s =
rb_str_subseq(str, RMATCH_BEG(match, i), RMATCH_END(match, i) - RMATCH_BEG(match, i));
11298 long last = -1, prev = 0;
11299 const char *p = RSTRING_PTR(str);
11300 long len = RSTRING_LEN(str);
11302 pat = get_pat_quoted(pat, 1);
11303 mustnot_broken(str);
11307 while (!
NIL_P(result = scan_once(str, pat, &start, 0))) {
11312 if (last >= 0) rb_pat_search(pat, str, last, 1);
11317 while (!
NIL_P(result = scan_once(str, pat, &start, 1))) {
11321 str_mod_check(str, p,
len);
11323 if (last >= 0) rb_pat_search(pat, str, last, 1);
11375rb_str_hex(
VALUE str)
11377 return rb_str_to_inum(str, 16, FALSE);
11461rb_str_oct(
VALUE str)
11463 return rb_str_to_inum(str, -8, FALSE);
11466#ifndef HAVE_CRYPT_R
11471 rb_nativethread_lock_t lock;
11472} crypt_mutex = {PTHREAD_MUTEX_INITIALIZER};
11541# define CRYPT_END() ALLOCV_END(databuf)
11544 extern char *crypt(
const char *,
const char *);
11545# define CRYPT_END() rb_nativethread_lock_unlock(&crypt_mutex.lock)
11548 const char *s, *saltp, *res;
11550 char salt_8bit_clean[3];
11554 mustnot_wchar(str);
11555 mustnot_wchar(salt);
11557 saltp = RSTRING_PTR(salt);
11558 if (RSTRING_LEN(salt) < 2 || !saltp[0] || !saltp[1]) {
11559 rb_raise(rb_eArgError,
"salt too short (need >=2 bytes)");
11563 if (!
ISASCII((
unsigned char)saltp[0]) || !
ISASCII((
unsigned char)saltp[1])) {
11564 salt_8bit_clean[0] = saltp[0] & 0x7f;
11565 salt_8bit_clean[1] = saltp[1] & 0x7f;
11566 salt_8bit_clean[2] =
'\0';
11567 saltp = salt_8bit_clean;
11572# ifdef HAVE_STRUCT_CRYPT_DATA_INITIALIZED
11573 data->initialized = 0;
11575 res = crypt_r(s, saltp, data);
11578 res = crypt(s, saltp);
11593 size_t res_size = strlen(res);
11594 tmp_buf =
ALLOCA_N(
char, res_size);
11595 memcpy(tmp_buf, res, res_size);
11631 char *ptr, *p, *pend;
11634 unsigned long sum0 = 0;
11639 ptr = p = RSTRING_PTR(str);
11640 len = RSTRING_LEN(str);
11646 str_mod_check(str, ptr,
len);
11649 sum0 += (
unsigned char)*p;
11660 if (bits < (
int)
sizeof(
long)*CHAR_BIT) {
11661 sum0 &= (((
unsigned long)1)<<bits)-1;
11681rb_str_justify(
int argc,
VALUE *argv,
VALUE str,
char jflag)
11685 long width,
len, flen = 1, fclen = 1;
11688 const char *f =
" ";
11689 long n, size, llen, rlen, llen2 = 0, rlen2 = 0;
11691 int singlebyte = 1, cr;
11695 enc = STR_ENC_GET(str);
11699 enc = rb_enc_check(str, pad);
11700 f = RSTRING_PTR(pad);
11701 flen = RSTRING_LEN(pad);
11702 fclen = str_strlen(pad, enc);
11703 singlebyte = single_byte_optimizable(pad);
11704 if (flen == 0 || fclen == 0) {
11705 rb_raise(rb_eArgError,
"zero width padding");
11708 termlen = rb_enc_mbminlen(enc);
11709 len = str_strlen(str, enc);
11710 if (width < 0 || len >= width)
return str_duplicate(
rb_cString, str);
11712 llen = (jflag ==
'l') ? 0 : ((jflag ==
'r') ? n : n/2);
11716 llen2 = str_offset(f, f + flen, llen % fclen, enc, singlebyte);
11717 rlen2 = str_offset(f, f + flen, rlen % fclen, enc, singlebyte);
11719 size = RSTRING_LEN(str);
11720 if ((
len = llen / fclen + rlen / fclen) >= LONG_MAX / flen ||
11721 (
len *= flen) >= LONG_MAX - llen2 - rlen2 ||
11722 (
len += llen2 + rlen2) >= LONG_MAX - size) {
11723 rb_raise(rb_eArgError,
"argument too big");
11727 p = RSTRING_PTR(res);
11729 memset(p, *f, llen);
11733 while (llen >= fclen) {
11739 memcpy(p, f, llen2);
11743 memcpy(p, RSTRING_PTR(str), size);
11746 memset(p, *f, rlen);
11750 while (rlen >= fclen) {
11756 memcpy(p, f, rlen2);
11760 TERM_FILL(p, termlen);
11761 STR_SET_LEN(res, p-RSTRING_PTR(res));
11782rb_str_ljust(
int argc,
VALUE *argv,
VALUE str)
11784 return rb_str_justify(argc, argv, str,
'l');
11796rb_str_rjust(
int argc,
VALUE *argv,
VALUE str)
11798 return rb_str_justify(argc, argv, str,
'r');
11811rb_str_center(
int argc,
VALUE *argv,
VALUE str)
11813 return rb_str_justify(argc, argv, str,
'c');
11829 sep = get_pat_quoted(sep, 0);
11836 pos = RMATCH_BEG(match, 0);
11840 pos = rb_str_index(str, sep, 0);
11841 if (pos < 0)
goto failed;
11846 RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
11849 return rb_ary_new3(3, str_duplicate(
rb_cString, str), str_new_empty_String(str), str_new_empty_String(str));
11863 long pos = RSTRING_LEN(str);
11865 sep = get_pat_quoted(sep, 0);
11872 pos = RMATCH_BEG(match, 0);
11877 pos = rb_str_rindex(str, sep, pos);
11886 RSTRING_LEN(str)-pos-RSTRING_LEN(sep)));
11888 return rb_ary_new3(3, str_new_empty_String(str), str_new_empty_String(str), str_duplicate(
rb_cString, str));
11900rb_str_start_with(
int argc,
VALUE *argv,
VALUE str)
11904 for (i=0; i<argc; i++) {
11905 VALUE tmp = argv[i];
11907 if (rb_reg_start_with_p(tmp, str))
11911 const char *p, *s, *e;
11916 enc = rb_enc_check(str, tmp);
11917 if ((tlen = RSTRING_LEN(tmp)) == 0)
return Qtrue;
11918 if ((slen = RSTRING_LEN(str)) < tlen)
continue;
11919 p = RSTRING_PTR(str);
11922 if (!at_char_right_boundary(p, s, e, enc))
11924 if (memcmp(p, RSTRING_PTR(tmp), tlen) == 0)
11940rb_str_end_with(
int argc,
VALUE *argv,
VALUE str)
11944 for (i=0; i<argc; i++) {
11945 VALUE tmp = argv[i];
11946 const char *p, *s, *e;
11951 enc = rb_enc_check(str, tmp);
11952 if ((tlen = RSTRING_LEN(tmp)) == 0)
return Qtrue;
11953 if ((slen = RSTRING_LEN(str)) < tlen)
continue;
11954 p = RSTRING_PTR(str);
11957 if (!at_char_boundary(p, s, e, enc))
11959 if (memcmp(s, RSTRING_PTR(tmp), tlen) == 0)
11975deleted_prefix_length(
VALUE str,
VALUE prefix)
11977 const char *strptr, *prefixptr;
11978 long olen, prefixlen;
11983 if (!is_broken_string(prefix) ||
11984 !rb_enc_asciicompat(enc) ||
11985 !rb_enc_asciicompat(rb_enc_get(prefix))) {
11986 enc = rb_enc_check(str, prefix);
11990 prefixlen = RSTRING_LEN(prefix);
11991 if (prefixlen <= 0)
return 0;
11992 olen = RSTRING_LEN(str);
11993 if (olen < prefixlen)
return 0;
11994 strptr = RSTRING_PTR(str);
11995 prefixptr = RSTRING_PTR(prefix);
11996 if (memcmp(strptr, prefixptr, prefixlen) != 0)
return 0;
11997 if (is_broken_string(prefix)) {
11998 if (!is_broken_string(str)) {
12002 const char *strend = strptr + olen;
12003 const char *after_prefix = strptr + prefixlen;
12004 if (!at_char_right_boundary(strptr, after_prefix, strend, enc)) {
12025rb_str_delete_prefix_bang(
VALUE str,
VALUE prefix)
12028 str_modify_keep_cr(str);
12030 prefixlen = deleted_prefix_length(str, prefix);
12031 if (prefixlen <= 0)
return Qnil;
12045rb_str_delete_prefix(
VALUE str,
VALUE prefix)
12049 prefixlen = deleted_prefix_length(str, prefix);
12050 if (prefixlen <= 0)
return str_duplicate(
rb_cString, str);
12052 return rb_str_subseq(str, prefixlen, RSTRING_LEN(str) - prefixlen);
12065deleted_suffix_length(
VALUE str,
VALUE suffix)
12067 const char *strptr, *suffixptr;
12068 long olen, suffixlen;
12072 if (is_broken_string(suffix))
return 0;
12073 enc = rb_enc_check(str, suffix);
12076 suffixlen = RSTRING_LEN(suffix);
12077 if (suffixlen <= 0)
return 0;
12078 olen = RSTRING_LEN(str);
12079 if (olen < suffixlen)
return 0;
12080 strptr = RSTRING_PTR(str);
12081 suffixptr = RSTRING_PTR(suffix);
12082 const char *strend = strptr + olen;
12083 const char *before_suffix = strend - suffixlen;
12084 if (memcmp(before_suffix, suffixptr, suffixlen) != 0)
return 0;
12085 if (!at_char_boundary(strptr, before_suffix, strend, enc))
return 0;
12101rb_str_delete_suffix_bang(
VALUE str,
VALUE suffix)
12103 long olen, suffixlen,
len;
12104 str_modifiable(str);
12106 suffixlen = deleted_suffix_length(str, suffix);
12107 if (suffixlen <= 0)
return Qnil;
12109 olen = RSTRING_LEN(str);
12110 str_modify_keep_cr(str);
12111 len = olen - suffixlen;
12112 STR_SET_LEN(str,
len);
12113 TERM_FILL(&RSTRING_PTR(str)[
len], TERM_LEN(str));
12129rb_str_delete_suffix(
VALUE str,
VALUE suffix)
12133 suffixlen = deleted_suffix_length(str, suffix);
12134 if (suffixlen <= 0)
return str_duplicate(
rb_cString, str);
12136 return rb_str_subseq(str, 0, RSTRING_LEN(str) - suffixlen);
12143 rb_raise(
rb_eTypeError,
"value of %"PRIsVALUE
" must be String", rb_id2str(
id));
12149nil_setter_warning(
ID id)
12151 rb_warn_deprecated(
"non-nil '%"PRIsVALUE
"'", NULL, rb_id2str(
id));
12158 if (!
NIL_P(*var)) {
12159 nil_setter_warning(
id);
12166 val = rb_fs_check(val);
12169 "value of %"PRIsVALUE
" must be String or Regexp",
12173 nil_setter_warning(
id);
12190 str_modifiable(str);
12193 int idx = rb_enc_to_index(encoding);
12200 rb_enc_associate_index(str, idx);
12224 if (STR_EMBED_P(str)) {
12225 str2 = str_alloc_embed(
rb_cString, RSTRING_LEN(str) + TERM_LEN(str));
12230 str_replace_shared_without_enc(str2, str);
12232 if (rb_enc_asciicompat(STR_ENC_GET(str))) {
12255rb_str_valid_encoding_p(
VALUE str)
12257 int cr = rb_enc_str_coderange(str);
12264rb_str_is_ascii_only_p(
VALUE str)
12266 int cr = rb_enc_str_coderange(str);
12274 static const char ellipsis[] =
"...";
12275 const long ellipsislen =
sizeof(ellipsis) - 1;
12277 const long blen = RSTRING_LEN(str);
12278 const char *
const p = RSTRING_PTR(str), *e = p + blen;
12279 VALUE estr, ret = 0;
12282 if (
len * rb_enc_mbminlen(enc) >= blen ||
12286 else if (
len <= ellipsislen ||
12288 if (rb_enc_asciicompat(enc)) {
12290 rb_enc_associate(ret, enc);
12297 else if (ret =
rb_str_subseq(str, 0, e - p), rb_enc_asciicompat(enc)) {
12302 rb_enc_from_encoding(enc), 0,
Qnil);
12313 cr = rb_enc_str_coderange(str);
12315 rb_raise(rb_eArgError,
"replacement must be valid byte sequence '%+"PRIsVALUE
"'", str);
12321 rb_enc_inspect_name(enc), rb_enc_inspect_name(e));
12340 if (enc == STR_ENC_GET(str)) {
12345 return enc_str_scrub(enc, str, repl, cr);
12353 const char *rep, *p, *e, *p1, *sp;
12359 rb_raise(rb_eArgError,
"both of block and replacement given");
12366 if (!
NIL_P(repl)) {
12367 repl = str_compat_and_valid(repl, enc);
12370 if (rb_enc_dummy_p(enc)) {
12373 encidx = rb_enc_to_index(enc);
12375#define DEFAULT_REPLACE_CHAR(str) do { \
12376 RBIMPL_ATTR_NONSTRING() static const char replace[sizeof(str)-1] = str; \
12377 rep = replace; replen = (int)sizeof(replace); \
12380 slen = RSTRING_LEN(str);
12381 p = RSTRING_PTR(str);
12386 if (rb_enc_asciicompat(enc)) {
12392 else if (!
NIL_P(repl)) {
12393 rep = RSTRING_PTR(repl);
12394 replen = RSTRING_LEN(repl);
12397 else if (encidx == rb_utf8_encindex()) {
12398 DEFAULT_REPLACE_CHAR(
"\xEF\xBF\xBD");
12402 DEFAULT_REPLACE_CHAR(
"?");
12407 p = search_nonascii(p, e);
12412 int ret = rb_enc_precise_mbclen(p, e, enc);
12420 p = search_nonascii(p, e);
12437 if (e - p < clen) clen = e - p;
12444 for (; clen > 1; clen--) {
12445 ret = rb_enc_precise_mbclen(q, q + clen, enc);
12456 repl =
rb_yield(rb_enc_str_new(p, clen, enc));
12457 str_mod_check(str, sp, slen);
12458 repl = str_compat_and_valid(repl, enc);
12465 p = search_nonascii(p, e);
12491 repl =
rb_yield(rb_enc_str_new(p, e-p, enc));
12492 str_mod_check(str, sp, slen);
12493 repl = str_compat_and_valid(repl, enc);
12502 long mbminlen = rb_enc_mbminlen(enc);
12506 else if (!
NIL_P(repl)) {
12507 rep = RSTRING_PTR(repl);
12508 replen = RSTRING_LEN(repl);
12510 else if (encidx == ENCINDEX_UTF_16BE) {
12511 DEFAULT_REPLACE_CHAR(
"\xFF\xFD");
12513 else if (encidx == ENCINDEX_UTF_16LE) {
12514 DEFAULT_REPLACE_CHAR(
"\xFD\xFF");
12516 else if (encidx == ENCINDEX_UTF_32BE) {
12517 DEFAULT_REPLACE_CHAR(
"\x00\x00\xFF\xFD");
12519 else if (encidx == ENCINDEX_UTF_32LE) {
12520 DEFAULT_REPLACE_CHAR(
"\xFD\xFF\x00\x00");
12523 DEFAULT_REPLACE_CHAR(
"?");
12527 int ret = rb_enc_precise_mbclen(p, e, enc);
12540 if (e - p < clen) clen = e - p;
12541 if (clen <= mbminlen * 2) {
12546 for (; clen > mbminlen; clen-=mbminlen) {
12547 ret = rb_enc_precise_mbclen(q, q + clen, enc);
12557 repl =
rb_yield(rb_enc_str_new(p, clen, enc));
12558 str_mod_check(str, sp, slen);
12559 repl = str_compat_and_valid(repl, enc);
12584 repl =
rb_yield(rb_enc_str_new(p, e-p, enc));
12585 str_mod_check(str, sp, slen);
12586 repl = str_compat_and_valid(repl, enc);
12626str_scrub_bang(
int argc,
VALUE *argv,
VALUE str)
12634static ID id_normalize;
12635static ID id_normalized_p;
12636static VALUE mUnicodeNormalize;
12639unicode_normalize_common(
int argc,
VALUE *argv,
VALUE str,
ID id)
12641 static int UnicodeNormalizeRequired = 0;
12644 if (!UnicodeNormalizeRequired) {
12645 rb_require(
"unicode_normalize/normalize.rb");
12646 UnicodeNormalizeRequired = 1;
12650 return rb_funcallv(mUnicodeNormalize,
id, argc+1, argv2);
12661rb_str_unicode_normalize(
int argc,
VALUE *argv,
VALUE str)
12663 return unicode_normalize_common(argc, argv, str, id_normalize);
12677rb_str_unicode_normalize_bang(
int argc,
VALUE *argv,
VALUE str)
12679 return rb_str_replace(str, unicode_normalize_common(argc, argv, str, id_normalize));
12706rb_str_unicode_normalized_p(
int argc,
VALUE *argv,
VALUE str)
12708 return unicode_normalize_common(argc, argv, str, id_normalized_p);
12840#define sym_equal rb_obj_equal
12843sym_printable(
const char *s,
const char *send,
rb_encoding *enc)
12847 int c = rb_enc_precise_mbclen(s, send, enc);
12851 c = rb_enc_mbc_to_codepoint(s, send, enc);
12859rb_str_symname_p(
VALUE sym)
12864 rb_encoding *resenc = rb_default_internal_encoding();
12866 if (resenc == NULL) resenc = rb_default_external_encoding();
12867 enc = STR_ENC_GET(sym);
12868 ptr = RSTRING_PTR(sym);
12869 len = RSTRING_LEN(sym);
12870 if ((resenc != enc && !rb_str_is_ascii_only_p(sym)) ||
len != (
long)strlen(ptr) ||
12878rb_str_quote_unprintable(
VALUE str)
12886 resenc = rb_default_internal_encoding();
12887 if (resenc == NULL) resenc = rb_default_external_encoding();
12888 enc = STR_ENC_GET(str);
12889 ptr = RSTRING_PTR(str);
12890 len = RSTRING_LEN(str);
12891 if ((resenc != enc && !rb_str_is_ascii_only_p(str)) ||
12892 !sym_printable(ptr, ptr +
len, enc)) {
12893 return rb_str_escape(str);
12899rb_id_quote_unprintable(
ID id)
12901 VALUE str = rb_id2str(
id);
12902 if (!rb_str_symname_p(str)) {
12903 return rb_str_escape(str);
12921sym_inspect(
VALUE sym)
12928 if (!rb_str_symname_p(str)) {
12930 len = RSTRING_LEN(str);
12931 rb_str_resize(str,
len + 1);
12932 dest = RSTRING_PTR(str);
12933 memmove(dest + 1, dest,
len);
12937 VALUE orig_str = str;
12939 len = RSTRING_LEN(orig_str);
12940 str = rb_enc_str_new(0,
len + 1, enc);
12943 ptr = RSTRING_PTR(orig_str);
12944 dest = RSTRING_PTR(str);
12945 memcpy(dest + 1, ptr,
len);
12963rb_sym_proc_call(
ID mid,
int argc,
const VALUE *argv,
int kw_splat,
VALUE passed_proc)
12968 rb_raise(rb_eArgError,
"no receiver given");
13071 return rb_str_match(
rb_sym2str(sym), other);
13086sym_match_m(
int argc,
VALUE *argv,
VALUE sym)
13088 return rb_str_match_m(argc, argv,
rb_sym2str(sym));
13101sym_match_m_p(
int argc,
VALUE *argv,
VALUE sym)
13103 return rb_str_match_m_p(argc, argv, sym);
13121 return rb_str_aref_m(argc, argv,
rb_sym2str(sym));
13132sym_length(
VALUE sym)
13166sym_downcase(
int argc,
VALUE *argv,
VALUE sym)
13182sym_capitalize(
int argc,
VALUE *argv,
VALUE sym)
13198sym_swapcase(
int argc,
VALUE *argv,
VALUE sym)
13212sym_start_with(
int argc,
VALUE *argv,
VALUE sym)
13214 return rb_str_start_with(argc, argv,
rb_sym2str(sym));
13227sym_end_with(
int argc,
VALUE *argv,
VALUE sym)
13229 return rb_str_end_with(argc, argv,
rb_sym2str(sym));
13241sym_encoding(
VALUE sym)
13247string_for_symbol(
VALUE name)
13252 rb_raise(
rb_eTypeError,
"%+"PRIsVALUE
" is not a symbol nor a string",
13266 name = string_for_symbol(name);
13267 return rb_intern_str(name);
13276 name = string_for_symbol(name);
13300 return rb_fstring(str);
13306 struct RString fake_str = {RBASIC_INIT};
13307 int encidx = ENCINDEX_US_ASCII;
13310 encidx = ENCINDEX_ASCII_8BIT;
13313 VALUE str = setup_fake_str(&fake_str,
ptr,
len, encidx);
13315 return register_fstring(str,
true,
false);
13327 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
13328 rb_enc_autoload(enc);
13331 struct RString fake_str = {RBASIC_INIT};
13332 return register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
true,
false);
13338 if (enc != NULL && UNLIKELY(rb_enc_autoload_p(enc))) {
13339 rb_enc_autoload(enc);
13342 struct RString fake_str = {RBASIC_INIT};
13343 VALUE str = register_fstring(rb_setup_fake_str(&fake_str,
ptr,
len, enc),
true,
true);
13354#if USE_YJIT || USE_ZJIT
13356rb_jit_str_concat_codepoint(
VALUE str,
VALUE codepoint)
13361 if (RB_LIKELY(code >= 0 && code < 0xff)) {
13362 rb_str_buf_cat_byte(str, (
char) code);
13372fstring_set_class_i(
VALUE *str,
void *data)
13376 return ST_CONTINUE;
13384 rb_concurrent_set_foreach_with_replace(fstring_table_obj, fstring_set_class_i, NULL);
13552 mUnicodeNormalize = rb_define_module(
"UnicodeNormalize");
13563 rb_gc_register_address(&
rb_fs);
13601#include "string.rbinc"
#define RUBY_ASSERT_ALWAYS(expr,...)
A variant of RUBY_ASSERT that does not interface with 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).
#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 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_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass)
Identical to rb_class_new_instance(), except it passes the passed keywords if any to the #initialize ...
VALUE rb_obj_frozen_p(VALUE obj)
Just calls RB_OBJ_FROZEN() inside.
double rb_str_to_dbl(VALUE str, int mode)
Identical to rb_cstr_to_dbl(), except it accepts a Ruby's string instead of C's.
VALUE rb_obj_class(VALUE obj)
Queries the class of an object.
VALUE rb_obj_dup(VALUE obj)
Duplicates the given object.
VALUE rb_cSymbol
Symbol class.
VALUE rb_equal(VALUE lhs, VALUE rhs)
This function is an optimised version of calling #==.
VALUE rb_obj_freeze(VALUE obj)
Just calls rb_obj_freeze_inline() inside.
VALUE rb_mComparable
Comparable module.
VALUE rb_cString
String class.
VALUE rb_to_int(VALUE val)
Identical to rb_check_to_int(), except it raises in case of conversion mismatch.
static char * rb_enc_left_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the left boundary of a character.
static char * rb_enc_right_char_head(const char *s, const char *p, const char *e, rb_encoding *enc)
Queries the right boundary of a character.
static unsigned int rb_enc_codepoint(const char *p, const char *e, rb_encoding *enc)
Queries the code point of character pointed by the passed pointer.
static int rb_enc_mbmaxlen(rb_encoding *enc)
Queries the maximum number of bytes that the passed encoding needs to represent a character.
static int RB_ENCODING_GET_INLINED(VALUE obj)
Queries the encoding of the passed object.
static int rb_enc_code_to_mbclen(int c, rb_encoding *enc)
Identical to rb_enc_codelen(), except it returns 0 for invalid code points.
static char * rb_enc_step_back(const char *s, const char *p, const char *e, int n, rb_encoding *enc)
Scans the string backwards for n characters.
VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to)
Encoding conversion main routine.
VALUE rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc)
Identical to rb_enc_str_new(), except it takes a C string literal.
char * rb_enc_nth(const char *head, const char *tail, long nth, rb_encoding *enc)
Queries the n-th character.
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts)
Identical to rb_str_conv_enc(), except it additionally takes IO encoder options.
VALUE rb_enc_interned_str(const char *ptr, long len, rb_encoding *enc)
Identical to rb_enc_str_new(), except it returns a "f"string.
long rb_memsearch(const void *x, long m, const void *y, long n, rb_encoding *enc)
Looks for the passed string in the passed buffer.
long rb_enc_strlen(const char *head, const char *tail, rb_encoding *enc)
Counts the number of characters of the passed string, according to the passed encoding.
VALUE rb_enc_str_buf_cat(VALUE str, const char *ptr, long len, rb_encoding *enc)
Identical to rb_str_cat(), except it additionally takes an encoding.
VALUE rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
Identical to rb_enc_str_new(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_export_to_enc(VALUE obj, rb_encoding *enc)
Identical to rb_str_export(), except it additionally takes an encoding.
VALUE rb_external_str_new_with_enc(const char *ptr, long len, rb_encoding *enc)
Identical to rb_external_str_new(), except it additionally takes an encoding.
int rb_enc_str_asciionly_p(VALUE str)
Queries if the passed string is "ASCII only".
VALUE rb_enc_interned_str_cstr(const char *ptr, rb_encoding *enc)
Identical to rb_enc_str_new_cstr(), except it returns a "f"string.
long rb_str_coderange_scan_restartable(const char *str, const char *end, rb_encoding *enc, int *cr)
Scans the passed string until it finds something odd.
int rb_enc_symname2_p(const char *name, long len, rb_encoding *enc)
Identical to rb_enc_symname_p(), except it additionally takes the passed string's length.
rb_econv_result_t rb_econv_convert(rb_econv_t *ec, const unsigned char **source_buffer_ptr, const unsigned char *source_buffer_end, unsigned char **destination_buffer_ptr, unsigned char *destination_buffer_end, int flags)
Converts a string from an encoding to another.
rb_econv_result_t
return value of rb_econv_convert()
@ econv_finished
The conversion stopped after converting everything.
@ econv_destination_buffer_full
The conversion stopped because there is no destination.
rb_econv_t * rb_econv_open_opts(const char *source_encoding, const char *destination_encoding, int ecflags, VALUE ecopts)
Identical to rb_econv_open(), except it additionally takes a hash of optional strings.
VALUE rb_str_encode(VALUE str, VALUE to, int ecflags, VALUE ecopts)
Converts the contents of the passed string from its encoding to the passed one.
void rb_econv_close(rb_econv_t *ec)
Destructs a converter.
VALUE rb_funcall(VALUE recv, ID mid, int n,...)
Calls a method.
VALUE rb_funcallv(VALUE recv, ID mid, int argc, const VALUE *argv)
Identical to rb_funcall(), except it takes the method arguments as a C array.
VALUE rb_funcall_with_block_kw(VALUE recv, ID mid, int argc, const VALUE *argv, VALUE procval, int kw_splat)
Identical to rb_funcallv_with_block(), except you can specify how to handle the last element of the g...
VALUE rb_check_array_type(VALUE obj)
Try converting an object to its array representation using its to_ary method, if any.
VALUE rb_ary_new(void)
Allocates a new, empty array.
VALUE rb_ary_new_capa(long capa)
Identical to rb_ary_new(), except it additionally specifies how many rooms of objects it should alloc...
VALUE rb_ary_push(VALUE ary, VALUE elem)
Special case of rb_ary_cat() that it adds only one element.
VALUE rb_ary_freeze(VALUE obj)
Freeze an array, preventing further modifications.
#define RETURN_SIZED_ENUMERATOR(obj, argc, argv, size_fn)
This roughly resembles return enum_for(__callee__) unless block_given?.
#define RETURN_ENUMERATOR(obj, argc, argv)
Identical to RETURN_SIZED_ENUMERATOR(), except its size is unknown.
#define UNLIMITED_ARGUMENTS
This macro is used in conjunction with rb_check_arity().
static int rb_check_arity(int argc, int min, int max)
Ensures that the passed integer is in the passed range.
VALUE rb_fs
The field separator character for inputs, or the $;.
VALUE rb_default_rs
This is the default value of rb_rs, i.e.
VALUE rb_backref_get(void)
Queries the last match, or Regexp.last_match, or the $~.
VALUE rb_sym_all_symbols(void)
Collects every single bits of symbols that have ever interned in the entire history of the current pr...
void rb_backref_set(VALUE md)
Updates $~.
VALUE rb_range_beg_len(VALUE range, long *begp, long *lenp, long len, int err)
Deconstructs a numerical range.
int rb_reg_backref_number(VALUE match, VALUE backref)
Queries the index of the given named capture.
int rb_reg_options(VALUE re)
Queries the options of the passed regular expression.
VALUE rb_reg_match(VALUE re, VALUE str)
This is the match operator.
void rb_match_busy(VALUE md)
Asserts that the given MatchData is "occupied".
VALUE rb_reg_nth_match(int n, VALUE md)
Queries the nth captured substring.
void rb_str_free(VALUE str)
Destroys the given string for no reason.
VALUE rb_str_new_shared(VALUE str)
Identical to rb_str_new_cstr(), except it takes a Ruby's string instead of C's.
VALUE rb_str_plus(VALUE lhs, VALUE rhs)
Generates a new string, concatenating the former to the latter.
#define rb_utf8_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "UTF-8" encoding.
#define rb_hash_end(h)
Just another name of st_hash_end.
#define rb_hash_uint32(h, i)
Just another name of st_hash_uint32.
VALUE rb_str_append(VALUE dst, VALUE src)
Identical to rb_str_buf_append(), except it converts the right hand side before concatenating.
VALUE rb_filesystem_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "filesystem" encoding.
VALUE rb_sym_to_s(VALUE sym)
This is an rb_sym2str() + rb_str_dup() combo.
VALUE rb_str_times(VALUE str, VALUE num)
Repetition of a string.
VALUE rb_external_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "default external" encoding.
VALUE rb_str_tmp_new(long len)
Allocates a "temporary" string.
long rb_str_offset(VALUE str, long pos)
"Inverse" of rb_str_sublen().
VALUE rb_str_succ(VALUE orig)
Searches for the "successor" of a string.
int rb_str_hash_cmp(VALUE str1, VALUE str2)
Compares two strings.
VALUE rb_str_subseq(VALUE str, long beg, long len)
Identical to rb_str_substr(), except the numbers are interpreted as byte offsets instead of character...
VALUE rb_str_ellipsize(VALUE str, long len)
Shortens str and adds three dots, an ellipsis, if it is longer than len characters.
st_index_t rb_memhash(const void *ptr, long len)
This is a universal hash function.
#define rb_str_new(str, len)
Allocates an instance of rb_cString.
void rb_str_shared_replace(VALUE dst, VALUE src)
Replaces the contents of the former with the latter.
#define rb_str_buf_cat
Just another name of rb_str_cat.
VALUE rb_str_new_static(const char *ptr, long len)
Identical to rb_str_new(), except it takes a C string literal.
#define rb_usascii_str_new(str, len)
Identical to rb_str_new, except it generates a string of "US ASCII" encoding.
size_t rb_str_capacity(VALUE str)
Queries the capacity of the given string.
VALUE rb_str_new_frozen(VALUE str)
Creates a frozen copy of the string, if necessary.
VALUE rb_str_dup(VALUE str)
Duplicates a string.
st_index_t rb_str_hash(VALUE str)
Calculates a hash value of a string.
VALUE rb_str_cat(VALUE dst, const char *src, long srclen)
Destructively appends the passed contents to the string.
VALUE rb_str_locktmp(VALUE str)
Obtains a "temporary lock" of the string.
long rb_str_strlen(VALUE str)
Counts the number of characters (not bytes) that are stored inside of the given string.
VALUE rb_str_resurrect(VALUE str)
Like rb_str_dup(), but always create an instance of rb_cString regardless of the given object's class...
#define rb_str_buf_new_cstr(str)
Identical to rb_str_new_cstr, except done differently.
#define rb_usascii_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "US ASCII" encoding.
VALUE rb_str_replace(VALUE dst, VALUE src)
Replaces the contents of the former object with the stringised contents of the latter.
char * rb_str_subpos(VALUE str, long beg, long *len)
Identical to rb_str_substr(), except it returns a C's string instead of Ruby's.
rb_gvar_setter_t rb_str_setter
This is a rb_gvar_setter_t that refutes non-string assignments.
VALUE rb_interned_str_cstr(const char *ptr)
Identical to rb_interned_str(), except it assumes the passed pointer is a pointer to a C's string.
VALUE rb_filesystem_str_new_cstr(const char *ptr)
Identical to rb_filesystem_str_new(), except it assumes the passed pointer is a pointer to a C string...
#define rb_external_str_new_cstr(str)
Identical to rb_str_new_cstr, except it generates a string of "default external" encoding.
VALUE rb_str_buf_append(VALUE dst, VALUE src)
Identical to rb_str_cat_cstr(), except it takes Ruby's string instead of C's.
long rb_str_sublen(VALUE str, long pos)
Byte offset to character offset conversion.
VALUE rb_str_equal(VALUE str1, VALUE str2)
Equality of two strings.
void rb_str_set_len(VALUE str, long len)
Overwrites the length of the string.
VALUE rb_str_inspect(VALUE str)
Generates a "readable" version of the receiver.
void rb_must_asciicompat(VALUE obj)
Asserts that the given string's encoding is (Ruby's definition of) ASCII compatible.
VALUE rb_interned_str(const char *ptr, long len)
Identical to rb_str_new(), except it returns an infamous "f"string.
int rb_str_cmp(VALUE lhs, VALUE rhs)
Compares two strings, as in strcmp(3).
VALUE rb_str_concat(VALUE dst, VALUE src)
Identical to rb_str_append(), except it also accepts an integer as a codepoint.
int rb_str_comparable(VALUE str1, VALUE str2)
Checks if two strings are comparable each other or not.
#define rb_strlen_lit(str)
Length of a string literal.
VALUE rb_str_buf_cat_ascii(VALUE dst, const char *src)
Identical to rb_str_cat_cstr(), except it additionally assumes the source string be a NUL terminated ...
VALUE rb_str_freeze(VALUE str)
This is the implementation of String#freeze.
void rb_str_update(VALUE dst, long beg, long len, VALUE src)
Replaces some (or all) of the contents of the given string.
VALUE rb_str_scrub(VALUE str, VALUE repl)
"Cleanses" the string.
#define rb_locale_str_new_cstr(str)
Identical to rb_external_str_new_cstr, except it generates a string of "locale" encoding instead of "...
VALUE rb_str_new_with_class(VALUE obj, const char *ptr, long len)
Identical to rb_str_new(), except it takes the class of the allocating object.
#define rb_str_dup_frozen
Just another name of rb_str_new_frozen.
VALUE rb_check_string_type(VALUE obj)
Try converting an object to its stringised representation using its to_str method,...
VALUE rb_str_substr(VALUE str, long beg, long len)
This is the implementation of two-argumented String#slice.
#define rb_str_cat_cstr(buf, str)
Identical to rb_str_cat(), except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_unlocktmp(VALUE str)
Releases a lock formerly obtained by rb_str_locktmp().
VALUE rb_utf8_str_new_static(const char *ptr, long len)
Identical to rb_str_new_static(), except it generates a string of "UTF-8" encoding instead of "binary...
#define rb_utf8_str_new(str, len)
Identical to rb_str_new, except it generates a string of "UTF-8" encoding.
void rb_str_modify_expand(VALUE str, long capa)
Identical to rb_str_modify(), except it additionally expands the capacity of the receiver.
VALUE rb_str_dump(VALUE str)
"Inverse" of rb_eval_string().
VALUE rb_locale_str_new(const char *ptr, long len)
Identical to rb_str_new(), except it generates a string of "locale" encoding.
VALUE rb_str_buf_new(long capa)
Allocates a "string buffer".
VALUE rb_str_length(VALUE)
Identical to rb_str_strlen(), except it returns the value in rb_cInteger.
#define rb_str_new_cstr(str)
Identical to rb_str_new, except it assumes the passed pointer is a pointer to a C string.
VALUE rb_str_drop_bytes(VALUE str, long len)
Shrinks the given string for the given number of bytes.
VALUE rb_str_split(VALUE str, const char *delim)
Divides the given string based on the given delimiter.
VALUE rb_usascii_str_new_static(const char *ptr, long len)
Identical to rb_str_new_static(), except it generates a string of "US ASCII" encoding instead of "bin...
VALUE rb_str_intern(VALUE str)
Identical to rb_to_symbol(), except it assumes the receiver being an instance of RString.
VALUE rb_obj_as_string(VALUE obj)
Try converting an object to its stringised representation using its to_s method, if any.
VALUE rb_ivar_set(VALUE obj, ID name, VALUE val)
Identical to rb_iv_set(), except it accepts the name as an ID instead of a C string.
VALUE rb_ivar_defined(VALUE obj, ID name)
Queries if the instance variable is defined at the object.
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
void rb_undef_alloc_func(VALUE klass)
Deletes the allocator function of a class.
void rb_define_alloc_func(VALUE klass, rb_alloc_func_t func)
Sets the allocator function of a class.
static ID rb_intern_const(const char *str)
This is a "tiny optimisation" over rb_intern().
VALUE rb_sym2str(VALUE symbol)
Obtain a frozen string representation of a symbol (not including the leading colon).
VALUE rb_to_symbol(VALUE name)
Identical to rb_intern_str(), except it generates a dynamic symbol if necessary.
ID rb_to_id(VALUE str)
Identical to rb_intern_str(), except it tries to convert the parameter object to an instance of rb_cS...
int capa
Designed capacity of the buffer.
int off
Offset inside of ptr.
int len
Length of the buffer.
#define RB_OBJ_SHAREABLE_P(obj)
Queries if the passed object has previously classified as shareable or not.
long rb_reg_search(VALUE re, VALUE str, long pos, int dir)
Runs the passed regular expression over the passed string.
VALUE rb_reg_regcomp(VALUE str)
Creates a new instance of rb_cRegexp.
VALUE rb_str_format(int argc, const VALUE *argv, VALUE fmt)
Formats a string.
VALUE rb_yield(VALUE val)
Yields the block.
#define MEMCPY(p1, p2, type, n)
Handy macro to call memcpy.
#define ALLOCA_N(type, n)
#define MEMZERO(p, type, n)
Handy macro to erase a region of memory.
#define RB_GC_GUARD(v)
Prevents premature destruction of local objects.
void rb_define_hooked_variable(const char *q, VALUE *w, type *e, void_type *r)
Define a function-backended global variable.
VALUE type(ANYARGS)
ANYARGS-ed function type.
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.
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.